📄 isapnp.c
字号:
for (i = 0; i < 8; i++) { raddr = (unsigned int)isapnp_reserve_mem[i << 1]; rsize = (unsigned int)isapnp_reserve_mem[(i << 1) + 1]; if (addr >= raddr && addr < raddr + rsize) return 1; if (addr + size > raddr && addr + size < (raddr + rsize) - 1) return 1; if (__check_region(&iomem_resource, addr, size)) return 1; } isapnp_for_each_dev(dev) { if (dev->active) { for (tmp = 0; tmp < 4; tmp++) { if (dev->resource[tmp].flags) { raddr = dev->resource[tmp + 8].start; rsize = (dev->resource[tmp + 8].end - raddr) + 1; if (addr >= raddr && addr < raddr + rsize) return 1; if (addr + size > raddr && addr + size < (raddr + rsize) - 1) return 1; } } } } for (i = 0; i < 4; i++) { unsigned int flags = cfg->request->resource[i + 8].flags; if (i == idx) continue; if (!flags) continue; tmp = cfg->result.resource[i + 8].start; if (flags & IORESOURCE_AUTO) { /* auto */ xmem = cfg->mem[i]; if (!xmem) return 1; if (cfg->result.resource[i + 8].flags & IORESOURCE_AUTO) continue; if (tmp + xmem->size >= addr && tmp <= addr + xmem->size) return 1; continue; } if (addr == tmp) return 1; xmem = isapnp_find_mem(cfg->request, i); if (!xmem) return 1; if (tmp + xmem->size >= addr && tmp <= addr + xmem->size) return 1; } return 0;}static int isapnp_valid_mem(struct isapnp_cfgtmp *cfg, int idx){ int err; unsigned long *value1, *value2; struct isapnp_mem *mem; if (!cfg || idx < 0 || idx > 3) return -EINVAL; if (!(cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO)) /* don't touch */ return 0; __again: mem = cfg->mem[idx]; if (!mem) return -EINVAL; value1 = &cfg->result.resource[idx + 8].start; value2 = &cfg->result.resource[idx + 8].end; if (cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO) { cfg->result.resource[idx + 8].flags &= ~IORESOURCE_AUTO; *value1 = mem->min; *value2 = mem->min + mem->size - 1; if (!isapnp_check_mem(cfg, *value1, mem->size, idx)) return 0; } do { *value1 += mem->align; *value2 = *value1 + mem->size - 1; if (*value1 > mem->max || !mem->align) { if (mem->res && mem->res->alt) { if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0) return err; goto __again; } return -ENOENT; } } while (isapnp_check_mem(cfg, *value1, mem->size, idx)); return 0;}static int isapnp_check_valid(struct isapnp_cfgtmp *cfg){ int tmp; for (tmp = 0; tmp < 8; tmp++) if (cfg->result.resource[tmp].flags & IORESOURCE_AUTO) return -EAGAIN; for (tmp = 0; tmp < 2; tmp++) if (cfg->result.irq_resource[tmp].flags & IORESOURCE_AUTO) return -EAGAIN; for (tmp = 0; tmp < 2; tmp++) if (cfg->result.dma_resource[tmp].flags & IORESOURCE_AUTO) return -EAGAIN; for (tmp = 0; tmp < 4; tmp++) if (cfg->result.resource[tmp + 8].flags & IORESOURCE_AUTO) return -EAGAIN; return 0;}static int isapnp_config_activate(struct pci_dev *dev){ struct isapnp_cfgtmp cfg; int tmp, fauto, err; if (!dev) return -EINVAL; if (dev->active) return -EBUSY; memset(&cfg, 0, sizeof(cfg)); cfg.request = dev; memcpy(&cfg.result, dev, sizeof(struct pci_dev)); /* check if all values are set, otherwise try auto-configuration */ for (tmp = fauto = 0; !fauto && tmp < 8; tmp++) { if (dev->resource[tmp].flags & IORESOURCE_AUTO) fauto++; } for (tmp = 0; !fauto && tmp < 2; tmp++) { if (dev->irq_resource[tmp].flags & IORESOURCE_AUTO) fauto++; } for (tmp = 0; !fauto && tmp < 2; tmp++) { if (dev->dma_resource[tmp].flags & IORESOURCE_AUTO) fauto++; } for (tmp = 0; !fauto && tmp < 4; tmp++) { if (dev->resource[tmp + 8].flags & IORESOURCE_AUTO) fauto++; } if (!fauto) goto __skip_auto; /* set variables to initial values */ if ((err = isapnp_alternative_switch(&cfg, NULL, NULL))<0) return err; /* find first valid configuration */ fauto = 0; do { for (tmp = 0; tmp < 8 && cfg.result.resource[tmp].flags; tmp++) if ((err = isapnp_valid_port(&cfg, tmp))<0) return err; for (tmp = 0; tmp < 2 && cfg.result.irq_resource[tmp].flags; tmp++) if ((err = isapnp_valid_irq(&cfg, tmp))<0) return err; for (tmp = 0; tmp < 2 && cfg.result.dma_resource[tmp].flags; tmp++) if ((err = isapnp_valid_dma(&cfg, tmp))<0) return err; for (tmp = 0; tmp < 4 && cfg.result.resource[tmp + 8].flags; tmp++) if ((err = isapnp_valid_mem(&cfg, tmp))<0) return err; } while (isapnp_check_valid(&cfg)<0 && fauto++ < 20); if (fauto >= 20) return -EAGAIN; __skip_auto: /* we have valid configuration, try configure hardware */ isapnp_cfg_begin(dev->bus->number, dev->devfn); dev->active = 1; dev->irq_resource[0] = cfg.result.irq_resource[0]; dev->irq_resource[1] = cfg.result.irq_resource[1]; dev->dma_resource[0] = cfg.result.dma_resource[0]; dev->dma_resource[1] = cfg.result.dma_resource[1]; for (tmp = 0; tmp < 12; tmp++) { dev->resource[tmp] = cfg.result.resource[tmp]; } for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++) isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start); for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) { int irq = dev->irq_resource[tmp].start; if (irq == 2) irq = 9; isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq); } for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++) isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start); for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++) isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff); isapnp_activate(dev->devfn); isapnp_cfg_end(); return 0;}static int isapnp_config_deactivate(struct pci_dev *dev){ if (!dev || !dev->active) return -EINVAL; isapnp_cfg_begin(dev->bus->number, dev->devfn); isapnp_deactivate(dev->devfn); dev->active = 0; isapnp_cfg_end(); return 0;}void isapnp_resource_change(struct resource *resource, unsigned long start, unsigned long size){ if (resource == NULL) return; resource->flags &= ~IORESOURCE_AUTO; resource->start = start; resource->end = start + size - 1;}/* * Inititialization. */#ifdef MODULEstatic void isapnp_free_port(struct isapnp_port *port){ struct isapnp_port *next; while (port) { next = port->next; kfree(port); port = next; }}static void isapnp_free_irq(struct isapnp_irq *irq){ struct isapnp_irq *next; while (irq) { next = irq->next; kfree(irq); irq = next; }}static void isapnp_free_dma(struct isapnp_dma *dma){ struct isapnp_dma *next; while (dma) { next = dma->next; kfree(dma); dma = next; }}static void isapnp_free_mem(struct isapnp_mem *mem){ struct isapnp_mem *next; while (mem) { next = mem->next; kfree(mem); mem = next; }}static void isapnp_free_mem32(struct isapnp_mem32 *mem32){ struct isapnp_mem32 *next; while (mem32) { next = mem32->next; kfree(mem32); mem32 = next; }}static void isapnp_free_resources(struct isapnp_resources *resources, int alt){ struct isapnp_resources *next; while (resources) { next = alt ? resources->alt : resources->next; isapnp_free_port(resources->port); isapnp_free_irq(resources->irq); isapnp_free_dma(resources->dma); isapnp_free_mem(resources->mem); isapnp_free_mem32(resources->mem32); if (!alt && resources->alt) isapnp_free_resources(resources->alt, 1); kfree(resources); resources = next; }}static void isapnp_free_card(struct pci_bus *card){ while (!list_empty(&card->devices)) { struct list_head *list = card->devices.next; struct pci_dev *dev = pci_dev_b(list); list_del(list); isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0); kfree(dev); } kfree(card);}#endif /* MODULE */static void isapnp_free_all_resources(void){#ifdef ISAPNP_REGION_OK if (pidxr_res) release_resource(pidxr_res);#endif if (pnpwrp_res) release_resource(pnpwrp_res); if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff && isapnp_rdp_res) release_resource(isapnp_rdp_res);#ifdef MODULE#ifdef CONFIG_PROC_FS isapnp_proc_done();#endif while (!list_empty(&isapnp_cards)) { struct list_head *list = isapnp_cards.next; list_del(list); isapnp_free_card(pci_bus_b(list)); }#endif}static int isapnp_announce_device(struct isapnp_driver *drv, struct pci_dev *dev){ const struct isapnp_device_id *id; int ret = 0; if (drv->id_table) { id = isapnp_match_dev(drv->id_table, dev); if (!id) { ret = 0; goto out; } } else id = NULL; if (drv->probe(dev, id) >= 0) { dev->driver = (struct pci_driver *) drv; ret = 1; }out: return ret;}/** * isapnp_dev_driver - get the isapnp_driver of a device * @dev: the device to query * * Returns the appropriate isapnp_driver structure or %NULL if there is no * registered driver for the device. */static struct isapnp_driver *isapnp_dev_driver(const struct pci_dev *dev){ return (struct isapnp_driver *) dev->driver;}static LIST_HEAD(isapnp_drivers);/** * isapnp_register_driver - register a new ISAPnP driver * @drv: the driver structure to register * * Adds the driver structure to the list of registered ISAPnP drivers * Returns the number of isapnp devices which were claimed by the driver * during registration. The driver remains registered even if the * return value is zero. */int isapnp_register_driver(struct isapnp_driver *drv){ struct pci_dev *dev; int count = 0; list_add_tail(&drv->node, &isapnp_drivers); isapnp_for_each_dev(dev) { if (!isapnp_dev_driver(dev)) count += isapnp_announce_device(drv, dev); } return count;}/** * isapnp_unregister_driver - unregister an isapnp driver * @drv: the driver structure to unregister * * Deletes the driver structure from the list of registered ISAPnP drivers, * gives it a chance to clean up by calling its remove() function for * each device it was responsible for, and marks those devices as * driverless. */void isapnp_unregister_driver(struct isapnp_driver *drv){ struct pci_dev *dev; list_del(&drv->node); isapnp_for_each_dev(dev) { if (dev->driver == (struct pci_driver *) drv) { if (drv->remove) drv->remove(dev); dev->driver = NULL; } }}EXPORT_SYMBOL(isapnp_cards);EXPORT_SYMBOL(isapnp_devices);EXPORT_SYMBOL(isapnp_present);EXPORT_SYMBOL(isapnp_cfg_begin);EXPORT_SYMBOL(isapnp_cfg_end);EXPORT_SYMBOL(isapnp_read_byte);EXPORT_SYMBOL(isapnp_read_word);EXPORT_SYMBOL(isapnp_read_dword);EXPORT_SYMBOL(isapnp_write_byte);EXPORT_SYMBOL(isapnp_write_word);EXPORT_SYMBOL(isapnp_write_dword);EXPORT_SYMBOL(isapnp_wake);EXPORT_SYMBOL(isapnp_device);EXPORT_SYMBOL(isapnp_activate);EXPORT_SYMBOL(isapnp_deactivate);EXPORT_SYMBOL(isapnp_find_card);EXPORT_SYMBOL(isapnp_find_dev);EXPORT_SYMBOL(isapnp_probe_cards);EXPORT_SYMBOL(isapnp_probe_devs);EXPORT_SYMBOL(isapnp_activate_dev);EXPORT_SYMBOL(isapnp_resource_change);EXPORT_SYMBOL(isapnp_register_driver);EXPORT_SYMBOL(isapnp_unregister_driver);int __init isapnp_init(void){ int cards; struct pci_bus *card; if (isapnp_disable) { isapnp_detected = 0; printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n"); return 0; }#ifdef ISAPNP_REGION_OK pidxr_res=request_region(_PIDXR, 1, "isapnp index"); if(!pidxr_res) { printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR); return -EBUSY; }#endif pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write"); if(!pnpwrp_res) { printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);#ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1);#endif return -EBUSY; } /* * Print a message. The existing ISAPnP code is hanging machines * so let the user know where. */ printk(KERN_INFO "isapnp: Scanning for PnP cards...\n"); if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) { isapnp_rdp |= 3; isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read"); if(!isapnp_rdp_res) { printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);#ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1);#endif release_region(isapnp_rdp, 1); return -EBUSY; } isapnp_set_rdp(); } isapnp_detected = 1; if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) { cards = isapnp_isolate(); if (cards < 0 || (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) { isapnp_free_all_resources(); isapnp_detected = 0; printk(KERN_INFO "isapnp: No Plug & Play device found\n"); return 0; } isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read"); } isapnp_build_device_list(); cards = 0; isapnp_for_each_card(card) { cards++; if (isapnp_verbose) { struct list_head *devlist; printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown"); if (isapnp_verbose < 2) continue; for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) { struct pci_dev *dev = pci_dev_b(devlist); printk(KERN_INFO "isapnp: Device '%s'\n", dev->name[0]?card->name:"Unknown"); } } } if (cards) { printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":""); } else { printk(KERN_INFO "isapnp: No Plug & Play card found\n"); }#ifdef CONFIG_PROC_FS isapnp_proc_init();#endif return 0;}#ifdef MODULEint init_module(void){ return isapnp_init();}void cleanup_module(void){ if (isapnp_detected) isapnp_free_all_resources();}#else/* format is: noisapnp */static int __init isapnp_setup_disable(char *str){ isapnp_disable = 1; return 1;}__setup("noisapnp", isapnp_setup_disable);/* format is: isapnp=rdp,reset,skip_pci_scan,verbose */static int __init isapnp_setup_isapnp(char *str){ (void)((get_option(&str,&isapnp_rdp) == 2) && (get_option(&str,&isapnp_reset) == 2) && (get_option(&str,&isapnp_skip_pci_scan) == 2) && (get_option(&str,&isapnp_verbose) == 2)); return 1;}__setup("isapnp=", isapnp_setup_isapnp);/* format is: isapnp_reserve_irq=irq1[,irq2] .... */static int __init isapnp_setup_reserve_irq(char *str){ int i; for (i = 0; i < 16; i++) if (get_option(&str,&isapnp_reserve_irq[i]) != 2) break; return 1;}__setup("isapnp_reserve_irq=", isapnp_setup_reserve_irq);/* format is: isapnp_reserve_dma=dma1[,dma2] .... */static int __init isapnp_setup_reserve_dma(char *str){ int i; for (i = 0; i < 8; i++) if (get_option(&str,&isapnp_reserve_dma[i]) != 2) break; return 1;}__setup("isapnp_reserve_dma=", isapnp_setup_reserve_dma);/* format is: isapnp_reserve_io=io1,size1[,io2,size2] .... */static int __init isapnp_setup_reserve_io(char *str){ int i; for (i = 0; i < 16; i++) if (get_option(&str,&isapnp_reserve_io[i]) != 2) break; return 1;}__setup("isapnp_reserve_io=", isapnp_setup_reserve_io);/* format is: isapnp_reserve_mem=mem1,size1[,mem2,size2] .... */static int __init isapnp_setup_reserve_mem(char *str){ int i; for (i = 0; i < 16; i++) if (get_option(&str,&isapnp_reserve_mem[i]) != 2) break; return 1;}__setup("isapnp_reserve_mem=", isapnp_setup_reserve_mem);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -