?? isapnp.c
字號:
}static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx){ int err, i; unsigned long *value1, *value2; struct isapnp_dma *dma; if (!cfg || idx < 0 || idx > 1) return -EINVAL; if (!(cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO)) /* don't touch */ return 0; __again: dma = cfg->dma[idx]; if (!dma) return -EINVAL; value1 = &cfg->result.dma_resource[idx].start; value2 = &cfg->result.dma_resource[idx].end; if (cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO) { for (i = 0; i < 8 && !(dma->map & (1<<i)); i++); if (i >= 8) return -ENOENT; cfg->result.dma_resource[idx].flags &= ~IORESOURCE_AUTO; if (!isapnp_check_dma(cfg, *value1 = *value2 = i, idx)) return 0; } do { for (i = *value1 + 1; i < 8 && !(dma->map & (1<<i)); i++); if (i >= 8) { if (dma->res && dma->res->alt) { if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0) return err; goto __again; } return -ENOENT; } else { *value1 = *value2 = i; } } while (isapnp_check_dma(cfg, *value1, idx)); return 0;}static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsigned int size, int idx){ int i, tmp; unsigned int raddr, rsize; struct pnp_dev *dev; struct isapnp_mem *xmem; 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)) if (check_region(addr, size)) return 1; } for (dev = isapnp_devices; dev; dev = dev->next) { 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].start; value2 = &cfg->result.resource[idx].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 >= 8 || !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 pnp_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 pnp_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 pnp_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_device(struct pnp_dev *dev){ struct pnp_dev *next; while (dev) { next = dev->sibling; isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0); kfree(dev); dev = next; }}#endif /* MODULE */static void isapnp_free_all_resources(void){#ifdef MODULE struct pnp_bus *card, *cardnext;#endif#ifdef ISAPNP_REGION_OK// release_resource(pidxr_res); release_region(_PIDXR, 1);#endif// release_resource(pnpwrp_res); release_region(_PNPWRP, 1); if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff)// release_resource(isapnp_rdp_res); release_region(isapnp_rdp, 1);#ifdef MODULE for (card = isapnp_cards; card; card = cardnext) { cardnext = card->next; isapnp_free_device(card->devices); kfree(card); }#ifdef CONFIG_PROC_FS isapnp_proc_done();#endif#endif}static int __init isapnp_do_reserve_irq(int irq){ int i; if (irq < 0 || irq > 15) return -EINVAL; for (i = 0; i < 16; i++) { if (isapnp_reserve_irq[i] == irq) return 0; } for (i = 0; i < 16; i++) { if (isapnp_reserve_irq[i] < 0) { isapnp_reserve_irq[i] = irq;#ifdef ISAPNP_DEBUG printk("IRQ %i is reserved now.\n", irq);#endif return 0; } } return -ENOMEM;}#ifdef CONFIG_PCIstruct pnp_dev *pnp_find_slot(unsigned int bus, unsigned int devfn){ struct pnp_dev *dev; for(dev=isapnp_devices; dev; dev=dev->next) if (dev->bus->number == bus && dev->devfn == devfn) break; return dev;}static void __init isapnp_pci_init(void){ int devfn; struct pnp_dev *dev; for (devfn = 0; devfn < 255; devfn++) { dev = pnp_find_slot(0, devfn); if (dev != NULL) break; } if (dev == NULL) return; while (dev) {#ifdef ISAPNP_DEBUG printk("PCI: reserved IRQ: %i\n", dev->irq);#endif if (dev->irq > 0) isapnp_do_reserve_irq(dev->irq); dev = dev->next; }}#endif /* CONFIG_PCI */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_resource_change);int __init isapnp_init(void){ int cards; struct pnp_bus *card; struct pnp_dev *dev; if (isapnp_disable) { isapnp_detected = 0; printk("isapnp: ISA Plug & Play support disabled\n"); return 0; }#ifdef ISAPNP_REGION_OK request_region(_PIDXR, 1, "isapnp index");// pidxr_res=request_region(_PIDXR, 1, "isapnp index");// if(!pidxr_res) {// printk("isapnp: Index Register 0x%x already used\n", _PIDXR);// return -EBUSY;// }#endif request_region(_PNPWRP, 1, "isapnp write");// pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write");// if(!pnpwrp_res) {// printk("isapnp: Write Data Register 0x%x already used\n", _PNPWRP);// return -EBUSY;// } /* * Print a message. The existing ISAPnP code is hanging machines * so let the user know where. */ printk("isapnp: Scanning for Pnp cards...\n"); if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) { isapnp_rdp |= 3; request_region(isapnp_rdp, 1, "isapnp read");// isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");// if(!isapnp_rdp_res) {// printk("isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);// 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("isapnp: No Plug & Play device found\n"); return 0; } request_region(isapnp_rdp, 1, "isapnp read");// isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read"); } isapnp_build_device_list(); cards = 0; for (card = isapnp_cards; card; card = card->next) cards++; if (isapnp_verbose) { for (card = isapnp_cards; card; card = card->next) { printk( "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown"); if (isapnp_verbose < 2) continue; for (dev = card->devices; dev; dev = dev->next) printk("isapnp: Device '%s'\n", dev->name[0]?card->name:"Unknown"); } } if (cards) { printk("isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":""); } else { printk("isapnp: No Plug & Play card found\n"); }#ifdef CONFIG_PCI if (!isapnp_skip_pci_scan) isapnp_pci_init();#endif#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();}#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -