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 status_t err; 552 num_cards = 0; 553 554 if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) 555 return ENOSYS; 556 557 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) { 558 ushort card_type = info.u.h0.subsystem_id & 0xfff0; 559 560 if (info.vendor_id == VENDOR_ID 561 && ((info.device_id == DEVICE_ID_56301) 562 || (info.device_id == DEVICE_ID_56361)) 563 && (info.u.h0.subsystem_vendor_id == SUBVENDOR_ID) 564 && ( 565 #ifdef ECHOGALS_FAMILY 566 (card_type == DARLA) 567 || (card_type == GINA) 568 || (card_type == LAYLA) 569 || (card_type == DARLA24) 570 #endif 571 #ifdef ECHO24_FAMILY 572 (card_type == GINA24) 573 || (card_type == LAYLA24) 574 || (card_type == MONA) 575 || (card_type == MIA) 576 #endif 577 #ifdef INDIGO_FAMILY 578 (card_type == INDIGO) 579 || (card_type == INDIGO_IO) 580 || (card_type == INDIGO_DJ) 581 #endif 582 #ifdef ECHO3G_FAMILY 583 (card_type == ECHO3G) 584 #endif 585 )) { 586 587 if (num_cards == NUM_CARDS) { 588 PRINT(("Too many "DRIVER_NAME" cards installed!\n")); 589 break; 590 } 591 memset(&cards[num_cards], 0, sizeof(echo_dev)); 592 cards[num_cards].info = info; 593 cards[num_cards].type = card_type; 594 #ifdef __HAIKU__ 595 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 596 DRIVER_NAME, &cards[num_cards])) < B_OK) { 597 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 598 DRIVER_NAME, info.bus, info.device, info.function, 599 strerror(err)); 600 continue; 601 } 602 #endif 603 if (echo_setup(&cards[num_cards])) { 604 PRINT(("Setup of "DRIVER_NAME" %ld failed\n", num_cards+1)); 605 #ifdef __HAIKU__ 606 (*pci->unreserve_device)(info.bus, info.device, info.function, 607 DRIVER_NAME, &cards[num_cards]); 608 #endif 609 } 610 else { 611 num_cards++; 612 } 613 } 614 } 615 if (!num_cards) { 616 PRINT(("no cards\n")); 617 put_module(B_PCI_MODULE_NAME); 618 PRINT(("no suitable cards found\n")); 619 return ENODEV; 620 } 621 622 return B_OK; 623 #endif 624 } 625 626 627 #ifndef CARDBUS 628 static void 629 make_device_names( 630 echo_dev * card) 631 { 632 #ifdef MIDI_SUPPORT 633 sprintf(card->midi.name, "midi/"DRIVER_NAME"/%ld", card-cards+1); 634 names[num_names++] = card->midi.name; 635 #endif 636 sprintf(card->name, "audio/hmulti/"DRIVER_NAME"/%ld", card-cards+1); 637 names[num_names++] = card->name; 638 639 names[num_names] = NULL; 640 } 641 #else 642 643 status_t 644 cardbus_device_added(pci_info *info, void **cookie) { 645 echo_dev * card, *dev; 646 uint32 index; 647 char buffer[32]; 648 649 LOG(("cardbus_device_added at %.2d:%.2d:%.2d\n", info->bus, info->device, info->function)); 650 // Allocate cookie 651 if (!(*cookie = card = (echo_dev *)malloc(sizeof(echo_dev)))) { 652 return B_NO_MEMORY; 653 } 654 // Clear cookie 655 memset(card, 0, sizeof(echo_dev)); 656 // Initialize cookie 657 card->info = *info; 658 card->plugged = true; 659 card->index = 0; 660 661 LIST_FOREACH(dev, &devices, next) { 662 if (dev->index == card->index) { 663 card->index++; 664 dev = LIST_FIRST(&devices); 665 } 666 } 667 668 // Format device name 669 sprintf(card->name, "audio/hmulti/" DRIVER_NAME "/%ld", card->index); 670 // Lock the devices 671 acquire_sem(device_lock); 672 LIST_INSERT_HEAD((&devices), card, next); 673 // Unlock the devices 674 release_sem(device_lock); 675 676 echo_setup(card); 677 return B_OK; 678 } 679 680 681 // cardbus_device_removed - handle cardbus device removal. 682 // status : OK 683 void 684 cardbus_device_removed(void *cookie) 685 { 686 echo_dev *card = (echo_dev *) cookie; 687 688 LOG((": cardbus_device_removed\n")); 689 // Check 690 if (card == NULL) { 691 LOG((": null device 0x%.8x\n", card)); 692 return; 693 } 694 695 echo_shutdown(card); 696 697 // Lock the devices 698 acquire_sem(device_lock); 699 // Finalize 700 card->plugged = false; 701 // Check if the device is opened 702 if (card->opened) { 703 LOG(("device 0x%.8x %s still in use\n", card, card->name)); 704 } else { 705 LOG(("free device 0x%.8x %s\n", card, card->name)); 706 LIST_REMOVE(card, next); 707 free(card); 708 } 709 // Unlock the devices 710 release_sem(device_lock); 711 } 712 713 #endif 714 715 716 static status_t 717 echo_setup(echo_dev * card) 718 { 719 unsigned char cmd; 720 char *name; 721 722 PRINT(("echo_setup(%p)\n", card)); 723 724 #ifndef CARDBUS 725 (*pci->write_pci_config)(card->info.bus, card->info.device, 726 card->info.function, PCI_latency, 1, 0xc0 ); 727 728 make_device_names(card); 729 #endif 730 card->bmbar = card->info.u.h0.base_registers[0]; 731 card->irq = card->info.u.h0.interrupt_line; 732 733 card->area_bmbar = map_mem(&card->log_bmbar, card->bmbar, 734 card->info.u.h0.base_register_sizes[0], DRIVER_NAME" bmbar io"); 735 if (card->area_bmbar <= B_OK) { 736 LOG(("mapping of bmbar io failed, error = %#x\n",card->area_bmbar)); 737 goto err5; 738 } 739 LOG(("mapping of bmbar: area %#x, phys %#x, log %#x\n", card->area_bmbar, 740 card->bmbar, card->log_bmbar)); 741 742 card->pOSS = new COsSupport(card->info.device_id, card->info.revision); 743 if (card->pOSS == NULL) 744 goto err4; 745 746 switch (card->type) { 747 #ifdef ECHOGALS_FAMILY 748 case DARLA: 749 card->pEG = new CDarla(card->pOSS); 750 name = "Echo Darla"; 751 break; 752 case GINA: 753 card->pEG = new CGina(card->pOSS); 754 name = "Echo Gina"; 755 break; 756 case LAYLA: 757 card->pEG = new CLayla(card->pOSS); 758 name = "Echo Layla"; 759 break; 760 case DARLA24: 761 card->pEG = new CDarla24(card->pOSS); 762 name = "Echo Darla24"; 763 break; 764 #endif 765 #ifdef ECHO24_FAMILY 766 case GINA24: 767 card->pEG = new CGina24(card->pOSS); 768 name = "Echo Gina24"; 769 break; 770 case LAYLA24: 771 card->pEG = new CLayla24(card->pOSS); 772 name = "Echo Layla24"; 773 break; 774 case MONA: 775 card->pEG = new CMona(card->pOSS); 776 name = "Echo Mona"; 777 break; 778 case MIA: 779 card->pEG = new CMia(card->pOSS); 780 name = "Echo Mia"; 781 break; 782 #endif 783 #ifdef INDIGO_FAMILY 784 case INDIGO: 785 card->pEG = new CIndigo(card->pOSS); 786 name = "Echo Indigo"; 787 break; 788 case INDIGO_IO: 789 card->pEG = new CIndigoIO(card->pOSS); 790 name = "Echo IndigoIO"; 791 break; 792 case INDIGO_DJ: 793 card->pEG = new CIndigoDJ(card->pOSS); 794 name = "Echo IndigoDJ"; 795 break; 796 #endif 797 #ifdef ECHO3G_FAMILY 798 case ECHO3G: 799 card->pEG = new C3g(card->pOSS); 800 name = "Echo 3g"; 801 break; 802 #endif 803 default: 804 PRINT(("card type 0x%x not supported by "DRIVER_NAME"\n", 805 card->type)); 806 } 807 808 if (card->pEG == NULL) 809 goto err2; 810 811 #ifndef CARDBUS 812 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 813 card->info.function, PCI_command, 2); 814 PRINT(("PCI command before: %x\n", cmd)); 815 (*pci->write_pci_config)(card->info.bus, card->info.device, 816 card->info.function, PCI_command, 2, cmd | PCI_command_io); 817 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, 818 card->info.function, PCI_command, 2); 819 PRINT(("PCI command after: %x\n", cmd)); 820 #endif 821 822 card->pEG->AssignResources(card->log_bmbar, name); 823 824 ECHOSTATUS status; 825 status = card->pEG->InitHw(); 826 if (status != ECHOSTATUS_OK) 827 goto err3; 828 829 card->pEG->GetCapabilities(&card->caps); 830 831 /* Init streams list */ 832 LIST_INIT(&(card->streams)); 833 834 /* Init mems list */ 835 LIST_INIT(&(card->mems)); 836 837 #ifdef MIDI_SUPPORT 838 card->midi.midi_ready_sem = create_sem(0, "midi sem"); 839 #endif 840 841 PRINT(("installing interrupt : %x\n", card->irq)); 842 status = install_io_interrupt_handler(card->irq, echo_int, card, 0); 843 if (status != B_OK) { 844 PRINT(("failed to install interrupt\n")); 845 goto err2; 846 } 847 848 PRINT(("echo_setup done\n")); 849 850 echo_dump_caps(card); 851 852 #ifdef ECHO3G_FAMILY 853 if (card->type == ECHO3G) { 854 strncpy(card->caps.szName, ((C3g*)card->pEG)->Get3gBoxName(), 855 ECHO_MAXNAMELEN); 856 } 857 #endif 858 859 status = card->pEG->OpenMixer(card->mixer); 860 if (status != ECHOSTATUS_OK) { 861 PRINT(("failed to open mixer\n")); 862 goto err1; 863 } 864 865 return B_OK; 866 867 err1: 868 remove_io_interrupt_handler(card->irq, echo_int, card); 869 err2: 870 #ifdef MIDI_SUPPORT 871 delete_sem(card->midi.midi_ready_sem); 872 #endif 873 err3: 874 delete card->pEG; 875 err4: 876 delete card->pOSS; 877 err5: 878 delete_area(card->area_bmbar); 879 return B_ERROR; 880 } 881 882 static void 883 echo_shutdown(echo_dev *card) 884 { 885 ECHOSTATUS status; 886 887 PRINT(("shutdown(%p)\n", card)); 888 status = card->pEG->CloseMixer(card->mixer); 889 if (status != ECHOSTATUS_OK) 890 PRINT(("echo_shutdown: error when CloseMixer\n")); 891 892 remove_io_interrupt_handler(card->irq, echo_int, card); 893 894 #ifdef MIDI_SUPPORT 895 delete_sem(card->midi.midi_ready_sem); 896 #endif 897 898 delete card->pEG; 899 delete card->pOSS; 900 901 delete_area(card->area_bmbar); 902 } 903 904 905 906 void 907 uninit_driver(void) 908 { 909 PRINT(("uninit_driver()\n")); 910 911 #ifdef CARDBUS 912 echo_dev *dev; 913 914 LIST_FOREACH(dev, &devices, next) { 915 echo_shutdown(dev); 916 } 917 put_module(CB_ENABLER_MODULE_NAME); 918 #else 919 int ix, cnt = num_cards; 920 num_cards = 0; 921 for (ix=0; ix<cnt; ix++) { 922 echo_shutdown(&cards[ix]); 923 } 924 925 memset(&cards, 0, sizeof(cards)); 926 put_module(B_PCI_MODULE_NAME); 927 #endif 928 } 929 930 931 const char ** 932 publish_devices(void) 933 { 934 #ifdef CARDBUS 935 echo_dev *dev; 936 int ix = 0; 937 938 // Lock the devices 939 acquire_sem(device_lock); 940 // Loop 941 LIST_FOREACH(dev, &devices, next) { 942 if (dev->plugged == true) { 943 names[ix] = dev->name; 944 ix++; 945 } 946 } 947 names[ix] = NULL; 948 release_sem(device_lock); 949 #else 950 int ix = 0; 951 PRINT(("publish_devices()\n")); 952 953 for (ix=0; names[ix]; ix++) { 954 PRINT(("publish %s\n", names[ix])); 955 } 956 #endif 957 return (const char **)names; 958 } 959 960 961 device_hooks * 962 find_device(const char * name) 963 { 964 echo_dev *dev; 965 #ifdef CARDBUS 966 LIST_FOREACH(dev, &devices, next) { 967 if (!strcmp(dev->name, name)) { 968 return &multi_hooks; 969 } 970 } 971 972 #else 973 int ix; 974 975 PRINT(("find_device(%s)\n", name)); 976 977 for (ix=0; ix<num_cards; ix++) { 978 #ifdef MIDI_SUPPORT 979 if (!strcmp(cards[ix].midi.name, name)) { 980 return &midi_hooks; 981 } 982 #endif 983 if (!strcmp(cards[ix].name, name)) { 984 return &multi_hooks; 985 } 986 } 987 #endif 988 PRINT(("find_device(%s) failed\n", name)); 989 return NULL; 990 } 991 992 int32 api_version = B_CUR_DRIVER_API_VERSION; 993