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 #if 0 191 void dump_card(cmedia_pci_dev * card) 192 { 193 int ix; 194 dprintf("\n"); 195 dprintf("CM: "); 196 for (ix=0; ix<6; ix++) { 197 if (ix == 2 || ix == 3) dprintf(" "); 198 else dprintf(" %02x", get_direct(card, ix)); 199 } 200 for (ix=0; ix<0x32; ix++) { 201 if (!(ix & 7)) { 202 dprintf("\nCMX%02x:", ix); 203 } 204 dprintf(" %02x", get_indirect(card, ix)); 205 } 206 dprintf("\n"); 207 dprintf("\n"); 208 } 209 #else 210 void dump_card(cmedia_pci_dev * card) 211 { 212 } 213 #endif 214 215 216 static void 217 disable_card_interrupts(cmedia_pci_dev * card) 218 { 219 set_direct(card, 0x0e, 0x00, 0x03); 220 } 221 222 223 static status_t 224 setup_dma(cmedia_pci_dev * card) 225 { 226 /* we're appropriating some ISA space here... */ 227 /* need kernel support to do it right */ 228 const uint16 base = card->enhanced + 0x80; 229 ddprintf(("cmedia_pci: dma base is 0x%04x\n", base)); 230 if (base == 0) 231 return B_DEV_RESOURCE_CONFLICT; 232 card->dma_base = base; 233 return B_OK; 234 } 235 236 237 static void 238 set_default_registers(cmedia_pci_dev * card) 239 { 240 static uchar values[] = { 241 #ifdef DO_JOY 242 0x04, 0x02, 0x02, /* enable joystick */ 243 #endif 244 245 0x0a, 0x01, 0x01, /* enable SPDIF inverse before SPDIF_LOOP */ 246 0x04, 0x80, 0x80, /* enable SPDIF_LOOP */ 247 248 0x1a, 0x00, 0x20, /* SPD32SEL disable */ 249 0x1a, 0x00, 0x10, /* SPDFLOOPI disable */ 250 251 0x1b, 0x04, 0x04, /* dual channel mode enable */ 252 0x1a, 0x00, 0x80, /* Double DAC structure disable */ 253 254 0x24, 0x00, 0x02, /* 3D surround disable */ 255 256 0x24, 0x00, 0x01, /* disable SPDIF_IN PCM to DAC */ 257 #ifdef DO_MIDI 258 0x04, 0x04, 0x04, /* enable MPU-401 */ 259 0x17, 0x00, 0x60, /* default at 0x330 */ 260 #endif 261 }; 262 uchar * ptr = values; 263 264 while (ptr < values+sizeof(values)) { 265 set_direct(card, ptr[0], ptr[1], ptr[2]); 266 ptr += 3; 267 } 268 } 269 270 271 static void 272 make_device_names(cmedia_pci_dev * card) 273 { 274 char * name = card->name; 275 sprintf(name, "cmedia_pci/%ld", card-cards + 1); 276 277 #if DO_MIDI 278 sprintf(card->midi.name, "midi/%s", name); 279 names[num_names++] = card->midi.name; 280 #endif /* DO_MIDI */ 281 #if DO_JOY 282 sprintf(card->joy.name1, "joystick/%s", name); 283 names[num_names++] = card->joy.name1; 284 #endif /* DO_JOY */ 285 #if DO_PCM 286 /* cmedia_pci DMA doesn't work when physical NULL isn't NULL from PCI */ 287 /* this is a hack to not export bad devices on BeBox hardware */ 288 if ((*pci->ram_address)(NULL) == NULL) { 289 sprintf(card->pcm.name, "audio/raw/%s", name); 290 names[num_names++] = card->pcm.name; 291 sprintf(card->pcm.oldname, "audio/old/%s", name); 292 names[num_names++] = card->pcm.oldname; 293 } 294 #endif /* DO_PCM */ 295 #if DO_MUX 296 sprintf(card->mux.name, "audio/mux/%s", name); 297 names[num_names++] = card->mux.name; 298 #endif /* DO_MUX */ 299 #if DO_MIXER 300 sprintf(card->mixer.name, "audio/mix/%s", name); 301 names[num_names++] = card->mixer.name; 302 #endif /* DO_MIXER */ 303 names[num_names] = NULL; 304 } 305 306 307 /* We use the SV chip in ISA DMA addressing mode, which is 24 bits */ 308 /* so we need to find suitable, locked, contiguous memory in that */ 309 /* physical address range. */ 310 311 static status_t 312 find_low_memory(cmedia_pci_dev * card) 313 { 314 size_t low_size = (MIN_MEMORY_SIZE + (B_PAGE_SIZE - 1)) 315 &~ (B_PAGE_SIZE - 1); 316 physical_entry where; 317 size_t trysize; 318 area_id curarea; 319 void * addr; 320 char name[DEVNAME]; 321 322 sprintf(name, "%s_low", card->name); 323 if (low_size < MIN_MEMORY_SIZE) { 324 low_size = MIN_MEMORY_SIZE; 325 } 326 trysize = low_size; 327 328 curarea = find_area(name); 329 if (curarea >= 0) { /* area there from previous run */ 330 area_info ainfo; 331 ddprintf(("cmedia_pci: testing likely candidate...\n")); 332 if (get_area_info(curarea, &ainfo)) { 333 ddprintf(("cmedia_pci: no info\n")); 334 goto allocate; 335 } 336 /* test area we found */ 337 trysize = ainfo.size; 338 addr = ainfo.address; 339 if (trysize < low_size) { 340 ddprintf(("cmedia_pci: too small (%lx)\n", trysize)); 341 goto allocate; 342 } 343 if (get_memory_map(addr, trysize, &where, 1) < B_OK) { 344 ddprintf(("cmedia_pci: no memory map\n")); 345 goto allocate; 346 } 347 if ((where.address & ~(phys_addr_t)0xffffff) != 0) { 348 ddprintf(("cmedia_pci: bad physical address\n")); 349 goto allocate; 350 } 351 if (ainfo.lock < B_FULL_LOCK || where.size < low_size) { 352 ddprintf(("cmedia_pci: lock not contiguous\n")); 353 goto allocate; 354 } 355 dprintf("cmedia_pci: physical %#" B_PRIxPHYSADDR " logical %p\n", 356 where.address, ainfo.address); 357 goto a_o_k; 358 } 359 360 allocate: 361 if (curarea >= 0) { 362 delete_area(curarea); /* area didn't work */ 363 curarea = -1; 364 } 365 ddprintf(("cmedia_pci: allocating new low area\n")); 366 367 curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS, 368 trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA); 369 ddprintf(("cmedia_pci: create_area(%lx) returned %lx logical %p\n", 370 trysize, curarea, addr)); 371 if (curarea < 0) { 372 goto oops; 373 } 374 if (get_memory_map(addr, low_size, &where, 1) < 0) { 375 delete_area(curarea); 376 curarea = B_ERROR; 377 goto oops; 378 } 379 ddprintf(("cmedia_pci: physical %p\n", where.address)); 380 if ((where.address & ~(phys_addr_t)0xffffff) != 0) { 381 delete_area(curarea); 382 curarea = B_ERROR; 383 goto oops; 384 } 385 if (((where.address + low_size) & ~(phys_addr_t)0xffffff) != 0) { 386 delete_area(curarea); 387 curarea = B_ERROR; 388 goto oops; 389 } 390 /* hey, it worked! */ 391 if (trysize > low_size) { /* don't waste */ 392 resize_area(curarea, low_size); 393 } 394 395 oops: 396 if (curarea < 0) { 397 dprintf("cmedia_pci: failed to create low_mem area\n"); 398 return curarea; 399 } 400 a_o_k: 401 ddprintf(("cmedia_pci: successfully found or created low area!\n")); 402 card->low_size = low_size; 403 card->low_mem = addr; 404 card->low_phys = (vuchar *)(addr_t)where.address; 405 card->map_low = curarea; 406 return B_OK; 407 } 408 409 410 static status_t 411 setup_cmedia_pci(cmedia_pci_dev * card) 412 { 413 status_t err = B_OK; 414 /* cpu_status cp; */ 415 416 ddprintf(("cmedia_pci: setup_cmedia_pci(%p)\n", card)); 417 418 if ((card->pcm.init_sem = create_sem(1, "cm pcm init")) < B_OK) 419 goto bail; 420 #if 1 421 if ((*mpu401->create_device)(0x330, &card->midi.driver, 422 #else 423 if ((*mpu401->create_device)(card->info.u.h0.base_registers[3], &card->midi.driver, 424 #endif 425 0, midi_interrupt_op, &card->midi) < B_OK) 426 goto bail3; 427 #if 1 428 if ((*gameport->create_device)(0x201, &card->joy.driver) < B_OK) 429 #else 430 if ((*gameport->create_device)(card->info.u.h0.base_registers[4], &card->joy.driver) < B_OK) 431 #endif 432 goto bail4; 433 ddprintf(("midi %p gameport %p\n", card->midi.driver, card->joy.driver)); 434 card->midi.card = card; 435 436 err = find_low_memory(card); 437 if (err < B_OK) { 438 goto bail5; 439 } 440 441 //cp = disable_interrupts(); 442 //acquire_spinlock(&card->hardware); 443 444 make_device_names(card); 445 card->enhanced = card->info.u.h0.base_registers[0]; 446 ddprintf(("cmedia_pci: %s enhanced at %x\n", card->name, card->enhanced)); 447 448 ddprintf(("cmedia_pci: revision %x\n", get_indirect(card, 0x15))); 449 450 disable_card_interrupts(card); 451 if (setup_dma(card) != B_OK) { 452 dprintf("cmedia pci: can't setup DMA\n"); 453 goto bail6; 454 } 455 456 set_default_registers(card); 457 458 //release_spinlock(&card->hardware); 459 //restore_interrupts(cp); 460 461 return B_OK; 462 463 bail6: 464 // deallocate low memory 465 bail5: 466 (*gameport->delete_device)(card->joy.driver); 467 bail4: 468 (*mpu401->delete_device)(card->midi.driver); 469 bail3: 470 delete_sem(card->pcm.init_sem); 471 bail: 472 return err < B_OK ? err : B_ERROR; 473 } 474 475 476 static int 477 debug_cmedia(int argc, char * argv[]) 478 { 479 int ix = 0; 480 if (argc == 2) { 481 ix = parse_expression(argv[1]) - 1; 482 } 483 if (argc > 2 || ix < 0 || ix >= num_cards) { 484 dprintf("cmedia_pci: dude, you gotta watch your syntax!\n"); 485 return -1; 486 } 487 dprintf("%s: enhanced registers at 0x%x\n", cards[ix].name, 488 cards[ix].enhanced); 489 dprintf("%s: open %ld dma_a at 0x%x dma_c 0x%x\n", cards[ix].pcm.name, 490 cards[ix].pcm.open_count, cards[ix].pcm.dma_a, cards[ix].pcm.dma_c); 491 if (cards[ix].pcm.open_count) { 492 dprintf(" dma_a: 0x%lx+0x%lx dma_c: 0x%lx+0x%lx\n", 493 PCI_IO_RD_32((int)cards[ix].pcm.dma_a), PCI_IO_RD_32((int)cards[ix].pcm.dma_a+4), 494 PCI_IO_RD_32((int)cards[ix].pcm.dma_c), PCI_IO_RD_32((int)cards[ix].pcm.dma_c+4)); 495 } 496 return 0; 497 } 498 499 500 status_t 501 init_driver(void) 502 { 503 pci_info info; 504 int ix = 0; 505 status_t err; 506 507 num_cards = 0; 508 509 ddprintf(("cmedia_pci: init_driver()\n")); 510 511 if (get_module(pci_name, (module_info **)&pci)) 512 return ENOSYS; 513 514 if (get_module(gameport_name, (module_info **)&gameport)) { 515 put_module(pci_name); 516 return ENOSYS; 517 } 518 ddprintf(("MPU\n")); 519 if (get_module(mpu401_name, (module_info **)&mpu401)) { 520 put_module(gameport_name); 521 put_module(pci_name); 522 return ENOSYS; 523 } 524 525 ddprintf(("MPU: %p\n", mpu401)); 526 527 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 528 if (info.vendor_id == CMEDIA_PCI_VENDOR_ID && 529 (info.device_id == CMEDIA_8338A_DEVICE_ID || 530 info.device_id == CMEDIA_8338B_DEVICE_ID || 531 info.device_id == CMEDIA_8738A_DEVICE_ID || 532 info.device_id == CMEDIA_8738B_DEVICE_ID )) { 533 if (num_cards == NUM_CARDS) { 534 dprintf("Too many C-Media cards installed!\n"); 535 break; 536 } 537 memset(&cards[num_cards], 0, sizeof(cmedia_pci_dev)); 538 cards[num_cards].info = info; 539 #ifdef __HAIKU__ 540 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 541 DRIVER_NAME, &cards[num_cards])) < B_OK) { 542 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 543 DRIVER_NAME, info.bus, info.device, info.function, 544 strerror(err)); 545 continue; 546 } 547 #endif 548 if (setup_cmedia_pci(&cards[num_cards])) { 549 dprintf("Setup of C-Media %ld failed\n", num_cards+1); 550 #ifdef __HAIKU__ 551 (*pci->unreserve_device)(info.bus, info.device, info.function, 552 DRIVER_NAME, &cards[num_cards]); 553 #endif 554 } 555 else { 556 num_cards++; 557 } 558 } 559 ix++; 560 } 561 if (!num_cards) { 562 KPRINTF(("no cards\n")); 563 put_module(mpu401_name); 564 put_module(gameport_name); 565 put_module(pci_name); 566 ddprintf(("cmedia_pci: no suitable cards found\n")); 567 return ENODEV; 568 } 569 570 #if DEBUG 571 add_debugger_command("cmedia", debug_cmedia, "cmedia [card# (1-n)]"); 572 #endif 573 return B_OK; 574 } 575 576 577 static void 578 teardown_cmedia_pci(cmedia_pci_dev * card) 579 { 580 static uchar regs[] = { 581 #ifdef DO_JOY 582 0x04, 0x00, 0x02, /* enable joystick */ 583 #endif 584 #ifdef DO_MIDI 585 0x04, 0x00, 0x04, /* enable MPU-401 */ 586 #endif 587 }; 588 uchar * ptr = regs; 589 cpu_status cp; 590 591 /* remove created devices */ 592 (*gameport->delete_device)(card->joy.driver); 593 (*mpu401->delete_device)(card->midi.driver); 594 595 cp = disable_interrupts(); 596 acquire_spinlock(&card->hardware); 597 598 while (ptr < regs + sizeof(regs)) { 599 set_direct(card, ptr[0], ptr[1], ptr[2]); 600 ptr += 3; 601 } 602 disable_card_interrupts(card); 603 604 release_spinlock(&card->hardware); 605 restore_interrupts(cp); 606 607 delete_sem(card->pcm.init_sem); 608 609 #ifdef __HAIKU__ 610 (*pci->unreserve_device)(card->info.bus, card->info.device, 611 card->info.function, DRIVER_NAME, card); 612 #endif 613 } 614 615 616 void 617 uninit_driver(void) 618 { 619 int ix, cnt = num_cards; 620 num_cards = 0; 621 622 ddprintf(("cmedia_pci: uninit_driver()\n")); 623 remove_debugger_command("cmedia", debug_cmedia); 624 625 for (ix = 0; ix < cnt; ix++) { 626 teardown_cmedia_pci(&cards[ix]); 627 } 628 memset(&cards, 0, sizeof(cards)); 629 put_module(mpu401_name); 630 put_module(gameport_name); 631 put_module(pci_name); 632 } 633 634 635 const char ** 636 publish_devices(void) 637 { 638 int ix = 0; 639 ddprintf(("cmedia_pci: publish_devices()\n")); 640 641 for (ix = 0; names[ix]; ix++) { 642 ddprintf(("cmedia_pci: publish %s\n", names[ix])); 643 } 644 return (const char **)names; 645 } 646 647 648 device_hooks * 649 find_device(const char * name) 650 { 651 int ix; 652 653 ddprintf(("cmedia_pci: find_device(%s)\n", name)); 654 655 for (ix = 0; ix < num_cards; ix++) { 656 #if DO_MIDI 657 if (!strcmp(cards[ix].midi.name, name)) { 658 return &midi_hooks; 659 } 660 #endif /* DO_MIDI */ 661 #if DO_JOY 662 if (!strcmp(cards[ix].joy.name1, name)) { 663 return &joy_hooks; 664 } 665 #endif /* DO_JOY */ 666 #if DO_PCM 667 if (!strcmp(cards[ix].pcm.name, name)) { 668 return &pcm_hooks; 669 } 670 if (!strcmp(cards[ix].pcm.oldname, name)) { 671 return &pcm_hooks; 672 } 673 #endif /* DO_PCM */ 674 #if DO_MUX 675 if (!strcmp(cards[ix].mux.name, name)) { 676 return &mux_hooks; 677 } 678 679 #endif /* DO_MUX */ 680 #if DO_MIXER 681 if (!strcmp(cards[ix].mixer.name, name)) { 682 return &mixer_hooks; 683 } 684 #endif /* DO_MIXER */ 685 } 686 ddprintf(("cmedia_pci: find_device(%s) failed\n", name)); 687 return NULL; 688 } 689 690 int32 api_version = B_CUR_DRIVER_API_VERSION; 691 692 static int32 693 cmedia_pci_interrupt(void * data) 694 { 695 cpu_status cp = disable_interrupts(); 696 cmedia_pci_dev * card = (cmedia_pci_dev *)data; 697 uchar status; 698 int32 handled = B_UNHANDLED_INTERRUPT; 699 700 /* KTRACE(); / * */ 701 acquire_spinlock(&card->hardware); 702 703 status = get_direct(card, 0x10); 704 705 #if DEBUG 706 /* kprintf("%x\n", status); / * */ 707 #endif 708 #if DO_PCM 709 if (status & 0x02) { 710 if (dma_c_interrupt(card)) { 711 handled = B_INVOKE_SCHEDULER; 712 } 713 else { 714 handled = B_HANDLED_INTERRUPT; 715 } 716 /* acknowledge interrupt */ 717 set_direct(card, 0x0e, 0x00, 0x02); 718 set_direct(card, 0x0e, 0x02, 0x02); 719 } 720 if (status & 0x01) { 721 if (dma_a_interrupt(card)) { 722 handled = B_INVOKE_SCHEDULER; 723 } 724 else { 725 handled = B_HANDLED_INTERRUPT; 726 } 727 /* acknowledge interrupt */ 728 set_direct(card, 0x0e, 0x00, 0x01); 729 set_direct(card, 0x0e, 0x01, 0x01); 730 } 731 #endif 732 #if DO_MIDI 733 status = get_direct(card, 0x12); 734 if (status & 0x01) { 735 if (midi_interrupt(card)) { 736 handled = B_INVOKE_SCHEDULER; 737 } else { 738 handled = B_HANDLED_INTERRUPT; 739 } 740 } 741 #endif 742 743 /* Sometimes, the Sonic Vibes will receive a byte of Midi data... 744 ** And duly note it in the MPU401 status register... 745 ** And generate an interrupt... 746 ** But not bother setting the midi interrupt bit in the ISR. 747 ** Thanks a lot, S3. 748 */ 749 if (handled == B_UNHANDLED_INTERRUPT) { 750 if (midi_interrupt(card)) { 751 handled = B_INVOKE_SCHEDULER; 752 } 753 } 754 755 /* KTRACE(); / * */ 756 release_spinlock(&card->hardware); 757 restore_interrupts(cp); 758 759 return handled; 760 // return (handled == B_INVOKE_SCHEDULER) ? B_HANDLED_INTERRUPT : handled; 761 } 762 763 764 void 765 increment_interrupt_handler(cmedia_pci_dev * card) 766 { 767 KPRINTF(("cmedia_pci: increment_interrupt_handler()\n")); 768 if (atomic_add(&card->inth_count, 1) == 0) { 769 // !!! 770 KPRINTF(("cmedia_pci: intline %d int %p\n", card->info.u.h0.interrupt_line, cmedia_pci_interrupt)); 771 install_io_interrupt_handler(card->info.u.h0.interrupt_line, 772 cmedia_pci_interrupt, card, 0); 773 } 774 } 775 776 777 void 778 decrement_interrupt_handler(cmedia_pci_dev * card) 779 { 780 KPRINTF(("cmedia_pci: decrement_interrupt_handler()\n")); 781 if (atomic_add(&card->inth_count, -1) == 1) { 782 KPRINTF(("cmedia_pci: remove_io_interrupt_handler()\n")); 783 remove_io_interrupt_handler(card->info.u.h0.interrupt_line, cmedia_pci_interrupt, card); 784 } 785 } 786 787 788