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", true); 105 mem->size = size; 106 if (mem->area < B_OK) { 107 free(mem); 108 return NULL; 109 } 110 return mem; 111 } 112 113 114 void 115 echo_mem_delete(echo_mem *mem) 116 { 117 if (mem->area > B_OK) 118 delete_area(mem->area); 119 free(mem); 120 } 121 122 123 echo_mem * 124 echo_mem_alloc(echo_dev *card, size_t size) 125 { 126 echo_mem *mem; 127 128 mem = echo_mem_new(card, size); 129 if (mem == NULL) 130 return (NULL); 131 132 LIST_INSERT_HEAD(&(card->mems), mem, next); 133 134 return mem; 135 } 136 137 138 void 139 echo_mem_free(echo_dev *card, void *ptr) 140 { 141 echo_mem *mem; 142 143 LIST_FOREACH(mem, &card->mems, next) { 144 if (mem->log_base != ptr) 145 continue; 146 LIST_REMOVE(mem, next); 147 148 echo_mem_delete(mem); 149 break; 150 } 151 } 152 153 /* Echo stream functions */ 154 155 extern char *pStatusStrs[ECHOSTATUS_LAST]; 156 157 status_t 158 echo_stream_set_audioparms(echo_stream *stream, uint8 channels, 159 uint8 bitsPerSample, uint32 sample_rate, uint8 index) 160 { 161 int32 i; 162 uint8 sample_size, frame_size; 163 ECHOGALS_OPENAUDIOPARAMETERS open_params; 164 ECHOGALS_CLOSEAUDIOPARAMETERS close_params; 165 ECHOGALS_AUDIOFORMAT format_params; 166 ECHOSTATUS status; 167 168 LOG(("echo_stream_set_audioparms\n")); 169 170 if (stream->pipe >= 0) { 171 close_params.wPipeIndex = stream->pipe; 172 status = stream->card->pEG->CloseAudio(&close_params); 173 if (status != ECHOSTATUS_OK && status != ECHOSTATUS_CHANNEL_NOT_OPEN) { 174 PRINT(("echo_stream_set_audioparms : CloseAudio failed\n")); 175 PRINT((" status: %s \n", pStatusStrs[status])); 176 return B_ERROR; 177 } 178 } 179 180 open_params.bIsCyclic = TRUE; 181 open_params.Pipe.nPipe = index; 182 open_params.Pipe.bIsInput = stream->use == ECHO_USE_RECORD ? TRUE : FALSE; 183 open_params.Pipe.wInterleave = channels; 184 open_params.ProcessId = NULL; 185 186 status = stream->card->pEG->OpenAudio(&open_params, &stream->pipe); 187 if (status != ECHOSTATUS_OK) { 188 PRINT(("echo_stream_set_audioparms : OpenAudio failed\n")); 189 PRINT((" status: %s \n", pStatusStrs[status])); 190 return B_ERROR; 191 } 192 193 //PRINT(("VerifyAudioOpen\n")); 194 status = stream->card->pEG->VerifyAudioOpen(stream->pipe); 195 if (status != ECHOSTATUS_OK) { 196 PRINT(("echo_stream_set_audioparms : VerifyAudioOpen failed\n")); 197 PRINT((" status: %s \n", pStatusStrs[status])); 198 return B_ERROR; 199 } 200 201 if (bitsPerSample == 24) 202 bitsPerSample = 32; 203 204 if ((stream->channels == channels) 205 && (stream->bitsPerSample == bitsPerSample) 206 && (stream->sample_rate == sample_rate)) 207 return B_OK; 208 209 format_params.wBitsPerSample = bitsPerSample; 210 format_params.byDataAreBigEndian = 0; 211 format_params.byMonoToStereo = 0; 212 format_params.wDataInterleave = channels == 1 ? 1 : 2; 213 214 status = stream->card->pEG->QueryAudioFormat(stream->pipe, &format_params); 215 if (status != ECHOSTATUS_OK) { 216 PRINT(("echo_stream_set_audioparms : bad format when querying\n")); 217 PRINT((" status: %s \n", pStatusStrs[status])); 218 return B_ERROR; 219 } 220 221 status = stream->card->pEG->SetAudioFormat(stream->pipe, &format_params); 222 if (status != ECHOSTATUS_OK) { 223 PRINT(("echo_stream_set_audioparms : bad format when setting\n")); 224 PRINT((" status: %s \n", pStatusStrs[status])); 225 return B_ERROR; 226 } 227 228 /* XXXX : setting sample rate is global in this driver */ 229 status = stream->card->pEG->QueryAudioSampleRate(sample_rate); 230 if (status != ECHOSTATUS_OK) { 231 PRINT(("echo_stream_set_audioparms : bad sample rate when querying\n")); 232 PRINT((" status: %s \n", pStatusStrs[status])); 233 return B_ERROR; 234 } 235 236 /* XXXX : setting sample rate is global in this driver */ 237 status = stream->card->pEG->SetAudioSampleRate(sample_rate); 238 if (status != ECHOSTATUS_OK) { 239 PRINT(("echo_stream_set_audioparms : bad sample rate when setting\n")); 240 PRINT((" status: %s \n", pStatusStrs[status])); 241 return B_ERROR; 242 } 243 244 if (stream->buffer) 245 echo_mem_free(stream->card, stream->buffer->log_base); 246 247 stream->bitsPerSample = bitsPerSample; 248 stream->sample_rate = sample_rate; 249 stream->channels = channels; 250 251 sample_size = stream->bitsPerSample / 8; 252 frame_size = sample_size * stream->channels; 253 254 stream->buffer = echo_mem_alloc(stream->card, 255 stream->bufframes * frame_size * stream->bufcount); 256 257 stream->trigblk = 1; 258 stream->blkmod = stream->bufcount; 259 stream->blksize = stream->bufframes * frame_size; 260 261 CDaffyDuck *duck = stream->card->pEG->GetDaffyDuck(stream->pipe); 262 if (duck == NULL) { 263 PRINT(("echo_stream_set_audioparms : Could not get daffy duck pointer\n")); 264 return B_ERROR; 265 } 266 267 uint32 dwNumFreeEntries = 0; 268 269 for (i = 0; i < stream->bufcount; i++) { 270 duck->AddMapping(((uint32)stream->buffer->phy_base) + 271 i * stream->blksize, stream->blksize, 0, TRUE, dwNumFreeEntries); 272 } 273 274 duck->Wrap(); 275 276 if (stream->card->pEG->GetAudioPositionPtr(stream->pipe, stream->position)!=ECHOSTATUS_OK) { 277 PRINT(("echo_stream_set_audioparms : Could not get audio position ptr\n")); 278 return B_ERROR; 279 } 280 281 return B_OK; 282 } 283 284 285 status_t 286 echo_stream_get_nth_buffer(echo_stream *stream, uint8 chan, uint8 buf, 287 char** buffer, size_t *stride) 288 { 289 uint8 sample_size, frame_size; 290 LOG(("echo_stream_get_nth_buffer\n")); 291 292 sample_size = stream->bitsPerSample / 8; 293 frame_size = sample_size * stream->channels; 294 295 *buffer = (char*)stream->buffer->log_base + (buf * stream->bufframes * frame_size) 296 + chan * sample_size; 297 *stride = frame_size; 298 299 return B_OK; 300 } 301 302 303 static uint32 304 echo_stream_curaddr(echo_stream *stream) 305 { 306 uint32 addr = B_LENDIAN_TO_HOST_INT32(*stream->position); 307 // TRACE(("stream_curaddr %p, phy_base %p\n", addr)); 308 return (addr / stream->blksize) % stream->blkmod; 309 } 310 311 312 void 313 echo_stream_start(echo_stream *stream, void (*inth) (void *), void *inthparam) 314 { 315 LOG(("echo_stream_start\n")); 316 ECHOSTATUS status; 317 318 stream->inth = inth; 319 stream->inthparam = inthparam; 320 321 stream->state |= ECHO_STATE_STARTED; 322 323 status = stream->card->pEG->Start(stream->pipe); 324 if (status!=ECHOSTATUS_OK) { 325 PRINT(("echo_stream_start : Could not start the pipe %s\n", pStatusStrs[status])); 326 } 327 } 328 329 330 void 331 echo_stream_halt(echo_stream *stream) 332 { 333 LOG(("echo_stream_halt\n")); 334 ECHOSTATUS status; 335 336 stream->state &= ~ECHO_STATE_STARTED; 337 338 status = stream->card->pEG->Stop(stream->pipe); 339 if (status!=ECHOSTATUS_OK) { 340 PRINT(("echo_stream_halt : Could not stop the pipe %s\n", pStatusStrs[status])); 341 } 342 } 343 344 345 echo_stream * 346 echo_stream_new(echo_dev *card, uint8 use, uint32 bufframes, uint8 bufcount) 347 { 348 echo_stream *stream; 349 cpu_status status; 350 LOG(("echo_stream_new\n")); 351 352 stream = (echo_stream *) malloc(sizeof(echo_stream)); 353 if (stream == NULL) 354 return (NULL); 355 stream->card = card; 356 stream->use = use; 357 stream->state = 0; 358 stream->bitsPerSample = 0; 359 stream->sample_rate = 0; 360 stream->channels = 0; 361 stream->bufframes = bufframes; 362 stream->bufcount = bufcount; 363 stream->inth = NULL; 364 stream->inthparam = NULL; 365 stream->buffer = NULL; 366 stream->blksize = 0; 367 stream->trigblk = 0; 368 stream->blkmod = 0; 369 370 stream->pipe = -1; 371 372 stream->frames_count = 0; 373 stream->real_time = 0; 374 stream->buffer_cycle = 0; 375 stream->update_needed = false; 376 377 status = lock(); 378 LIST_INSERT_HEAD((&card->streams), stream, next); 379 unlock(status); 380 381 return stream; 382 } 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 #ifdef CARDBUS 537 // Get card services client module 538 if (get_module(CB_ENABLER_MODULE_NAME, (module_info **)&cbemi) != B_OK) { 539 dprintf(DRIVER_NAME ": cardbus enabler module error\n"); 540 return B_ERROR; 541 } 542 // Create the devices lock 543 device_lock = create_sem(1, DRIVER_NAME " device"); 544 if (device_lock < B_OK) { 545 dprintf(DRIVER_NAME ": create device semaphore error 0x%.8x\n", device_lock); 546 put_module(CB_ENABLER_MODULE_NAME); 547 return B_ERROR; 548 } 549 // Register driver 550 cbemi->register_driver(DRIVER_NAME, descriptors, COUNT_DESCRIPTOR); 551 cbemi->install_notify(DRIVER_NAME, &cardbus_hooks); 552 LIST_INIT(&(devices)); 553 return B_OK; 554 #else 555 int ix = 0; 556 557 pci_info info; 558 status_t err; 559 num_cards = 0; 560 561 if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) 562 return ENOSYS; 563 564 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) { 565 ushort card_type = info.u.h0.subsystem_id & 0xfff0; 566 567 if (info.vendor_id == VENDOR_ID 568 && ((info.device_id == DEVICE_ID_56301) 569 || (info.device_id == DEVICE_ID_56361)) 570 && (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID) 571 && ( 572 #ifdef ECHOGALS_FAMILY 573 (card_type == DARLA) 574 || (card_type == GINA) 575 || (card_type == LAYLA) 576 || (card_type == DARLA24) 577 #endif 578 #ifdef ECHO24_FAMILY 579 (card_type == GINA24) 580 || (card_type == LAYLA24) 581 || (card_type == MONA) 582 || (card_type == MIA) 583 #endif 584 #ifdef INDIGO_FAMILY 585 (card_type == INDIGO) 586 || (card_type == INDIGO_IO) 587 || (card_type == INDIGO_DJ) 588 #endif 589 #ifdef ECHO3G_FAMILY 590 (card_type == ECHO3G) 591 #endif 592 )) { 593 594 if (num_cards == NUM_CARDS) { 595 PRINT(("Too many " DRIVER_NAME " cards installed!\n")); 596 break; 597 } 598 memset(&cards[num_cards], 0, sizeof(echo_dev)); 599 cards[num_cards].info = info; 600 cards[num_cards].type = card_type; 601 #ifdef __HAIKU__ 602 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 603 DRIVER_NAME, &cards[num_cards])) < B_OK) { 604 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 605 DRIVER_NAME, info.bus, info.device, info.function, 606 strerror(err)); 607 continue; 608 } 609 #endif 610 if (echo_setup(&cards[num_cards])) { 611 PRINT(("Setup of " DRIVER_NAME " %" B_PRId32 " failed\n", num_cards + 1)); 612 #ifdef __HAIKU__ 613 (*pci->unreserve_device)(info.bus, info.device, info.function, 614 DRIVER_NAME, &cards[num_cards]); 615 #endif 616 } 617 else { 618 num_cards++; 619 } 620 } 621 } 622 if (!num_cards) { 623 PRINT(("no cards\n")); 624 put_module(B_PCI_MODULE_NAME); 625 PRINT(("no suitable cards found\n")); 626 return ENODEV; 627 } 628 629 return B_OK; 630 #endif 631 } 632 633 634 #ifndef CARDBUS 635 static void 636 make_device_names(echo_dev * card) 637 { 638 #ifdef MIDI_SUPPORT 639 sprintf(card->midi.name, "midi/" DRIVER_NAME "/%ld", card-cards + 1); 640 names[num_names++] = card->midi.name; 641 #endif 642 sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card-cards + 1); 643 names[num_names++] = card->name; 644 645 names[num_names] = NULL; 646 } 647 #else 648 649 status_t 650 cardbus_device_added(pci_info *info, void **cookie) { 651 echo_dev * card, *dev; 652 uint32 index; 653 char buffer[32]; 654 655 LOG(("cardbus_device_added at %.2d:%.2d:%.2d\n", info->bus, info->device, info->function)); 656 // Allocate cookie 657 if (!(*cookie = card = (echo_dev *)malloc(sizeof(echo_dev)))) { 658 return B_NO_MEMORY; 659 } 660 // Clear cookie 661 memset(card, 0, sizeof(echo_dev)); 662 // Initialize cookie 663 card->info = *info; 664 card->plugged = true; 665 card->index = 0; 666 667 LIST_FOREACH(dev, &devices, next) { 668 if (dev->index == card->index) { 669 card->index++; 670 dev = LIST_FIRST(&devices); 671 } 672 } 673 674 // Format device name 675 sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card->index); 676 // Lock the devices 677 acquire_sem(device_lock); 678 LIST_INSERT_HEAD((&devices), card, next); 679 // Unlock the devices 680 release_sem(device_lock); 681 682 echo_setup(card); 683 return B_OK; 684 } 685 686 687 // cardbus_device_removed - handle cardbus device removal. 688 // status : OK 689 void 690 cardbus_device_removed(void *cookie) 691 { 692 echo_dev *card = (echo_dev *) cookie; 693 694 LOG((": cardbus_device_removed\n")); 695 // Check 696 if (card == NULL) { 697 LOG((": null device 0x%.8x\n", card)); 698 return; 699 } 700 701 echo_shutdown(card); 702 703 // Lock the devices 704 acquire_sem(device_lock); 705 // Finalize 706 card->plugged = false; 707 // Check if the device is opened 708 if (card->opened) { 709 LOG(("device 0x%.8x %s still in use\n", card, card->name)); 710 } else { 711 LOG(("free device 0x%.8x %s\n", card, card->name)); 712 LIST_REMOVE(card, next); 713 free(card); 714 } 715 // Unlock the devices 716 release_sem(device_lock); 717 } 718 719 #endif 720 721 722 static status_t 723 echo_setup(echo_dev* card) 724 { 725 unsigned char cmd; 726 const char* name; 727 728 PRINT(("echo_setup(%p)\n", card)); 729 730 #ifndef CARDBUS 731 (*pci->write_pci_config)(card->info.bus, card->info.device, 732 card->info.function, PCI_latency, 1, 0xc0 ); 733 734 make_device_names(card); 735 #endif 736 card->bmbar = card->info.u.h0.base_registers[0]; 737 card->irq = card->info.u.h0.interrupt_line; 738 739 card->area_bmbar = map_mem(&card->log_bmbar, card->bmbar, 740 card->info.u.h0.base_register_sizes[0], DRIVER_NAME" bmbar io"); 741 if (card->area_bmbar <= B_OK) { 742 LOG(("mapping of bmbar io failed, error = %#x\n",card->area_bmbar)); 743 goto err5; 744 } 745 LOG(("mapping of bmbar: area %#x, phys %#x, log %#x\n", card->area_bmbar, 746 card->bmbar, card->log_bmbar)); 747 748 card->pOSS = new COsSupport(card->info.device_id, card->info.revision); 749 if (card->pOSS == NULL) 750 goto err4; 751 752 switch (card->type) { 753 #ifdef ECHOGALS_FAMILY 754 case DARLA: 755 card->pEG = new CDarla(card->pOSS); 756 name = "Echo Darla"; 757 break; 758 case GINA: 759 card->pEG = new CGina(card->pOSS); 760 name = "Echo Gina"; 761 break; 762 case LAYLA: 763 card->pEG = new CLayla(card->pOSS); 764 name = "Echo Layla"; 765 break; 766 case DARLA24: 767 card->pEG = new CDarla24(card->pOSS); 768 name = "Echo Darla24"; 769 break; 770 #endif 771 #ifdef ECHO24_FAMILY 772 case GINA24: 773 card->pEG = new CGina24(card->pOSS); 774 name = "Echo Gina24"; 775 break; 776 case LAYLA24: 777 card->pEG = new CLayla24(card->pOSS); 778 name = "Echo Layla24"; 779 break; 780 case MONA: 781 card->pEG = new CMona(card->pOSS); 782 name = "Echo Mona"; 783 break; 784 case MIA: 785 card->pEG = new CMia(card->pOSS); 786 name = "Echo Mia"; 787 break; 788 #endif 789 #ifdef INDIGO_FAMILY 790 case INDIGO: 791 card->pEG = new CIndigo(card->pOSS); 792 name = "Echo Indigo"; 793 break; 794 case INDIGO_IO: 795 card->pEG = new CIndigoIO(card->pOSS); 796 name = "Echo IndigoIO"; 797 break; 798 case INDIGO_DJ: 799 card->pEG = new CIndigoDJ(card->pOSS); 800 name = "Echo IndigoDJ"; 801 break; 802 #endif 803 #ifdef ECHO3G_FAMILY 804 case ECHO3G: 805 card->pEG = new C3g(card->pOSS); 806 name = "Echo 3g"; 807 break; 808 #endif 809 default: 810 PRINT(("card type 0x%x not supported by " DRIVER_NAME "\n", 811 card->type)); 812 name = "Unknown"; 813 } 814 815 if (card->pEG == NULL) 816 goto err2; 817 818 #ifndef CARDBUS 819 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 820 card->info.function, PCI_command, 2); 821 PRINT(("PCI command before: %x\n", cmd)); 822 (*pci->write_pci_config)(card->info.bus, card->info.device, 823 card->info.function, PCI_command, 2, cmd | PCI_command_io); 824 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 825 card->info.function, PCI_command, 2); 826 PRINT(("PCI command after: %x\n", cmd)); 827 #endif 828 829 card->pEG->AssignResources(card->log_bmbar, name); 830 831 ECHOSTATUS status; 832 status = card->pEG->InitHw(); 833 if (status != ECHOSTATUS_OK) 834 goto err3; 835 836 card->pEG->GetCapabilities(&card->caps); 837 838 /* Init streams list */ 839 LIST_INIT(&(card->streams)); 840 841 /* Init mems list */ 842 LIST_INIT(&(card->mems)); 843 844 #ifdef MIDI_SUPPORT 845 card->midi.midi_ready_sem = create_sem(0, "midi sem"); 846 #endif 847 848 PRINT(("installing interrupt : %x\n", card->irq)); 849 status = install_io_interrupt_handler(card->irq, echo_int, card, 0); 850 if (status != B_OK) { 851 PRINT(("failed to install interrupt\n")); 852 goto err2; 853 } 854 855 PRINT(("echo_setup done\n")); 856 857 echo_dump_caps(card); 858 859 #ifdef ECHO3G_FAMILY 860 if (card->type == ECHO3G) { 861 strlcpy(card->caps.szName, ((C3g*)card->pEG)->Get3gBoxName(), 862 ECHO_MAXNAMELEN); 863 } 864 #endif 865 866 status = card->pEG->OpenMixer(card->mixer); 867 if (status != ECHOSTATUS_OK) { 868 PRINT(("failed to open mixer\n")); 869 goto err1; 870 } 871 872 return B_OK; 873 874 err1: 875 remove_io_interrupt_handler(card->irq, echo_int, card); 876 err2: 877 #ifdef MIDI_SUPPORT 878 delete_sem(card->midi.midi_ready_sem); 879 #endif 880 err3: 881 delete card->pEG; 882 err4: 883 delete card->pOSS; 884 err5: 885 delete_area(card->area_bmbar); 886 return B_ERROR; 887 } 888 889 static void 890 echo_shutdown(echo_dev *card) 891 { 892 ECHOSTATUS status; 893 894 PRINT(("shutdown(%p)\n", card)); 895 status = card->pEG->CloseMixer(card->mixer); 896 if (status != ECHOSTATUS_OK) 897 PRINT(("echo_shutdown: error when CloseMixer\n")); 898 899 remove_io_interrupt_handler(card->irq, echo_int, card); 900 901 #ifdef MIDI_SUPPORT 902 delete_sem(card->midi.midi_ready_sem); 903 #endif 904 905 delete card->pEG; 906 delete card->pOSS; 907 908 delete_area(card->area_bmbar); 909 } 910 911 912 913 void 914 uninit_driver(void) 915 { 916 PRINT(("uninit_driver()\n")); 917 918 #ifdef CARDBUS 919 echo_dev *dev; 920 921 LIST_FOREACH(dev, &devices, next) { 922 echo_shutdown(dev); 923 } 924 put_module(CB_ENABLER_MODULE_NAME); 925 #else 926 int ix, cnt = num_cards; 927 num_cards = 0; 928 for (ix=0; ix<cnt; ix++) { 929 echo_shutdown(&cards[ix]); 930 #ifdef __HAIKU__ 931 (*pci->unreserve_device)(cards[ix].info.bus, 932 cards[ix].info.device, cards[ix].info.function, 933 DRIVER_NAME, &cards[ix]); 934 #endif 935 } 936 937 memset(&cards, 0, sizeof(cards)); 938 put_module(B_PCI_MODULE_NAME); 939 #endif 940 } 941 942 943 const char ** 944 publish_devices(void) 945 { 946 #ifdef CARDBUS 947 echo_dev *dev; 948 int ix = 0; 949 950 // Lock the devices 951 acquire_sem(device_lock); 952 // Loop 953 LIST_FOREACH(dev, &devices, next) { 954 if (dev->plugged == true) { 955 names[ix] = dev->name; 956 ix++; 957 } 958 } 959 names[ix] = NULL; 960 release_sem(device_lock); 961 #else 962 int ix = 0; 963 PRINT(("publish_devices()\n")); 964 965 for (ix=0; names[ix]; ix++) { 966 PRINT(("publish %s\n", names[ix])); 967 } 968 #endif 969 return (const char **)names; 970 } 971 972 973 device_hooks * 974 find_device(const char * name) 975 { 976 #ifdef CARDBUS 977 echo_dev *dev; 978 LIST_FOREACH(dev, &devices, next) { 979 if (!strcmp(dev->name, name)) { 980 return &multi_hooks; 981 } 982 } 983 984 #else 985 int ix; 986 987 PRINT(("find_device(%s)\n", name)); 988 989 for (ix=0; ix<num_cards; ix++) { 990 #ifdef MIDI_SUPPORT 991 if (!strcmp(cards[ix].midi.name, name)) { 992 return &midi_hooks; 993 } 994 #endif 995 if (!strcmp(cards[ix].name, name)) { 996 return &multi_hooks; 997 } 998 } 999 #endif 1000 PRINT(("find_device(%s) failed\n", name)); 1001 return NULL; 1002 } 1003 1004 int32 api_version = B_CUR_DRIVER_API_VERSION; 1005