1 /* 2 Copyright 1999, Be Incorporated. All Rights Reserved. 3 This file may be used under the terms of the Be Sample Code License. 4 */ 5 6 #include "cmedia_pci.h" 7 #include "cm_private.h" 8 9 #include <string.h> 10 #include <stdio.h> 11 12 #include <KernelExport.h> 13 14 15 #if DEBUG 16 #define KPRINTF(x) kprintf x 17 #else 18 #define KPRINTF(x) 19 #endif 20 21 EXPORT status_t init_hardware(void); 22 EXPORT status_t init_driver(void); 23 EXPORT void uninit_driver(void); 24 EXPORT const char ** publish_devices(void); 25 EXPORT device_hooks * find_device(const char *); 26 27 28 static char pci_name[] = B_PCI_MODULE_NAME; 29 static pci_module_info *pci; 30 static char gameport_name[] = "generic/gameport/v1"; 31 generic_gameport_module * gameport; 32 static char mpu401_name[] = B_MPU_401_MODULE_NAME; 33 generic_mpu401_module * mpu401; 34 35 #define DO_JOY 1 36 #define DO_MIDI 1 37 #define DO_PCM 1 38 #define DO_MUX 0 39 #define DO_MIXER 0 40 41 #if DO_MIDI 42 extern device_hooks midi_hooks; 43 #endif /* DO_MIDI */ 44 #if DO_JOY 45 extern device_hooks joy_hooks; 46 #endif /* DO_JOY */ 47 #if DO_PCM 48 extern device_hooks pcm_hooks; 49 #endif /* DO_PCM */ 50 #if DO_MUX 51 extern device_hooks mux_hooks; 52 #endif /* DO_MUX */ 53 #if DO_MIXER 54 extern device_hooks mixer_hooks; 55 #endif /* DO_MIXER */ 56 57 58 int32 num_cards; 59 cmedia_pci_dev cards[NUM_CARDS]; 60 int num_names; 61 char * names[NUM_CARDS * 7 + 1]; 62 /* vuchar *io_base; */ 63 64 65 /* ---------- 66 PCI_IO_RD - read a byte from pci i/o space 67 ----- */ 68 69 uint8 70 PCI_IO_RD (int offset) 71 { 72 return (*pci->read_io_8) (offset); 73 } 74 75 76 /* ---------- 77 PCI_IO_RD_32 - read a 32 bit value from pci i/o space 78 ----- */ 79 80 uint32 81 PCI_IO_RD_32 (int offset) 82 { 83 return (*pci->read_io_32) (offset); 84 } 85 /* ---------- 86 PCI_IO_WR - write a byte to pci i/o space 87 ----- */ 88 89 void 90 PCI_IO_WR (int offset, uint8 val) 91 { 92 (*pci->write_io_8) (offset, val); 93 } 94 95 96 /* detect presence of our hardware */ 97 status_t 98 init_hardware(void) 99 { 100 int ix=0; 101 pci_info info; 102 status_t err = ENODEV; 103 104 ddprintf(("cmedia_pci: init_hardware()\n")); 105 106 if (get_module(pci_name, (module_info **)&pci)) 107 return ENOSYS; 108 109 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 110 if (info.vendor_id == CMEDIA_PCI_VENDOR_ID && 111 (info.device_id == CMEDIA_8338A_DEVICE_ID || 112 info.device_id == CMEDIA_8338B_DEVICE_ID || 113 info.device_id == CMEDIA_8738A_DEVICE_ID || 114 info.device_id == CMEDIA_8738B_DEVICE_ID )) { 115 err = B_OK; 116 } 117 ix++; 118 } 119 #if defined(__POWERPC__) && 0 120 { 121 char area_name [32]; 122 area_info area; 123 area_id id; 124 125 sprintf (area_name, "pci_bus%d_isa_io", info.bus); 126 id = find_area (area_name); 127 if (id < 0) 128 err = id; 129 else if ((err = get_area_info (id, &area)) == B_OK) 130 io_base = area.address; 131 } 132 #endif 133 134 put_module(pci_name); 135 136 return err; 137 } 138 139 140 void set_direct(cmedia_pci_dev * card, int regno, uchar value, uchar mask) 141 { 142 if (mask == 0) { 143 return; 144 } 145 if (mask != 0xff) { 146 uchar old = PCI_IO_RD(card->enhanced+regno); 147 value = (value&mask)|(old&~mask); 148 } 149 PCI_IO_WR(card->enhanced+regno, value); 150 ddprintf(("cmedia_pci: CM%02x = %02x\n", regno, value)); 151 } 152 153 154 uchar get_direct(cmedia_pci_dev * card, int regno) 155 { 156 uchar ret = PCI_IO_RD(card->enhanced+regno); 157 return ret; 158 } 159 160 161 162 void set_indirect(cmedia_pci_dev * card, int regno, uchar value, uchar mask) 163 { 164 PCI_IO_WR(card->enhanced+0x23, regno); 165 EIEIO(); 166 if (mask == 0) { 167 return; 168 } 169 if (mask != 0xff) { 170 uchar old = PCI_IO_RD(card->enhanced+0x22); 171 value = (value&mask)|(old&~mask); 172 } 173 PCI_IO_WR(card->enhanced+0x22, value); 174 EIEIO(); 175 ddprintf(("cmedia_pci: CMX%02x = %02x\n", regno, value)); 176 } 177 178 179 180 uchar get_indirect(cmedia_pci_dev * card,int regno) 181 { 182 uchar ret; 183 PCI_IO_WR(card->enhanced+0x23, regno); 184 EIEIO(); 185 ret = PCI_IO_RD(card->enhanced+0x22); 186 return ret; 187 } 188 189 190 void dump_card(cmedia_pci_dev* card); 191 #if 0 192 void dump_card(cmedia_pci_dev* card) 193 { 194 int ix; 195 dprintf("\n"); 196 dprintf("CM: "); 197 for (ix=0; ix<6; ix++) { 198 if (ix == 2 || ix == 3) dprintf(" "); 199 else dprintf(" %02x", get_direct(card, ix)); 200 } 201 for (ix=0; ix<0x32; ix++) { 202 if (!(ix & 7)) { 203 dprintf("\nCMX%02x:", ix); 204 } 205 dprintf(" %02x", get_indirect(card, ix)); 206 } 207 dprintf("\n"); 208 dprintf("\n"); 209 } 210 #else 211 void dump_card(cmedia_pci_dev* card) 212 { 213 } 214 #endif 215 216 217 static void 218 disable_card_interrupts(cmedia_pci_dev * card) 219 { 220 set_direct(card, 0x0e, 0x00, 0x03); 221 } 222 223 224 static status_t 225 setup_dma(cmedia_pci_dev * card) 226 { 227 /* we're appropriating some ISA space here... */ 228 /* need kernel support to do it right */ 229 const uint16 base = card->enhanced + 0x80; 230 ddprintf(("cmedia_pci: dma base is 0x%04x\n", base)); 231 if (base == 0) 232 return B_DEV_RESOURCE_CONFLICT; 233 card->dma_base = base; 234 return B_OK; 235 } 236 237 238 static void 239 set_default_registers(cmedia_pci_dev * card) 240 { 241 static uchar values[] = { 242 #ifdef DO_JOY 243 0x04, 0x02, 0x02, /* enable joystick */ 244 #endif 245 246 0x0a, 0x01, 0x01, /* enable SPDIF inverse before SPDIF_LOOP */ 247 0x04, 0x80, 0x80, /* enable SPDIF_LOOP */ 248 249 0x1a, 0x00, 0x20, /* SPD32SEL disable */ 250 0x1a, 0x00, 0x10, /* SPDFLOOPI disable */ 251 252 0x1b, 0x04, 0x04, /* dual channel mode enable */ 253 0x1a, 0x00, 0x80, /* Double DAC structure disable */ 254 255 0x24, 0x00, 0x02, /* 3D surround disable */ 256 257 0x24, 0x00, 0x01, /* disable SPDIF_IN PCM to DAC */ 258 #ifdef DO_MIDI 259 0x04, 0x04, 0x04, /* enable MPU-401 */ 260 0x17, 0x00, 0x60, /* default at 0x330 */ 261 #endif 262 }; 263 uchar * ptr = values; 264 265 while (ptr < values+sizeof(values)) { 266 set_direct(card, ptr[0], ptr[1], ptr[2]); 267 ptr += 3; 268 } 269 } 270 271 272 static void 273 make_device_names(cmedia_pci_dev * card) 274 { 275 char * name = card->name; 276 sprintf(name, "cmedia_pci/%ld", card-cards + 1); 277 278 #if DO_MIDI 279 sprintf(card->midi.name, "midi/%s", name); 280 names[num_names++] = card->midi.name; 281 #endif /* DO_MIDI */ 282 #if DO_JOY 283 sprintf(card->joy.name1, "joystick/%s", name); 284 names[num_names++] = card->joy.name1; 285 #endif /* DO_JOY */ 286 #if DO_PCM 287 /* cmedia_pci DMA doesn't work when physical NULL isn't NULL from PCI */ 288 /* this is a hack to not export bad devices on BeBox hardware */ 289 if ((*pci->ram_address)(0) == 0) { 290 sprintf(card->pcm.name, "audio/raw/%s", name); 291 names[num_names++] = card->pcm.name; 292 sprintf(card->pcm.oldname, "audio/old/%s", name); 293 names[num_names++] = card->pcm.oldname; 294 } 295 #endif /* DO_PCM */ 296 #if DO_MUX 297 sprintf(card->mux.name, "audio/mux/%s", name); 298 names[num_names++] = card->mux.name; 299 #endif /* DO_MUX */ 300 #if DO_MIXER 301 sprintf(card->mixer.name, "audio/mix/%s", name); 302 names[num_names++] = card->mixer.name; 303 #endif /* DO_MIXER */ 304 names[num_names] = NULL; 305 } 306 307 308 /* We use the SV chip in ISA DMA addressing mode, which is 24 bits */ 309 /* so we need to find suitable, locked, contiguous memory in that */ 310 /* physical address range. */ 311 312 static status_t 313 find_low_memory(cmedia_pci_dev * card) 314 { 315 size_t low_size = (MIN_MEMORY_SIZE + (B_PAGE_SIZE - 1)) 316 &~ (B_PAGE_SIZE - 1); 317 physical_entry where; 318 size_t trysize; 319 area_id curarea; 320 void * addr; 321 char name[DEVNAME]; 322 323 sprintf(name, "%s_low", card->name); 324 if (low_size < MIN_MEMORY_SIZE) { 325 low_size = MIN_MEMORY_SIZE; 326 } 327 trysize = low_size; 328 329 curarea = find_area(name); 330 if (curarea >= 0) { /* area there from previous run */ 331 area_info ainfo; 332 ddprintf(("cmedia_pci: testing likely candidate...\n")); 333 if (get_area_info(curarea, &ainfo)) { 334 ddprintf(("cmedia_pci: no info\n")); 335 goto allocate; 336 } 337 /* test area we found */ 338 trysize = ainfo.size; 339 addr = ainfo.address; 340 if (trysize < low_size) { 341 ddprintf(("cmedia_pci: too small (%lx)\n", trysize)); 342 goto allocate; 343 } 344 if (get_memory_map(addr, trysize, &where, 1) < B_OK) { 345 ddprintf(("cmedia_pci: no memory map\n")); 346 goto allocate; 347 } 348 if ((where.address & ~(phys_addr_t)0xffffff) != 0) { 349 ddprintf(("cmedia_pci: bad physical address\n")); 350 goto allocate; 351 } 352 if (ainfo.lock < B_FULL_LOCK || where.size < low_size) { 353 ddprintf(("cmedia_pci: lock not contiguous\n")); 354 goto allocate; 355 } 356 dprintf("cmedia_pci: physical %#" B_PRIxPHYSADDR " logical %p\n", 357 where.address, ainfo.address); 358 goto a_o_k; 359 } 360 361 allocate: 362 if (curarea >= 0) { 363 delete_area(curarea); /* area didn't work */ 364 curarea = -1; 365 } 366 ddprintf(("cmedia_pci: allocating new low area\n")); 367 368 curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS, 369 trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA); 370 ddprintf(("cmedia_pci: create_area(%lx) returned %lx logical %p\n", 371 trysize, curarea, addr)); 372 if (curarea < 0) { 373 goto oops; 374 } 375 if (get_memory_map(addr, low_size, &where, 1) < 0) { 376 delete_area(curarea); 377 curarea = B_ERROR; 378 goto oops; 379 } 380 ddprintf(("cmedia_pci: physical %p\n", where.address)); 381 if ((where.address & ~(phys_addr_t)0xffffff) != 0) { 382 delete_area(curarea); 383 curarea = B_ERROR; 384 goto oops; 385 } 386 if (((where.address + low_size) & ~(phys_addr_t)0xffffff) != 0) { 387 delete_area(curarea); 388 curarea = B_ERROR; 389 goto oops; 390 } 391 /* hey, it worked! */ 392 if (trysize > low_size) { /* don't waste */ 393 resize_area(curarea, low_size); 394 } 395 396 oops: 397 if (curarea < 0) { 398 dprintf("cmedia_pci: failed to create low_mem area\n"); 399 return curarea; 400 } 401 a_o_k: 402 ddprintf(("cmedia_pci: successfully found or created low area!\n")); 403 card->low_size = low_size; 404 card->low_mem = addr; 405 card->low_phys = where.address; 406 card->map_low = curarea; 407 return B_OK; 408 } 409 410 411 static status_t 412 setup_cmedia_pci(cmedia_pci_dev * card) 413 { 414 status_t err = B_OK; 415 /* cpu_status cp; */ 416 417 ddprintf(("cmedia_pci: setup_cmedia_pci(%p)\n", card)); 418 419 if ((card->pcm.init_sem = create_sem(1, "cm pcm init")) < B_OK) 420 goto bail; 421 #if 1 422 if ((*mpu401->create_device)(0x330, &card->midi.driver, 423 #else 424 if ((*mpu401->create_device)(card->info.u.h0.base_registers[3], &card->midi.driver, 425 #endif 426 0, midi_interrupt_op, &card->midi) < B_OK) 427 goto bail3; 428 #if 1 429 if ((*gameport->create_device)(0x201, &card->joy.driver) < B_OK) 430 #else 431 if ((*gameport->create_device)(card->info.u.h0.base_registers[4], &card->joy.driver) < B_OK) 432 #endif 433 goto bail4; 434 ddprintf(("midi %p gameport %p\n", card->midi.driver, card->joy.driver)); 435 card->midi.card = card; 436 437 err = find_low_memory(card); 438 if (err < B_OK) { 439 goto bail5; 440 } 441 442 //cp = disable_interrupts(); 443 //acquire_spinlock(&card->hardware); 444 445 make_device_names(card); 446 card->enhanced = card->info.u.h0.base_registers[0]; 447 ddprintf(("cmedia_pci: %s enhanced at %x\n", card->name, card->enhanced)); 448 449 ddprintf(("cmedia_pci: revision %x\n", get_indirect(card, 0x15))); 450 451 disable_card_interrupts(card); 452 if (setup_dma(card) != B_OK) { 453 dprintf("cmedia pci: can't setup DMA\n"); 454 goto bail6; 455 } 456 457 set_default_registers(card); 458 459 //release_spinlock(&card->hardware); 460 //restore_interrupts(cp); 461 462 return B_OK; 463 464 bail6: 465 // deallocate low memory 466 bail5: 467 (*gameport->delete_device)(card->joy.driver); 468 bail4: 469 (*mpu401->delete_device)(card->midi.driver); 470 bail3: 471 delete_sem(card->pcm.init_sem); 472 bail: 473 return err < B_OK ? err : B_ERROR; 474 } 475 476 477 static int 478 debug_cmedia(int argc, char * argv[]) 479 { 480 int ix = 0; 481 if (argc == 2) { 482 ix = parse_expression(argv[1]) - 1; 483 } 484 if (argc > 2 || ix < 0 || ix >= num_cards) { 485 dprintf("cmedia_pci: dude, you gotta watch your syntax!\n"); 486 return -1; 487 } 488 dprintf("%s: enhanced registers at 0x%x\n", cards[ix].name, 489 cards[ix].enhanced); 490 dprintf("%s: open %" B_PRId32 " dma_a at 0x%x dma_c 0x%x\n", cards[ix].pcm.name, 491 cards[ix].pcm.open_count, cards[ix].pcm.dma_a, cards[ix].pcm.dma_c); 492 if (cards[ix].pcm.open_count) { 493 dprintf(" dma_a: 0x%" B_PRIu32 "+0x%" B_PRIu32 " dma_c: 0x%" B_PRIu32 "+0x%" B_PRIu32 494 "\n", 495 PCI_IO_RD_32((int)cards[ix].pcm.dma_a), PCI_IO_RD_32((int)cards[ix].pcm.dma_a + 4), 496 PCI_IO_RD_32((int)cards[ix].pcm.dma_c), PCI_IO_RD_32((int)cards[ix].pcm.dma_c + 4)); 497 } 498 return 0; 499 } 500 501 502 status_t 503 init_driver(void) 504 { 505 pci_info info; 506 int ix = 0; 507 status_t err; 508 509 num_cards = 0; 510 511 ddprintf(("cmedia_pci: init_driver()\n")); 512 513 if (get_module(pci_name, (module_info **)&pci)) 514 return ENOSYS; 515 516 if (get_module(gameport_name, (module_info **)&gameport)) { 517 put_module(pci_name); 518 return ENOSYS; 519 } 520 ddprintf(("MPU\n")); 521 if (get_module(mpu401_name, (module_info **)&mpu401)) { 522 put_module(gameport_name); 523 put_module(pci_name); 524 return ENOSYS; 525 } 526 527 ddprintf(("MPU: %p\n", mpu401)); 528 529 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 530 if (info.vendor_id == CMEDIA_PCI_VENDOR_ID && 531 (info.device_id == CMEDIA_8338A_DEVICE_ID || 532 info.device_id == CMEDIA_8338B_DEVICE_ID || 533 info.device_id == CMEDIA_8738A_DEVICE_ID || 534 info.device_id == CMEDIA_8738B_DEVICE_ID )) { 535 if (num_cards == NUM_CARDS) { 536 dprintf("Too many C-Media cards installed!\n"); 537 break; 538 } 539 memset(&cards[num_cards], 0, sizeof(cmedia_pci_dev)); 540 cards[num_cards].info = info; 541 #ifdef __HAIKU__ 542 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 543 DRIVER_NAME, &cards[num_cards])) < B_OK) { 544 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 545 DRIVER_NAME, info.bus, info.device, info.function, 546 strerror(err)); 547 continue; 548 } 549 #endif 550 if (setup_cmedia_pci(&cards[num_cards])) { 551 dprintf("Setup of C-Media %d failed\n", num_cards + 1); 552 #ifdef __HAIKU__ 553 (*pci->unreserve_device)(info.bus, info.device, info.function, 554 DRIVER_NAME, &cards[num_cards]); 555 #endif 556 } 557 else { 558 num_cards++; 559 } 560 } 561 ix++; 562 } 563 if (!num_cards) { 564 KPRINTF(("no cards\n")); 565 put_module(mpu401_name); 566 put_module(gameport_name); 567 put_module(pci_name); 568 ddprintf(("cmedia_pci: no suitable cards found\n")); 569 return ENODEV; 570 } 571 572 #if DEBUG 573 add_debugger_command("cmedia", debug_cmedia, "cmedia [card# (1-n)]"); 574 #endif 575 return B_OK; 576 } 577 578 579 static void 580 teardown_cmedia_pci(cmedia_pci_dev * card) 581 { 582 static uchar regs[] = { 583 #ifdef DO_JOY 584 0x04, 0x00, 0x02, /* enable joystick */ 585 #endif 586 #ifdef DO_MIDI 587 0x04, 0x00, 0x04, /* enable MPU-401 */ 588 #endif 589 }; 590 uchar * ptr = regs; 591 cpu_status cp; 592 593 /* remove created devices */ 594 (*gameport->delete_device)(card->joy.driver); 595 (*mpu401->delete_device)(card->midi.driver); 596 597 cp = disable_interrupts(); 598 acquire_spinlock(&card->hardware); 599 600 while (ptr < regs + sizeof(regs)) { 601 set_direct(card, ptr[0], ptr[1], ptr[2]); 602 ptr += 3; 603 } 604 disable_card_interrupts(card); 605 606 release_spinlock(&card->hardware); 607 restore_interrupts(cp); 608 609 delete_sem(card->pcm.init_sem); 610 611 #ifdef __HAIKU__ 612 (*pci->unreserve_device)(card->info.bus, card->info.device, 613 card->info.function, DRIVER_NAME, card); 614 #endif 615 } 616 617 618 void 619 uninit_driver(void) 620 { 621 int ix, cnt = num_cards; 622 num_cards = 0; 623 624 ddprintf(("cmedia_pci: uninit_driver()\n")); 625 remove_debugger_command("cmedia", debug_cmedia); 626 627 for (ix = 0; ix < cnt; ix++) { 628 teardown_cmedia_pci(&cards[ix]); 629 } 630 memset(&cards, 0, sizeof(cards)); 631 put_module(mpu401_name); 632 put_module(gameport_name); 633 put_module(pci_name); 634 } 635 636 637 const char ** 638 publish_devices(void) 639 { 640 int ix = 0; 641 ddprintf(("cmedia_pci: publish_devices()\n")); 642 643 for (ix = 0; names[ix]; ix++) { 644 ddprintf(("cmedia_pci: publish %s\n", names[ix])); 645 } 646 return (const char **)names; 647 } 648 649 650 device_hooks * 651 find_device(const char * name) 652 { 653 int ix; 654 655 ddprintf(("cmedia_pci: find_device(%s)\n", name)); 656 657 for (ix = 0; ix < num_cards; ix++) { 658 #if DO_MIDI 659 if (!strcmp(cards[ix].midi.name, name)) { 660 return &midi_hooks; 661 } 662 #endif /* DO_MIDI */ 663 #if DO_JOY 664 if (!strcmp(cards[ix].joy.name1, name)) { 665 return &joy_hooks; 666 } 667 #endif /* DO_JOY */ 668 #if DO_PCM 669 if (!strcmp(cards[ix].pcm.name, name)) { 670 return &pcm_hooks; 671 } 672 if (!strcmp(cards[ix].pcm.oldname, name)) { 673 return &pcm_hooks; 674 } 675 #endif /* DO_PCM */ 676 #if DO_MUX 677 if (!strcmp(cards[ix].mux.name, name)) { 678 return &mux_hooks; 679 } 680 681 #endif /* DO_MUX */ 682 #if DO_MIXER 683 if (!strcmp(cards[ix].mixer.name, name)) { 684 return &mixer_hooks; 685 } 686 #endif /* DO_MIXER */ 687 } 688 ddprintf(("cmedia_pci: find_device(%s) failed\n", name)); 689 return NULL; 690 } 691 692 int32 api_version = B_CUR_DRIVER_API_VERSION; 693 694 static int32 695 cmedia_pci_interrupt(void * data) 696 { 697 cpu_status cp = disable_interrupts(); 698 cmedia_pci_dev * card = (cmedia_pci_dev *)data; 699 uchar status; 700 int32 handled = B_UNHANDLED_INTERRUPT; 701 702 /* KTRACE(); / * */ 703 acquire_spinlock(&card->hardware); 704 705 status = get_direct(card, 0x10); 706 707 #if DEBUG 708 /* kprintf("%x\n", status); / * */ 709 #endif 710 #if DO_PCM 711 if (status & 0x02) { 712 if (dma_c_interrupt(card)) { 713 handled = B_INVOKE_SCHEDULER; 714 } 715 else { 716 handled = B_HANDLED_INTERRUPT; 717 } 718 /* acknowledge interrupt */ 719 set_direct(card, 0x0e, 0x00, 0x02); 720 set_direct(card, 0x0e, 0x02, 0x02); 721 } 722 if (status & 0x01) { 723 if (dma_a_interrupt(card)) { 724 handled = B_INVOKE_SCHEDULER; 725 } 726 else { 727 handled = B_HANDLED_INTERRUPT; 728 } 729 /* acknowledge interrupt */ 730 set_direct(card, 0x0e, 0x00, 0x01); 731 set_direct(card, 0x0e, 0x01, 0x01); 732 } 733 #endif 734 #if DO_MIDI 735 status = get_direct(card, 0x12); 736 if (status & 0x01) { 737 if (midi_interrupt(card)) { 738 handled = B_INVOKE_SCHEDULER; 739 } else { 740 handled = B_HANDLED_INTERRUPT; 741 } 742 } 743 #endif 744 745 /* Sometimes, the Sonic Vibes will receive a byte of Midi data... 746 ** And duly note it in the MPU401 status register... 747 ** And generate an interrupt... 748 ** But not bother setting the midi interrupt bit in the ISR. 749 ** Thanks a lot, S3. 750 */ 751 if (handled == B_UNHANDLED_INTERRUPT) { 752 if (midi_interrupt(card)) { 753 handled = B_INVOKE_SCHEDULER; 754 } 755 } 756 757 /* KTRACE(); / * */ 758 release_spinlock(&card->hardware); 759 restore_interrupts(cp); 760 761 return handled; 762 // return (handled == B_INVOKE_SCHEDULER) ? B_HANDLED_INTERRUPT : handled; 763 } 764 765 766 void 767 increment_interrupt_handler(cmedia_pci_dev * card) 768 { 769 KPRINTF(("cmedia_pci: increment_interrupt_handler()\n")); 770 if (atomic_add(&card->inth_count, 1) == 0) { 771 // !!! 772 KPRINTF(("cmedia_pci: intline %d int %p\n", card->info.u.h0.interrupt_line, cmedia_pci_interrupt)); 773 install_io_interrupt_handler(card->info.u.h0.interrupt_line, 774 cmedia_pci_interrupt, card, 0); 775 } 776 } 777 778 779 void 780 decrement_interrupt_handler(cmedia_pci_dev * card) 781 { 782 KPRINTF(("cmedia_pci: decrement_interrupt_handler()\n")); 783 if (atomic_add(&card->inth_count, -1) == 1) { 784 KPRINTF(("cmedia_pci: remove_io_interrupt_handler()\n")); 785 remove_io_interrupt_handler(card->info.u.h0.interrupt_line, cmedia_pci_interrupt, card); 786 } 787 } 788 789 790