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