📄 sb_card.c
字号:
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110), ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110), ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110), ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120), ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120), ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120), ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200), ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200), ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020), 0 }, { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200), ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 }, { ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000), ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 }, { ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000), ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 }, { ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000), ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 }, {0}};MODULE_DEVICE_TABLE(isapnp, id_table);static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev){ int err; /* Device already active? Let's use it */ if(dev->active) return(dev); if((err = dev->activate(dev)) < 0) { printk(KERN_ERR "sb: %s %s config failed (out of resources?)[%d]\n", devname, resname, err); dev->deactivate(dev); return(NULL); } return(dev);}static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_config, struct address_info *mpu_config, int slot, int card){ /* Configure Audio device */ if((sb_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].audio_vendor, sb_isapnp_list[slot].audio_function, NULL))) { int ret; ret = sb_dev[card]->prepare(sb_dev[card]); /* If device is active, assume configured with /proc/isapnp * and use anyway. Some other way to check this? */ if(ret && ret != -EBUSY) { printk(KERN_ERR "sb: ISAPnP found device that could not be autoconfigured.\n"); return(NULL); } if(ret == -EBUSY) audio_activated[card] = 1; if((sb_dev[card] = activate_dev(sb_isapnp_list[slot].name, "sb", sb_dev[card]))) { hw_config->io_base = sb_dev[card]->resource[0].start; hw_config->irq = sb_dev[card]->irq_resource[0].start; hw_config->dma = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma].start; if(sb_isapnp_list[slot].dma2 != -1) hw_config->dma2 = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma2].start; else hw_config->dma2 = -1; } else return(NULL); } else return(NULL); /* Cards with separate OPL3 device (ALS, CMI, etc.) * This is just to activate the device so the OPL module can use it */ if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) { if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) { int ret = opl_dev[card]->prepare(opl_dev[card]); /* If device is active, assume configured with * /proc/isapnp and use anyway */ if(ret && ret != -EBUSY) { printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n"); return(sb_dev[card]); } if(ret == -EBUSY) opl_activated[card] = 1; /* Some have irq and dma for opl. the opl3 driver wont * use 'em so don't configure 'em and hope it works -PEL */ opl_dev[card]->irq_resource[0].flags = 0; opl_dev[card]->dma_resource[0].flags = 0; opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]); } else printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name); } /* Cards with MPU as part of Audio device (CTL and ESS) */ if(!sb_isapnp_list[slot].mpu_vendor) { mpu_config->io_base = sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start; return(sb_dev[card]); } /* Cards with separate MPU device (ALS, CMI, etc.) */ if(!uart401) return(sb_dev[card]); if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL))) { int ret = mpu_dev[card]->prepare(mpu_dev[card]); /* If device is active, assume configured with /proc/isapnp * and use anyway */ if(ret && ret != -EBUSY) { printk(KERN_ERR "sb: MPU device could not be autoconfigured.\n"); return(sb_dev[card]); } if(ret == -EBUSY) mpu_activated[card] = 1; /* Some cards ask for irq but don't need them - azummo */ if(sb_isapnp_list[slot].mpu_irq == -1) mpu_dev[card]->irq_resource[0].flags = 0; if((mpu_dev[card] = activate_dev(sb_isapnp_list[slot].name, "mpu", mpu_dev[card]))) { mpu_config->io_base = mpu_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start; if(sb_isapnp_list[slot].mpu_irq != -1) mpu_config->irq = mpu_dev[card]->irq_resource[sb_isapnp_list[slot].mpu_irq].start; } } else printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name); return(sb_dev[card]);}static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, int slot, int card){ char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name; printk(KERN_INFO "sb: %s detected\n", busname); /* Initialize this baby. */ if(sb_init(bus, hw_config, mpu_config, slot, card)) { /* We got it. */ printk(KERN_NOTICE "sb: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n", busname, hw_config->io_base, hw_config->irq, hw_config->dma, hw_config->dma2); return 1; } else printk(KERN_INFO "sb: Failed to initialize %s\n", busname); return 0;}static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card){ static int first = 1; int i; /* Count entries in sb_isapnp_list */ for (i = 0; sb_isapnp_list[i].card_vendor != 0; i++); i--; /* Check and adjust isapnpjump */ if( isapnpjump < 0 || isapnpjump > i) { isapnpjump = reverse ? i : 0; printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump); } if(!first || !reverse) i = isapnpjump; first = 0; while(sb_isapnp_list[i].card_vendor != 0) { static struct pci_bus *bus = NULL; while ((bus = isapnp_find_card( sb_isapnp_list[i].card_vendor, sb_isapnp_list[i].card_device, bus))) { if(sb_isapnp_init(hw_config, mpu_config, bus, i, card)) { isapnpjump = i; /* start next search from here */ return 0; } } i += reverse ? -1 : 1; } return -ENODEV;}#endifstatic int __init init_sb(void){ int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1; printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); for(card = 0; card < max; card++, sb_cards_num++) {#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE /* Please remember that even with CONFIG_ISAPNP defined one * should still be able to disable PNP support for this * single driver! */ if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) { if(!sb_cards_num) { /* Found no ISAPnP cards, so check for a non-pnp * card and set the detection loop for 1 cycle */ printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n"); isapnp = 0; max = 1; } else /* found all the ISAPnP cards so exit the * detection loop. */ break; }#endif if(!isapnp || (pnplegacy&&card==0)) { cfg[card].io_base = io; cfg[card].irq = irq; cfg[card].dma = dma; cfg[card].dma2 = dma16; } cfg[card].card_subtype = type; if (!probe_sb(&cfg[card])) { /* if one or more cards already registered, don't * return an error but print a warning. Note, this * should never really happen unless the hardware * or ISAPnP screwed up. */ if (sb_cards_num) { printk(KERN_WARNING "sb.c: There was a " \ "problem probing one of your SoundBlaster " \ "ISAPnP soundcards. Continuing.\n"); card--; sb_cards_num--; continue; } else if(pnplegacy && isapnp) { printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \ "found. Continuing with PnP detection.\n"); pnplegacy=0; card--; continue; } else return -ENODEV; } attach_sb_card(&cfg[card]); if(cfg[card].slots[0]==-1) { if(card==0 && pnplegacy && isapnp) { printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \ "found. Continuing with PnP detection.\n"); pnplegacy=0; card--; continue; } else return -ENODEV; } if (!isapnp||(pnplegacy&&card==0)) cfg_mpu[card].io_base = mpu_io; if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE)) sbmpu[card] = 1; } if(isapnp) printk(KERN_NOTICE "sb: %d Soundblaster PnP card(s) found.\n", sb_cards_num); return 0;}static void __exit cleanup_sb(void){ int i; if (smw_free) { vfree(smw_free); smw_free = NULL; } for(i = 0; i < sb_cards_num; i++) { unload_sb(&cfg[i], i); if (sbmpu[i]) unload_sbmpu(&cfg_mpu[i]);#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE if(!audio_activated[i] && sb_dev[i]) sb_dev[i]->deactivate(sb_dev[i]); if(!mpu_activated[i] && mpu_dev[i]) mpu_dev[i]->deactivate(mpu_dev[i]); if(!opl_activated[i] && opl_dev[i]) opl_dev[i]->deactivate(opl_dev[i]);#endif }}module_init(init_sb);module_exit(cleanup_sb);#ifndef MODULEstatic int __init setup_sb(char *str){ /* io, irq, dma, dma2 - just the basics */ int ints[5]; str = get_options(str, ARRAY_SIZE(ints), ints); io = ints[1]; irq = ints[2]; dma = ints[3]; dma16 = ints[4]; return 1;}__setup("sb=", setup_sb);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -