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 21EXPORT status_t init_hardware(void); 22EXPORT status_t init_driver(void); 23EXPORT void uninit_driver(void); 24EXPORT const char ** publish_devices(void); 25EXPORT device_hooks * find_device(const char *); 26 27 28static char pci_name[] = B_PCI_MODULE_NAME; 29static pci_module_info *pci; 30static char gameport_name[] = "generic/gameport/v1"; 31generic_gameport_module * gameport; 32static char mpu401_name[] = B_MPU_401_MODULE_NAME; 33generic_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 42extern device_hooks midi_hooks; 43#endif /* DO_MIDI */ 44#if DO_JOY 45extern device_hooks joy_hooks; 46#endif /* DO_JOY */ 47#if DO_PCM 48extern device_hooks pcm_hooks; 49#endif /* DO_PCM */ 50#if DO_MUX 51extern device_hooks mux_hooks; 52#endif /* DO_MUX */ 53#if DO_MIXER 54extern device_hooks mixer_hooks; 55#endif /* DO_MIXER */ 56 57 58int32 num_cards; 59cmedia_pci_dev cards[NUM_CARDS]; 60int num_names; 61char * 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 69uint8 70PCI_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 80uint32 81PCI_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 89void 90PCI_IO_WR (int offset, uint8 val) 91{ 92 (*pci->write_io_8) (offset, val); 93} 94 95 96/* detect presence of our hardware */ 97status_t 98init_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 140void 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 154uchar 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 162void 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 180uchar 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 190void dump_card(cmedia_pci_dev* card); 191#if 0 192void 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 211void dump_card(cmedia_pci_dev* card) 212{ 213} 214#endif 215 216 217static void 218disable_card_interrupts(cmedia_pci_dev * card) 219{ 220 set_direct(card, 0x0e, 0x00, 0x03); 221} 222 223 224static status_t 225setup_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 238static void 239set_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 272static void 273make_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 312static status_t 313find_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 } 356dprintf("cmedia_pci: physical %#" B_PRIxPHYSADDR " logical %p\n", 357where.address, ainfo.address); 358 goto a_o_k; 359 } 360 361allocate: 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 396oops: 397 if (curarea < 0) { 398 dprintf("cmedia_pci: failed to create low_mem area\n"); 399 return curarea; 400 } 401a_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 411static status_t 412setup_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 464bail6: 465 // deallocate low memory 466bail5: 467 (*gameport->delete_device)(card->joy.driver); 468bail4: 469 (*mpu401->delete_device)(card->midi.driver); 470bail3: 471 delete_sem(card->pcm.init_sem); 472bail: 473 return err < B_OK ? err : B_ERROR; 474} 475 476 477static int 478debug_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 502status_t 503init_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 579static void 580teardown_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 618void 619uninit_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 637const char ** 638publish_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 650device_hooks * 651find_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 692int32 api_version = B_CUR_DRIVER_API_VERSION; 693 694static int32 695cmedia_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 766void 767increment_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 779void 780decrement_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