1 //------------------------------------------------------------------------------ 2 // 3 // EchoGals/Echo24 BeOS Driver for Echo audio cards 4 // 5 // Copyright (c) 2003, Jérôme Duval 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a 8 // copy of this software and associated documentation files (the "Software"), 9 // to deal in the Software without restriction, including without limitation 10 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 // and/or sell copies of the Software, and to permit persons to whom the 12 // Software is furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 // DEALINGS IN THE SOFTWARE. 24 25 #include <KernelExport.h> 26 #include <Drivers.h> 27 #include <driver_settings.h> 28 #include <malloc.h> 29 #include <unistd.h> 30 #include "OsSupportBeOS.h" 31 #include "EchoGalsXface.h" 32 #include "C3g.h" 33 #include "CDarla24.h" 34 #include "CDarla.h" 35 #include "CGina.h" 36 #include "CGina24.h" 37 #include "CIndigo.h" 38 #include "CIndigoDJ.h" 39 #include "CIndigoIO.h" 40 #include "CLayla.h" 41 #include "CLayla24.h" 42 #include "CMia.h" 43 #include "CMona.h" 44 #include "echo.h" 45 #include "debug.h" 46 #include "util.h" 47 48 #ifdef CARDBUS 49 static cb_enabler_module_info *cbemi; 50 struct _echodevs devices; 51 static char *names[NUM_CARDS]; 52 int32 num_names = 0; 53 static uint32 device_index = 0; 54 static sem_id device_lock = 0; 55 56 static const cb_device_descriptor descriptors[] = { 57 {VENDOR_ID, DEVICE_ID_56301, 0xff, 0xff, 0xff} 58 }; 59 60 #define COUNT_DESCRIPTOR 1 61 62 status_t cardbus_device_added(pci_info *info, void **cookie); 63 void cardbus_device_removed(void *cookie); 64 65 static cb_notify_hooks cardbus_hooks = { 66 cardbus_device_added, // Add entry point 67 cardbus_device_removed // Remove entry point 68 }; 69 70 #else // CARDBUS 71 static pci_module_info *pci; 72 int32 num_cards; 73 echo_dev cards[NUM_CARDS]; 74 int32 num_names; 75 char * names[NUM_CARDS*20+1]; 76 #endif // CARDBUS 77 78 echo_settings current_settings = { 79 2, // channels 80 16, // bits per sample 81 48000, // sample rate 82 512, // buffer frames 83 2 // buffer count 84 }; 85 86 extern device_hooks multi_hooks; 87 #ifdef MIDI_SUPPORT 88 extern device_hooks midi_hooks; 89 #endif 90 91 int32 echo_int(void *arg); 92 status_t init_hardware(void); 93 status_t init_driver(void); 94 static void make_device_names(echo_dev * card); 95 96 static status_t echo_setup(echo_dev * card); 97 static void echo_shutdown(echo_dev *card); 98 99 void uninit_driver(void); 100 const char ** publish_devices(void); 101 device_hooks * find_device(const char * name); 102 103 104 /* Echo Memory management */ 105 106 echo_mem * 107 echo_mem_new(echo_dev *card, size_t size) 108 { 109 echo_mem *mem; 110 111 if ((mem = (echo_mem *) malloc(sizeof(*mem))) == NULL) 112 return (NULL); 113 114 mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "echo buffer"); 115 mem->size = size; 116 if (mem->area < B_OK) { 117 free(mem); 118 return NULL; 119 } 120 return mem; 121 } 122 123 void 124 echo_mem_delete(echo_mem *mem) 125 { 126 if (mem->area > B_OK) 127 delete_area(mem->area); 128 free(mem); 129 } 130 131 echo_mem * 132 echo_mem_alloc(echo_dev *card, size_t size) 133 { 134 echo_mem *mem; 135 136 mem = echo_mem_new(card, size); 137 if (mem == NULL) 138 return (NULL); 139 140 LIST_INSERT_HEAD(&(card->mems), mem, next); 141 142 return mem; 143 } 144 145 void 146 echo_mem_free(echo_dev *card, void *ptr) 147 { 148 echo_mem *mem; 149 150 LIST_FOREACH(mem, &card->mems, next) { 151 if (mem->log_base != ptr) 152 continue; 153 LIST_REMOVE(mem, next); 154 155 echo_mem_delete(mem); 156 break; 157 } 158 } 159 160 /* Echo stream functions */ 161 162 extern char *pStatusStrs[ECHOSTATUS_LAST]; 163 164 status_t 165 echo_stream_set_audioparms(echo_stream *stream, uint8 channels, 166 uint8 bitsPerSample, uint32 sample_rate, uint8 index) 167 { 168 int32 i; 169 uint8 sample_size, frame_size; 170 ECHOGALS_OPENAUDIOPARAMETERS open_params; 171 ECHOGALS_CLOSEAUDIOPARAMETERS close_params; 172 ECHOGALS_AUDIOFORMAT format_params; 173 ECHOSTATUS status; 174 175 LOG(("echo_stream_set_audioparms\n")); 176 177 if (stream->pipe >= 0) { 178 close_params.wPipeIndex = stream->pipe; 179 status = stream->card->pEG->CloseAudio(&close_params); 180 if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) { 181 PRINT(("echo_stream_set_audioparms : CloseAudio failed\n")); 182 PRINT((" status: %s \n", pStatusStrs[status])); 183 return B_ERROR; 184 } 185 } 186 187 open_params.bIsCyclic = TRUE; 188 open_params.Pipe.nPipe = index; 189 open_params.Pipe.bIsInput = stream->use == ECHO_USE_RECORD ? TRUE : FALSE; 190 open_params.Pipe.wInterleave = channels; 191 open_params.ProcessId = NULL; 192 193 status = stream->card->pEG->OpenAudio(&open_params, &stream->pipe); 194 if (status != ECHOSTATUS_OK) { 195 PRINT(("echo_stream_set_audioparms : OpenAudio failed\n")); 196 PRINT((" status: %s \n", pStatusStrs[status])); 197 return B_ERROR; 198 } 199 200 //PRINT(("VerifyAudioOpen\n")); 201 status = stream->card->pEG->VerifyAudioOpen(stream->pipe); 202 if (status != ECHOSTATUS_OK) { 203 PRINT(("echo_stream_set_audioparms : VerifyAudioOpen failed\n")); 204 PRINT((" status: %s \n", pStatusStrs[status])); 205 return B_ERROR; 206 } 207 208 if ((stream->channels == channels) && 209 (stream->bitsPerSample == bitsPerSample) && 210 (stream->sample_rate == sample_rate)) 211 return B_OK; 212 213 format_params.wBitsPerSample = bitsPerSample; 214 format_params.byDataAreBigEndian = 0; 215 format_params.byMonoToStereo = 0; 216 format_params.wDataInterleave = channels == 1 ? 1 : 2; 217 218 status = stream->card->pEG->QueryAudioFormat(stream->pipe, &format_params); 219 if (status != ECHOSTATUS_OK) { 220 PRINT(("echo_stream_set_audioparms : bad format when querying\n")); 221 PRINT((" status: %s \n", pStatusStrs[status])); 222 return B_ERROR; 223 } 224 225 status = stream->card->pEG->SetAudioFormat(stream->pipe, &format_params); 226 if (status != ECHOSTATUS_OK) { 227 PRINT(("echo_stream_set_audioparms : bad format when setting\n")); 228 PRINT((" status: %s \n", pStatusStrs[status])); 229 return B_ERROR; 230 } 231 232 /* XXXX : setting sample rate is global in this driver */ 233 status = stream->card->pEG->QueryAudioSampleRate(sample_rate); 234 if (status != ECHOSTATUS_OK) { 235 PRINT(("echo_stream_set_audioparms : bad sample rate when querying\n")); 236 PRINT((" status: %s \n", pStatusStrs[status])); 237 return B_ERROR; 238 } 239 240 /* XXXX : setting sample rate is global in this driver */ 241 status = stream->card->pEG->SetAudioSampleRate(sample_rate); 242 if (status != ECHOSTATUS_OK) { 243 PRINT(("echo_stream_set_audioparms : bad sample rate when setting\n")); 244 PRINT((" status: %s \n", pStatusStrs[status])); 245 return B_ERROR; 246 } 247 248 if (stream->buffer) 249 echo_mem_free(stream->card, stream->buffer->log_base); 250 251 stream->bitsPerSample = bitsPerSample; 252 stream->sample_rate = sample_rate; 253 stream->channels = channels; 254 255 sample_size = stream->bitsPerSample / 8; 256 frame_size = sample_size * stream->channels; 257 258 stream->buffer = echo_mem_alloc(stream->card, stream->bufframes * frame_size * stream->bufcount); 259 260 stream->trigblk = 1; 261 stream->blkmod = stream->bufcount; 262 stream->blksize = stream->bufframes * frame_size; 263 264 CDaffyDuck *duck = stream->card->pEG->GetDaffyDuck(stream->pipe); 265 if (duck == NULL) { 266 PRINT(("echo_stream_set_audioparms : Could not get daffy duck pointer\n")); 267 return B_ERROR; 268 } 269 270 uint32 dwNumFreeEntries = 0; 271 272 for (i=0; i<stream->bufcount; i++) { 273 duck->AddMapping(((uint32)stream->buffer->phy_base) + 274 i * stream->blksize, stream->blksize, 0, TRUE, dwNumFreeEntries); 275 } 276 277 duck->Wrap(); 278 279 if (stream->card->pEG->GetAudioPositionPtr(stream->pipe, stream->position)!=ECHOSTATUS_OK) { 280 PRINT(("echo_stream_set_audioparms : Could not get audio position ptr\n")); 281 return B_ERROR; 282 } 283 284 return B_OK; 285 } 286 287 288 status_t 289 echo_stream_get_nth_buffer(echo_stream *stream, uint8 chan, uint8 buf, 290 char** buffer, size_t *stride) 291 { 292 uint8 sample_size, frame_size; 293 LOG(("echo_stream_get_nth_buffer\n")); 294 295 sample_size = stream->bitsPerSample / 8; 296 frame_size = sample_size * stream->channels; 297 298 *buffer = (char*)stream->buffer->log_base + (buf * stream->bufframes * frame_size) 299 + chan * sample_size; 300 *stride = frame_size; 301 302 return B_OK; 303 } 304 305 306 static uint32 307 echo_stream_curaddr(echo_stream *stream) 308 { 309 uint32 addr = B_LENDIAN_TO_HOST_INT32(*stream->position); 310 // TRACE(("stream_curaddr %p, phy_base %p\n", addr)); 311 return (addr / stream->blksize) % stream->blkmod; 312 } 313 314 315 void 316 echo_stream_start(echo_stream *stream, void (*inth) (void *), void *inthparam) 317 { 318 LOG(("echo_stream_start\n")); 319 ECHOSTATUS status; 320 321 stream->inth = inth; 322 stream->inthparam = inthparam; 323 324 stream->state |= ECHO_STATE_STARTED; 325 326 status = stream->card->pEG->Start(stream->pipe); 327 if (status!=ECHOSTATUS_OK) { 328 PRINT(("echo_stream_start : Could not start the pipe %s\n", pStatusStrs[status])); 329 } 330 } 331 332 void 333 echo_stream_halt(echo_stream *stream) 334 { 335 LOG(("echo_stream_halt\n")); 336 ECHOSTATUS status; 337 338 stream->state &= ~ECHO_STATE_STARTED; 339 340 status = stream->card->pEG->Stop(stream->pipe); 341 if (status!=ECHOSTATUS_OK) { 342 PRINT(("echo_stream_halt : Could not stop the pipe %s\n", pStatusStrs[status])); 343 } 344 } 345 346 echo_stream * 347 echo_stream_new(echo_dev *card, uint8 use, uint32 bufframes, uint8 bufcount) 348 { 349 echo_stream *stream; 350 cpu_status status; 351 LOG(("echo_stream_new\n")); 352 353 stream = (echo_stream *) malloc(sizeof(echo_stream)); 354 if (stream == NULL) 355 return (NULL); 356 stream->card = card; 357 stream->use = use; 358 stream->state = !ECHO_STATE_STARTED; 359 stream->bitsPerSample = 0; 360 stream->sample_rate = 0; 361 stream->channels = 0; 362 stream->bufframes = bufframes; 363 stream->bufcount = bufcount; 364 stream->inth = NULL; 365 stream->inthparam = NULL; 366 stream->buffer = NULL; 367 stream->blksize = 0; 368 stream->trigblk = 0; 369 stream->blkmod = 0; 370 371 stream->pipe = -1; 372 373 stream->frames_count = 0; 374 stream->real_time = 0; 375 stream->buffer_cycle = 0; 376 stream->update_needed = false; 377 378 status = lock(); 379 LIST_INSERT_HEAD((&card->streams), stream, next); 380 unlock(status); 381 382 return stream; 383 } 384 385 void 386 echo_stream_delete(echo_stream *stream) 387 { 388 cpu_status status; 389 ECHOGALS_CLOSEAUDIOPARAMETERS close_params; 390 LOG(("echo_stream_delete\n")); 391 392 echo_stream_halt(stream); 393 394 if (stream->pipe >= 0) { 395 close_params.wPipeIndex = stream->pipe; 396 status = stream->card->pEG->CloseAudio(&close_params); 397 if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) { 398 PRINT(("echo_stream_set_audioparms : CloseAudio failed\n")); 399 PRINT((" status: %s \n", pStatusStrs[status])); 400 } 401 } 402 403 if (stream->buffer) 404 echo_mem_free(stream->card, stream->buffer->log_base); 405 406 status = lock(); 407 LIST_REMOVE(stream, next); 408 unlock(status); 409 410 free(stream); 411 } 412 413 414 /* Echo interrupt */ 415 416 int32 echo_int(void *arg) 417 { 418 echo_dev* card = (echo_dev*)arg; 419 BOOL midiReceived; 420 ECHOSTATUS err; 421 echo_stream* stream; 422 uint32 curblk; 423 424 err = card->pEG->ServiceIrq(midiReceived); 425 426 if (err != ECHOSTATUS_OK) { 427 return B_UNHANDLED_INTERRUPT; 428 } 429 430 #ifdef MIDI_SUPPORT 431 if (midiReceived) 432 release_sem_etc(card->midi.midi_ready_sem, 1, B_DO_NOT_RESCHEDULE); 433 #endif 434 435 LIST_FOREACH(stream, &card->streams, next) { 436 if ((stream->state & ECHO_STATE_STARTED) == 0 || 437 (stream->inth == NULL)) 438 continue; 439 440 curblk = echo_stream_curaddr(stream); 441 //TRACE(("echo_int stream %p at trigblk %lu at stream->trigblk %lu\n", 442 // stream, curblk, stream->trigblk)); 443 if (curblk == stream->trigblk) { 444 if (stream->inth) 445 stream->inth(stream->inthparam); 446 447 stream->trigblk++; 448 stream->trigblk %= stream->blkmod; 449 } 450 } 451 452 return B_INVOKE_SCHEDULER; 453 } 454 455 /* dumps card capabilities */ 456 void 457 echo_dump_caps(echo_dev *card) 458 { 459 PECHOGALS_CAPS caps = &card->caps; 460 PRINT(("name: %s\n", caps->szName)); 461 PRINT(("out pipes: %d, in pipes: %d, out busses: %d, in busses: %d, out midi: %d, in midi: %d\n", 462 caps->wNumPipesOut, caps->wNumPipesIn, caps->wNumBussesOut, caps->wNumBussesIn, caps->wNumMidiOut, caps->wNumMidiIn)); 463 464 } 465 466 467 /* detect presence of our hardware */ 468 status_t 469 init_hardware(void) 470 { 471 #ifdef CARDBUS 472 return B_OK; 473 #else 474 int ix=0; 475 pci_info info; 476 status_t err = ENODEV; 477 478 LOG_CREATE(); 479 480 PRINT(("init_hardware()\n")); 481 482 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) 483 return ENOSYS; 484 485 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 486 487 ushort card_type = info.u.h0.subsystem_id & 0xfff0; 488 489 if (info.vendor_id == VENDOR_ID && 490 ((info.device_id == DEVICE_ID_56301) 491 || (info.device_id == DEVICE_ID_56361)) && 492 (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID) && 493 ( 494 #ifdef ECHOGALS_FAMILY 495 (card_type == DARLA) 496 || (card_type == GINA) 497 || (card_type == LAYLA) 498 || (card_type == DARLA24) 499 #endif 500 #ifdef ECHO24_FAMILY 501 (card_type == GINA24) 502 || (card_type == LAYLA24) 503 || (card_type == MONA) 504 || (card_type == MIA) 505 #endif 506 #ifdef INDIGO_FAMILY 507 (card_type == INDIGO) 508 || (card_type == INDIGO_IO) 509 || (card_type == INDIGO_DJ) 510 #endif 511 #ifdef ECHO3G_FAMILY 512 (card_type == ECHO3G) 513 #endif 514 )) { 515 err = B_OK; 516 } 517 ix++; 518 } 519 520 put_module(B_PCI_MODULE_NAME); 521 522 if (err != B_OK) { 523 PRINT(("no card found\n")); 524 } 525 526 return err; 527 #endif 528 } 529 530 531 status_t 532 init_driver(void) 533 { 534 PRINT(("init_driver()\n")); 535 536 void *settings_handle; 537 // get driver settings 538 settings_handle = load_driver_settings ("echo.settings"); 539 if (settings_handle != NULL) { 540 const char* item; 541 char* end; 542 uint32 value; 543 544 item = get_driver_parameter (settings_handle, "channels", NULL, NULL); 545 if (item) { 546 value = strtoul (item, &end, 0); 547 if (*end == '\0') current_settings.channels = value; 548 } 549 PRINT(("channels %lu\n", current_settings.channels)); 550 551 item = get_driver_parameter (settings_handle, "bitsPerSample", NULL, NULL); 552 if (item) { 553 value = strtoul (item, &end, 0); 554 if (*end == '\0') current_settings.bitsPerSample = value; 555 } 556 PRINT(("bitsPerSample %lu\n", current_settings.bitsPerSample)); 557 558 item = get_driver_parameter (settings_handle, "sample_rate", NULL, NULL); 559 if (item) { 560 value = strtoul (item, &end, 0); 561 if (*end == '\0') current_settings.sample_rate = value; 562 } 563 PRINT(("sample_rate %lu\n", current_settings.sample_rate)); 564 565 item = get_driver_parameter (settings_handle, "buffer_frames", NULL, NULL); 566 if (item) { 567 value = strtoul (item, &end, 0); 568 if (*end == '\0') current_settings.buffer_frames = value; 569 } 570 PRINT(("buffer_frames %lu\n", current_settings.buffer_frames)); 571 572 item = get_driver_parameter (settings_handle, "buffer_count", NULL, NULL); 573 if (item) { 574 value = strtoul (item, &end, 0); 575 if (*end == '\0') current_settings.buffer_count = value; 576 } 577 PRINT(("buffer_count %lu\n", current_settings.buffer_count)); 578 579 unload_driver_settings (settings_handle); 580 } 581 582 #ifdef CARDBUS 583 // Get card services client module 584 if (get_module(CB_ENABLER_MODULE_NAME, (module_info **)&cbemi) != B_OK) { 585 dprintf(DRIVER_NAME ": cardbus enabler module error\n"); 586 return B_ERROR; 587 } 588 // Create the devices lock 589 device_lock = create_sem(1, DRIVER_NAME " device"); 590 if (device_lock < B_OK) { 591 dprintf(DRIVER_NAME ": create device semaphore error 0x%.8x\n", device_lock); 592 put_module(CB_ENABLER_MODULE_NAME); 593 return B_ERROR; 594 } 595 // Register driver 596 cbemi->register_driver(DRIVER_NAME, descriptors, COUNT_DESCRIPTOR); 597 cbemi->install_notify(DRIVER_NAME, &cardbus_hooks); 598 LIST_INIT(&(devices)); 599 return B_OK; 600 #else 601 int ix=0; 602 603 pci_info info; 604 num_cards = 0; 605 606 if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) 607 return ENOSYS; 608 609 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 610 ushort card_type = info.u.h0.subsystem_id & 0xfff0; 611 612 if (info.vendor_id == VENDOR_ID && 613 ((info.device_id == DEVICE_ID_56301) 614 || (info.device_id == DEVICE_ID_56361)) && 615 (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID) && 616 ( 617 #ifdef ECHOGALS_FAMILY 618 (card_type == DARLA) 619 || (card_type == GINA) 620 || (card_type == LAYLA) 621 || (card_type == DARLA24) 622 #endif 623 #ifdef ECHO24_FAMILY 624 (card_type == GINA24) 625 || (card_type == LAYLA24) 626 || (card_type == MONA) 627 || (card_type == MIA) 628 #endif 629 #ifdef INDIGO_FAMILY 630 (card_type == INDIGO) 631 || (card_type == INDIGO_IO) 632 || (card_type == INDIGO_DJ) 633 #endif 634 #ifdef ECHO3G_FAMILY 635 (card_type == ECHO3G) 636 #endif 637 )) { 638 639 if (num_cards == NUM_CARDS) { 640 PRINT(("Too many "DRIVER_NAME" cards installed!\n")); 641 break; 642 } 643 memset(&cards[num_cards], 0, sizeof(echo_dev)); 644 cards[num_cards].info = info; 645 cards[num_cards].type = card_type; 646 if (echo_setup(&cards[num_cards])) { 647 PRINT(("Setup of "DRIVER_NAME" %ld failed\n", num_cards+1)); 648 } 649 else { 650 num_cards++; 651 } 652 } 653 ix++; 654 } 655 if (!num_cards) { 656 PRINT(("no cards\n")); 657 put_module(B_PCI_MODULE_NAME); 658 PRINT(("no suitable cards found\n")); 659 return ENODEV; 660 } 661 662 return B_OK; 663 #endif 664 } 665 666 667 #ifndef CARDBUS 668 static void 669 make_device_names( 670 echo_dev * card) 671 { 672 #ifdef MIDI_SUPPORT 673 sprintf(card->midi.name, "midi/"DRIVER_NAME"/%ld", card-cards+1); 674 names[num_names++] = card->midi.name; 675 #endif 676 sprintf(card->name, "audio/hmulti/"DRIVER_NAME"/%ld", card-cards+1); 677 names[num_names++] = card->name; 678 679 names[num_names] = NULL; 680 } 681 #else 682 683 status_t 684 cardbus_device_added(pci_info *info, void **cookie) { 685 echo_dev * card, *dev; 686 uint32 index; 687 char buffer[32]; 688 689 LOG(("cardbus_device_added at %.2d:%.2d:%.2d\n", info->bus, info->device, info->function)); 690 // Allocate cookie 691 if (!(*cookie = card = (echo_dev *)malloc(sizeof(echo_dev)))) { 692 return B_NO_MEMORY; 693 } 694 // Clear cookie 695 memset(card, 0, sizeof(echo_dev)); 696 // Initialize cookie 697 card->info = *info; 698 card->plugged = true; 699 card->index = 0; 700 701 LIST_FOREACH(dev, &devices, next) { 702 if (dev->index == card->index) { 703 card->index++; 704 dev = LIST_FIRST(&devices); 705 } 706 } 707 708 // Format device name 709 sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card->index); 710 // Lock the devices 711 acquire_sem(device_lock); 712 LIST_INSERT_HEAD((&devices), card, next); 713 // Unlock the devices 714 release_sem(device_lock); 715 716 echo_setup(card); 717 return B_OK; 718 } 719 720 721 // cardbus_device_removed - handle cardbus device removal. 722 // status : OK 723 void 724 cardbus_device_removed(void *cookie) 725 { 726 echo_dev *card = (echo_dev *) cookie; 727 728 LOG((": cardbus_device_removed\n")); 729 // Check 730 if (card == NULL) { 731 LOG((": null device 0x%.8x\n", card)); 732 return; 733 } 734 735 echo_shutdown(card); 736 737 // Lock the devices 738 acquire_sem(device_lock); 739 // Finalize 740 card->plugged = false; 741 // Check if the device is opened 742 if (card->opened) { 743 LOG(("device 0x%.8x %s still in use\n", card, card->name)); 744 } else { 745 LOG(("free device 0x%.8x %s\n", card, card->name)); 746 LIST_REMOVE(card, next); 747 free(card); 748 } 749 // Unlock the devices 750 release_sem(device_lock); 751 } 752 753 #endif 754 755 756 static status_t 757 echo_setup(echo_dev * card) 758 { 759 status_t err = B_OK; 760 unsigned char cmd; 761 char *name; 762 763 PRINT(("echo_setup(%p)\n", card)); 764 765 #ifndef CARDBUS 766 (*pci->write_pci_config)(card->info.bus, card->info.device, card->info.function, 767 PCI_latency, 1, 0xc0 ); 768 769 make_device_names(card); 770 #endif 771 card->bmbar = card->info.u.h0.base_registers[0]; 772 card->irq = card->info.u.h0.interrupt_line; 773 774 775 card->pOSS = new COsSupport(card->info.device_id, card->info.revision); 776 if (card->pOSS == NULL) 777 return B_ERROR; 778 779 switch (card->type) { 780 #ifdef ECHOGALS_FAMILY 781 case DARLA: 782 card->pEG = new CDarla(card->pOSS); 783 name = "Echo Darla"; 784 break; 785 case GINA: 786 card->pEG = new CGina(card->pOSS); 787 name = "Echo Gina"; 788 break; 789 case LAYLA: 790 card->pEG = new CLayla(card->pOSS); 791 name = "Echo Layla"; 792 break; 793 case DARLA24: 794 card->pEG = new CDarla24(card->pOSS); 795 name = "Echo Darla24"; 796 break; 797 #endif 798 #ifdef ECHO24_FAMILY 799 case GINA24: 800 card->pEG = new CGina24(card->pOSS); 801 name = "Echo Gina24"; 802 break; 803 case LAYLA24: 804 card->pEG = new CLayla24(card->pOSS); 805 name = "Echo Layla24"; 806 break; 807 case MONA: 808 card->pEG = new CMona(card->pOSS); 809 name = "Echo Mona"; 810 break; 811 case MIA: 812 card->pEG = new CMia(card->pOSS); 813 name = "Echo Mia"; 814 break; 815 #endif 816 #ifdef INDIGO_FAMILY 817 case INDIGO: 818 card->pEG = new CIndigo(card->pOSS); 819 name = "Echo Indigo"; 820 break; 821 case INDIGO_IO: 822 card->pEG = new CIndigoIO(card->pOSS); 823 name = "Echo IndigoIO"; 824 break; 825 case INDIGO_DJ: 826 card->pEG = new CIndigoDJ(card->pOSS); 827 name = "Echo IndigoDJ"; 828 break; 829 #endif 830 #ifdef ECHO3G_FAMILY 831 case ECHO3G: 832 card->pEG = new C3g(card->pOSS); 833 name = "Echo 3g"; 834 break; 835 #endif 836 default: 837 PRINT(("card type 0x%x not supported by "DRIVER_NAME"\n", card->type)); 838 delete card->pOSS; 839 return B_ERROR; 840 } 841 842 if (card->pEG == NULL) 843 return B_ERROR; 844 845 card->area_bmbar = map_mem(&card->log_bmbar, (void *)card->bmbar, 846 card->info.u.h0.base_register_sizes[0], DRIVER_NAME" bmbar io"); 847 if (card->area_bmbar <= B_OK) { 848 LOG(("mapping of bmbar io failed, error = %#x\n",card->area_bmbar)); 849 return B_ERROR; 850 } 851 LOG(("mapping of bmbar: area %#x, phys %#x, log %#x\n", card->area_bmbar, card->bmbar, card->log_bmbar)); 852 853 #ifndef CARDBUS 854 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2); 855 PRINT(("PCI command before: %x\n", cmd)); 856 (*pci->write_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2, cmd | PCI_command_io); 857 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2); 858 PRINT(("PCI command after: %x\n", cmd)); 859 #endif 860 861 card->pEG->AssignResources(card->log_bmbar, name); 862 863 ECHOSTATUS status; 864 status = card->pEG->InitHw(); 865 if (status != ECHOSTATUS_OK) 866 return B_ERROR; 867 868 card->pEG->GetCapabilities(&card->caps); 869 870 /* Init streams list */ 871 LIST_INIT(&(card->streams)); 872 873 /* Init mems list */ 874 LIST_INIT(&(card->mems)); 875 876 #ifdef MIDI_SUPPORT 877 card->midi.midi_ready_sem = create_sem(0, "midi sem"); 878 #endif 879 880 PRINT(("installing interrupt : %x\n", card->irq)); 881 install_io_interrupt_handler(card->irq, echo_int, card, 0); 882 883 PRINT(("echo_setup done\n")); 884 885 echo_dump_caps(card); 886 887 #ifdef ECHO3G_FAMILY 888 if (card->type == ECHO3G) { 889 strncpy(card->caps.szName, ((C3g*)card->pEG)->Get3gBoxName(), ECHO_MAXNAMELEN); 890 } 891 #endif 892 893 status = card->pEG->OpenMixer(card->mixer); 894 if (status != ECHOSTATUS_OK) 895 return B_ERROR; 896 897 return err; 898 } 899 900 static void 901 echo_shutdown(echo_dev *card) 902 { 903 ECHOSTATUS status; 904 905 PRINT(("shutdown(%p)\n", card)); 906 status = card->pEG->CloseMixer(card->mixer); 907 if (status != ECHOSTATUS_OK) 908 PRINT(("echo_shutdown: error when CloseMixer\n")); 909 910 remove_io_interrupt_handler(card->irq, echo_int, card); 911 912 #ifdef MIDI_SUPPORT 913 delete_sem(card->midi.midi_ready_sem); 914 #endif 915 916 delete card->pEG; 917 delete card->pOSS; 918 919 delete_area(card->area_bmbar); 920 } 921 922 923 924 void 925 uninit_driver(void) 926 { 927 PRINT(("uninit_driver()\n")); 928 929 #ifdef CARDBUS 930 echo_dev *dev; 931 932 LIST_FOREACH(dev, &devices, next) { 933 echo_shutdown(dev); 934 } 935 put_module(CB_ENABLER_MODULE_NAME); 936 #else 937 int ix, cnt = num_cards; 938 num_cards = 0; 939 for (ix=0; ix<cnt; ix++) { 940 echo_shutdown(&cards[ix]); 941 } 942 943 memset(&cards, 0, sizeof(cards)); 944 put_module(B_PCI_MODULE_NAME); 945 #endif 946 } 947 948 949 const char ** 950 publish_devices(void) 951 { 952 #ifdef CARDBUS 953 echo_dev *dev; 954 int ix = 0; 955 956 // Lock the devices 957 acquire_sem(device_lock); 958 // Loop 959 LIST_FOREACH(dev, &devices, next) { 960 if (dev->plugged == true) { 961 names[ix] = dev->name; 962 ix++; 963 } 964 } 965 names[ix] = NULL; 966 release_sem(device_lock); 967 #else 968 int ix = 0; 969 PRINT(("publish_devices()\n")); 970 971 for (ix=0; names[ix]; ix++) { 972 PRINT(("publish %s\n", names[ix])); 973 } 974 #endif 975 return (const char **)names; 976 } 977 978 979 device_hooks * 980 find_device(const char * name) 981 { 982 echo_dev *dev; 983 #ifdef CARDBUS 984 LIST_FOREACH(dev, &devices, next) { 985 if (!strcmp(dev->name, name)) { 986 return &multi_hooks; 987 } 988 } 989 990 #else 991 int ix; 992 993 PRINT(("find_device(%s)\n", name)); 994 995 for (ix=0; ix<num_cards; ix++) { 996 #ifdef MIDI_SUPPORT 997 if (!strcmp(cards[ix].midi.name, name)) { 998 return &midi_hooks; 999 } 1000 #endif 1001 if (!strcmp(cards[ix].name, name)) { 1002 return &multi_hooks; 1003 } 1004 } 1005 #endif 1006 PRINT(("find_device(%s) failed\n", name)); 1007 return NULL; 1008 } 1009 1010 int32 api_version = B_CUR_DRIVER_API_VERSION; 1011