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 #if !defined(_KERNEL_EXPORT_H) 13 #include <KernelExport.h> 14 #endif 15 16 17 #if DEBUG 18 #define KPRINTF(x) kprintf x 19 #else 20 #define KPRINTF(x) 21 #endif 22 23 EXPORT status_t init_hardware(void); 24 EXPORT status_t init_driver(void); 25 EXPORT void uninit_driver(void); 26 EXPORT const char ** publish_devices(void); 27 EXPORT device_hooks * find_device(const char *); 28 29 30 static char pci_name[] = B_PCI_MODULE_NAME; 31 static pci_module_info *pci; 32 static char gameport_name[] = "generic/gameport/v1"; 33 generic_gameport_module * gameport; 34 static char mpu401_name[] = B_MPU_401_MODULE_NAME; 35 generic_mpu401_module * mpu401; 36 37 #define DO_JOY 1 38 #define DO_MIDI 1 39 #define DO_PCM 1 40 #define DO_MUX 0 41 #define DO_MIXER 0 42 43 #if DO_MIDI 44 extern device_hooks midi_hooks; 45 #endif /* DO_MIDI */ 46 #if DO_JOY 47 extern device_hooks joy_hooks; 48 #endif /* DO_JOY */ 49 #if DO_PCM 50 extern device_hooks pcm_hooks; 51 #endif /* DO_PCM */ 52 #if DO_MUX 53 extern device_hooks mux_hooks; 54 #endif /* DO_MUX */ 55 #if DO_MIXER 56 extern device_hooks mixer_hooks; 57 #endif /* DO_MIXER */ 58 59 60 int32 num_cards; 61 cmedia_pci_dev cards[NUM_CARDS]; 62 int num_names; 63 char * names[NUM_CARDS * 7 + 1]; 64 /* vuchar *io_base; */ 65 66 67 /* ---------- 68 PCI_IO_RD - read a byte from pci i/o space 69 ----- */ 70 71 uint8 72 PCI_IO_RD (int offset) 73 { 74 return (*pci->read_io_8) (offset); 75 } 76 77 78 /* ---------- 79 PCI_IO_RD_32 - read a 32 bit value from pci i/o space 80 ----- */ 81 82 uint32 83 PCI_IO_RD_32 (int offset) 84 { 85 return (*pci->read_io_32) (offset); 86 } 87 /* ---------- 88 PCI_IO_WR - write a byte to pci i/o space 89 ----- */ 90 91 void 92 PCI_IO_WR (int offset, uint8 val) 93 { 94 (*pci->write_io_8) (offset, val); 95 } 96 97 98 /* detect presence of our hardware */ 99 status_t 100 init_hardware(void) 101 { 102 int ix=0; 103 pci_info info; 104 status_t err = ENODEV; 105 106 ddprintf(("cmedia_pci: init_hardware()\n")); 107 108 if (get_module(pci_name, (module_info **)&pci)) 109 return ENOSYS; 110 111 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 112 if (info.vendor_id == CMEDIA_PCI_VENDOR_ID && 113 (info.device_id == CMEDIA_8338A_DEVICE_ID || 114 info.device_id == CMEDIA_8338B_DEVICE_ID || 115 info.device_id == CMEDIA_8738A_DEVICE_ID || 116 info.device_id == CMEDIA_8738B_DEVICE_ID )) { 117 err = B_OK; 118 } 119 ix++; 120 } 121 #if defined(__POWERPC__) && 0 122 { 123 char area_name [32]; 124 area_info area; 125 area_id id; 126 127 sprintf (area_name, "pci_bus%d_isa_io", info.bus); 128 id = find_area (area_name); 129 if (id < 0) 130 err = id; 131 else if ((err = get_area_info (id, &area)) == B_OK) 132 io_base = area.address; 133 } 134 #endif 135 136 put_module(pci_name); 137 138 return err; 139 } 140 141 142 void set_direct(cmedia_pci_dev * card, int regno, uchar value, uchar mask) 143 { 144 if (mask == 0) { 145 return; 146 } 147 if (mask != 0xff) { 148 uchar old = PCI_IO_RD(card->enhanced+regno); 149 value = (value&mask)|(old&~mask); 150 } 151 PCI_IO_WR(card->enhanced+regno, value); 152 ddprintf(("cmedia_pci: CM%02x = %02x\n", regno, value)); 153 } 154 155 156 uchar get_direct(cmedia_pci_dev * card, int regno) 157 { 158 uchar ret = PCI_IO_RD(card->enhanced+regno); 159 return ret; 160 } 161 162 163 164 void set_indirect(cmedia_pci_dev * card, int regno, uchar value, uchar mask) 165 { 166 PCI_IO_WR(card->enhanced+0x23, regno); 167 EIEIO(); 168 if (mask == 0) { 169 return; 170 } 171 if (mask != 0xff) { 172 uchar old = PCI_IO_RD(card->enhanced+0x22); 173 value = (value&mask)|(old&~mask); 174 } 175 PCI_IO_WR(card->enhanced+0x22, value); 176 EIEIO(); 177 ddprintf(("cmedia_pci: CMX%02x = %02x\n", regno, value)); 178 } 179 180 181 182 uchar get_indirect(cmedia_pci_dev * card,int regno) 183 { 184 uchar ret; 185 PCI_IO_WR(card->enhanced+0x23, regno); 186 EIEIO(); 187 ret = PCI_IO_RD(card->enhanced+0x22); 188 return ret; 189 } 190 191 192 #if 0 193 void dump_card(cmedia_pci_dev * card) 194 { 195 int ix; 196 dprintf("\n"); 197 dprintf("CM: "); 198 for (ix=0; ix<6; ix++) { 199 if (ix == 2 || ix == 3) dprintf(" "); 200 else dprintf(" %02x", get_direct(card, ix)); 201 } 202 for (ix=0; ix<0x32; ix++) { 203 if (!(ix & 7)) { 204 dprintf("\nCMX%02x:", ix); 205 } 206 dprintf(" %02x", get_indirect(card, ix)); 207 } 208 dprintf("\n"); 209 dprintf("\n"); 210 } 211 #else 212 void dump_card(cmedia_pci_dev * card) 213 { 214 } 215 #endif 216 217 218 static void 219 disable_card_interrupts(cmedia_pci_dev * card) 220 { 221 set_direct(card, 0x0e, 0x00, 0x03); 222 } 223 224 225 static status_t 226 setup_dma(cmedia_pci_dev * card) 227 { 228 /* we're appropriating some ISA space here... */ 229 /* need kernel support to do it right */ 230 const uint16 base = card->enhanced + 0x80; 231 ddprintf(("cmedia_pci: dma base is 0x%04x\n", base)); 232 if (base == 0) 233 return B_DEV_RESOURCE_CONFLICT; 234 card->dma_base = base; 235 return B_OK; 236 } 237 238 239 static void 240 set_default_registers(cmedia_pci_dev * card) 241 { 242 static uchar values[] = { 243 #ifdef DO_JOY 244 0x04, 0x02, 0x02, /* enable joystick */ 245 #endif 246 247 0x0a, 0x01, 0x01, /* enable SPDIF inverse before SPDIF_LOOP */ 248 0x04, 0x80, 0x80, /* enable SPDIF_LOOP */ 249 250 0x1a, 0x00, 0x20, /* SPD32SEL disable */ 251 0x1a, 0x00, 0x10, /* SPDFLOOPI disable */ 252 253 0x1b, 0x04, 0x04, /* dual channel mode enable */ 254 0x1a, 0x00, 0x80, /* Double DAC structure disable */ 255 256 0x24, 0x00, 0x02, /* 3D surround disable */ 257 258 0x24, 0x00, 0x01, /* disable SPDIF_IN PCM to DAC */ 259 #ifdef DO_MIDI 260 0x04, 0x04, 0x04, /* enable MPU-401 */ 261 0x17, 0x00, 0x60, /* default at 0x330 */ 262 #endif 263 }; 264 uchar * ptr = values; 265 266 while (ptr < values+sizeof(values)) { 267 set_direct(card, ptr[0], ptr[1], ptr[2]); 268 ptr += 3; 269 } 270 } 271 272 273 static void 274 make_device_names(cmedia_pci_dev * card) 275 { 276 char * name = card->name; 277 sprintf(name, "cmedia_pci/%ld", card-cards + 1); 278 279 #if DO_MIDI 280 sprintf(card->midi.name, "midi/%s", name); 281 names[num_names++] = card->midi.name; 282 #endif /* DO_MIDI */ 283 #if DO_JOY 284 sprintf(card->joy.name1, "joystick/%s", name); 285 names[num_names++] = card->joy.name1; 286 #endif /* DO_JOY */ 287 #if DO_PCM 288 /* cmedia_pci DMA doesn't work when physical NULL isn't NULL from PCI */ 289 /* this is a hack to not export bad devices on BeBox hardware */ 290 if ((*pci->ram_address)(NULL) == NULL) { 291 sprintf(card->pcm.name, "audio/raw/%s", name); 292 names[num_names++] = card->pcm.name; 293 sprintf(card->pcm.oldname, "audio/old/%s", name); 294 names[num_names++] = card->pcm.oldname; 295 } 296 #endif /* DO_PCM */ 297 #if DO_MUX 298 sprintf(card->mux.name, "audio/mux/%s", name); 299 names[num_names++] = card->mux.name; 300 #endif /* DO_MUX */ 301 #if DO_MIXER 302 sprintf(card->mixer.name, "audio/mix/%s", name); 303 names[num_names++] = card->mixer.name; 304 #endif /* DO_MIXER */ 305 names[num_names] = NULL; 306 } 307 308 309 /* We use the SV chip in ISA DMA addressing mode, which is 24 bits */ 310 /* so we need to find suitable, locked, contiguous memory in that */ 311 /* physical address range. */ 312 313 static status_t 314 find_low_memory(cmedia_pci_dev * card) 315 { 316 size_t low_size = (MIN_MEMORY_SIZE + (B_PAGE_SIZE - 1)) 317 &~ (B_PAGE_SIZE - 1); 318 physical_entry where; 319 size_t trysize; 320 area_id curarea; 321 void * addr; 322 char name[DEVNAME]; 323 324 sprintf(name, "%s_low", card->name); 325 if (low_size < MIN_MEMORY_SIZE) { 326 low_size = MIN_MEMORY_SIZE; 327 } 328 trysize = low_size; 329 330 curarea = find_area(name); 331 if (curarea >= 0) { /* area there from previous run */ 332 area_info ainfo; 333 ddprintf(("cmedia_pci: testing likely candidate...\n")); 334 if (get_area_info(curarea, &ainfo)) { 335 ddprintf(("cmedia_pci: no info\n")); 336 goto allocate; 337 } 338 /* test area we found */ 339 trysize = ainfo.size; 340 addr = ainfo.address; 341 if (trysize < low_size) { 342 ddprintf(("cmedia_pci: too small (%lx)\n", trysize)); 343 goto allocate; 344 } 345 if (get_memory_map(addr, trysize, &where, 1) < B_OK) { 346 ddprintf(("cmedia_pci: no memory map\n")); 347 goto allocate; 348 } 349 if ((where.address & ~(phys_addr_t)0xffffff) != 0) { 350 ddprintf(("cmedia_pci: bad physical address\n")); 351 goto allocate; 352 } 353 if (ainfo.lock < B_FULL_LOCK || where.size < low_size) { 354 ddprintf(("cmedia_pci: lock not contiguous\n")); 355 goto allocate; 356 } 357 dprintf("cmedia_pci: physical %#" B_PRIxPHYSADDR " logical %p\n", 358 where.address, ainfo.address); 359 goto a_o_k; 360 } 361 362 allocate: 363 if (curarea >= 0) { 364 delete_area(curarea); /* area didn't work */ 365 curarea = -1; 366 } 367 ddprintf(("cmedia_pci: allocating new low area\n")); 368 369 curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS, 370 trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA); 371 ddprintf(("cmedia_pci: create_area(%lx) returned %lx logical %p\n", 372 trysize, curarea, addr)); 373 if (curarea < 0) { 374 goto oops; 375 } 376 if (get_memory_map(addr, low_size, &where, 1) < 0) { 377 delete_area(curarea); 378 curarea = B_ERROR; 379 goto oops; 380 } 381 ddprintf(("cmedia_pci: physical %p\n", where.address)); 382 if ((where.address & ~(phys_addr_t)0xffffff) != 0) { 383 delete_area(curarea); 384 curarea = B_ERROR; 385 goto oops; 386 } 387 if (((where.address + low_size) & ~(phys_addr_t)0xffffff) != 0) { 388 delete_area(curarea); 389 curarea = B_ERROR; 390 goto oops; 391 } 392 /* hey, it worked! */ 393 if (trysize > low_size) { /* don't waste */ 394 resize_area(curarea, low_size); 395 } 396 397 oops: 398 if (curarea < 0) { 399 dprintf("cmedia_pci: failed to create low_mem area\n"); 400 return curarea; 401 } 402 a_o_k: 403 ddprintf(("cmedia_pci: successfully found or created low area!\n")); 404 card->low_size = low_size; 405 card->low_mem = addr; 406 card->low_phys = (vuchar *)(addr_t)where.address; 407 card->map_low = curarea; 408 return B_OK; 409 } 410 411 412 static status_t 413 setup_cmedia_pci(cmedia_pci_dev * card) 414 { 415 status_t err = B_OK; 416 /* cpu_status cp; */ 417 418 ddprintf(("cmedia_pci: setup_cmedia_pci(%p)\n", card)); 419 420 if ((card->pcm.init_sem = create_sem(1, "cm pcm init")) < B_OK) 421 goto bail; 422 #if 1 423 if ((*mpu401->create_device)(0x330, &card->midi.driver, 424 #else 425 if ((*mpu401->create_device)(card->info.u.h0.base_registers[3], &card->midi.driver, 426 #endif 427 0, midi_interrupt_op, &card->midi) < B_OK) 428 goto bail3; 429 #if 1 430 if ((*gameport->create_device)(0x201, &card->joy.driver) < B_OK) 431 #else 432 if ((*gameport->create_device)(card->info.u.h0.base_registers[4], &card->joy.driver) < B_OK) 433 #endif 434 goto bail4; 435 ddprintf(("midi %p gameport %p\n", card->midi.driver, card->joy.driver)); 436 card->midi.card = card; 437 438 err = find_low_memory(card); 439 if (err < B_OK) { 440 goto bail5; 441 } 442 443 //cp = disable_interrupts(); 444 //acquire_spinlock(&card->hardware); 445 446 make_device_names(card); 447 card->enhanced = card->info.u.h0.base_registers[0]; 448 ddprintf(("cmedia_pci: %s enhanced at %x\n", card->name, card->enhanced)); 449 450 ddprintf(("cmedia_pci: revision %x\n", get_indirect(card, 0x15))); 451 452 disable_card_interrupts(card); 453 if (setup_dma(card) != B_OK) { 454 dprintf("cmedia pci: can't setup DMA\n"); 455 goto bail6; 456 } 457 458 set_default_registers(card); 459 460 //release_spinlock(&card->hardware); 461 //restore_interrupts(cp); 462 463 return B_OK; 464 465 bail6: 466 // deallocate low memory 467 bail5: 468 (*gameport->delete_device)(card->joy.driver); 469 bail4: 470 (*mpu401->delete_device)(card->midi.driver); 471 bail3: 472 delete_sem(card->pcm.init_sem); 473 bail: 474 return err < B_OK ? err : B_ERROR; 475 } 476 477 478 static int 479 debug_cmedia(int argc, char * argv[]) 480 { 481 int ix = 0; 482 if (argc == 2) { 483 ix = parse_expression(argv[1]) - 1; 484 } 485 if (argc > 2 || ix < 0 || ix >= num_cards) { 486 dprintf("cmedia_pci: dude, you gotta watch your syntax!\n"); 487 return -1; 488 } 489 dprintf("%s: enhanced registers at 0x%x\n", cards[ix].name, 490 cards[ix].enhanced); 491 dprintf("%s: open %ld dma_a at 0x%x dma_c 0x%x\n", cards[ix].pcm.name, 492 cards[ix].pcm.open_count, cards[ix].pcm.dma_a, cards[ix].pcm.dma_c); 493 if (cards[ix].pcm.open_count) { 494 dprintf(" dma_a: 0x%lx+0x%lx dma_c: 0x%lx+0x%lx\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 %ld 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