?? hostap_plx.c
字號:
.card_present = NULL, .cor_sreset = prism2_plx_cor_sreset, .dev_open = NULL, .dev_close = NULL, .genesis_reset = prism2_plx_genesis_reset, .hw_type = HOSTAP_HW_PLX,};static int prism2_plx_check_cis(void *attr_mem, int attr_len, unsigned int *cor_offset, unsigned int *cor_index){#define CISTPL_CONFIG 0x1A#define CISTPL_MANFID 0x20#define CISTPL_END 0xFF#define CIS_MAX_LEN 256 u8 cis[CIS_MAX_LEN]; int i, pos; unsigned int rmsz, rasz, manfid1, manfid2; struct prism2_plx_manfid *manfid; /* read CIS; it is in even offsets in the beginning of attr_mem */ for (i = 0; i < CIS_MAX_LEN; i++) cis[i] = readb(attr_mem + 2 * i); printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n", dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]); /* set reasonable defaults for Prism2 cards just in case CIS parsing * fails */ *cor_offset = 0x3e0; *cor_index = 0x01; manfid1 = manfid2 = 0; pos = 0; while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) { if (pos + cis[pos + 1] >= CIS_MAX_LEN) goto cis_error; switch (cis[pos]) { case CISTPL_CONFIG: if (cis[pos + 1] < 1) goto cis_error; rmsz = (cis[pos + 2] & 0x3c) >> 2; rasz = cis[pos + 2] & 0x03; if (4 + rasz + rmsz > cis[pos + 1]) goto cis_error; *cor_index = cis[pos + 3] & 0x3F; *cor_offset = 0; for (i = 0; i <= rasz; i++) *cor_offset += cis[pos + 4 + i] << (8 * i); printk(KERN_DEBUG "%s: cor_index=0x%x " "cor_offset=0x%x\n", dev_info, *cor_index, *cor_offset); if (*cor_offset > attr_len) { printk(KERN_ERR "%s: COR offset not within " "attr_mem\n", dev_info); return -1; } break; case CISTPL_MANFID: if (cis[pos + 1] < 4) goto cis_error; manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); printk(KERN_DEBUG "%s: manfid=0x%04x, 0x%04x\n", dev_info, manfid1, manfid2); break; } pos += cis[pos + 1] + 2; } if (pos >= CIS_MAX_LEN || cis[pos] != CISTPL_END) goto cis_error; for (manfid = prism2_plx_known_manfids; manfid->manfid1 != 0; manfid++) if (manfid1 == manfid->manfid1 && manfid2 == manfid->manfid2) return 0; printk(KERN_INFO "%s: unknown manfid 0x%04x, 0x%04x - assuming this is" " not supported card\n", dev_info, manfid1, manfid2); goto fail; cis_error: printk(KERN_WARNING "%s: invalid CIS data\n", dev_info); fail: if (ignore_cis) { printk(KERN_INFO "%s: ignore_cis parameter set - ignoring " "errors during CIS verification\n", dev_info); return 0; } return -1;}static int prism2_plx_probe(struct pci_dev *pdev, const struct pci_device_id *id){ unsigned int pccard_ioaddr, plx_ioaddr; unsigned long pccard_attr_mem; unsigned int pccard_attr_len; void *attr_mem = NULL; unsigned int cor_offset, cor_index; u32 reg; local_info_t *local = NULL; struct net_device *dev = NULL; struct hostap_interface *iface; static int cards_found /* = 0 */; int irq_registered = 0; int tmd7160; if (pci_enable_device(pdev)) return -EIO; /* National Datacomm NCP130 based on TMD7160, not PLX9052. */ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); plx_ioaddr = pci_resource_start(pdev, 1); pccard_ioaddr = pci_resource_start(pdev, tmd7160 ? 2 : 3); if (tmd7160) { /* TMD7160 */ attr_mem = NULL; /* no access to PC Card attribute memory */ printk(KERN_INFO "TMD7160 PCI/PCMCIA adapter: io=0x%x, " "irq=%d, pccard_io=0x%x\n", plx_ioaddr, pdev->irq, pccard_ioaddr); cor_offset = plx_ioaddr; cor_index = 0x04; outb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, plx_ioaddr); mdelay(1); reg = inb(plx_ioaddr); if (reg != (cor_index | COR_LEVLREQ | COR_ENABLE_FUNC)) { printk(KERN_ERR "%s: Error setting COR (expected=" "0x%02x, was=0x%02x)\n", dev_info, cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, reg); goto fail; } } else { /* PLX9052 */ pccard_attr_mem = pci_resource_start(pdev, 2); pccard_attr_len = pci_resource_len(pdev, 2); if (pccard_attr_len < PLX_MIN_ATTR_LEN) goto fail; attr_mem = ioremap(pccard_attr_mem, pccard_attr_len); if (attr_mem == NULL) { printk(KERN_ERR "%s: cannot remap attr_mem\n", dev_info); goto fail; } printk(KERN_INFO "PLX9052 PCI/PCMCIA adapter: " "mem=0x%lx, plx_io=0x%x, irq=%d, pccard_io=0x%x\n", pccard_attr_mem, plx_ioaddr, pdev->irq, pccard_ioaddr); if (prism2_plx_check_cis(attr_mem, pccard_attr_len, &cor_offset, &cor_index)) { printk(KERN_INFO "Unknown PC Card CIS - not a " "Prism2/2.5 card?\n"); goto fail; } printk(KERN_DEBUG "Prism2/2.5 PC Card detected in PLX9052 " "adapter\n"); /* Write COR to enable PC Card */ writeb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, attr_mem + cor_offset); /* Enable PCI interrupts if they are not already enabled */ reg = inl(plx_ioaddr + PLX_INTCSR); printk(KERN_DEBUG "PLX_INTCSR=0x%x\n", reg); if (!(reg & PLX_INTCSR_PCI_INTEN)) { outl(reg | PLX_INTCSR_PCI_INTEN, plx_ioaddr + PLX_INTCSR); if (!(inl(plx_ioaddr + PLX_INTCSR) & PLX_INTCSR_PCI_INTEN)) { printk(KERN_WARNING "%s: Could not enable " "Local Interrupts\n", dev_info); goto fail; } } reg = inl(plx_ioaddr + PLX_CNTRL); printk(KERN_DEBUG "PLX_CNTRL=0x%x (Serial EEPROM " "present=%d)\n", reg, (reg & PLX_CNTRL_SERIAL_EEPROM_PRESENT) != 0); /* should set PLX_PCIIPR to 0x01 (INTA#) if Serial EEPROM is * not present; but are there really such cards in use(?) */ } dev = prism2_init_local_data(&prism2_plx_funcs, cards_found,#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) NULL#else &pdev->dev#endif ); if (dev == NULL) goto fail; iface = dev->priv; local = iface->local; cards_found++; dev->irq = pdev->irq; dev->base_addr = pccard_ioaddr; local->attr_mem = attr_mem; local->cor_offset = cor_offset; pci_set_drvdata(pdev, dev); if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name, dev)) { printk(KERN_WARNING "%s: request_irq failed\n", dev->name); goto fail; } else irq_registered = 1; if (prism2_hw_config(dev, 1)) { printk(KERN_DEBUG "%s: hardware initialization failed\n", dev_info); goto fail; } return hostap_hw_ready(dev); fail: prism2_free_local_data(dev); if (irq_registered && dev) free_irq(dev->irq, dev); if (attr_mem) iounmap(attr_mem); pci_disable_device(pdev); return -ENODEV;}static void prism2_plx_remove(struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata(pdev); struct hostap_interface *iface = dev->priv; /* Reset the hardware, and ensure interrupts are disabled. */ prism2_plx_cor_sreset(iface->local); hfa384x_disable_interrupts(dev); if (iface->local->attr_mem) iounmap(iface->local->attr_mem); if (dev->irq) free_irq(dev->irq, dev); prism2_free_local_data(dev); pci_disable_device(pdev);}MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);static struct pci_driver prism2_plx_drv_id = { .name = "hostap_plx", .id_table = prism2_plx_id_table, .probe = prism2_plx_probe, .remove = prism2_plx_remove, .suspend = NULL, .resume = NULL, .enable_wake = NULL};static int __init init_prism2_plx(void){ printk(KERN_INFO "%s: %s\n", dev_info, version);#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) if (pci_register_driver(&prism2_plx_drv_id) <= 0) { printk("hostap_plx: No devices found, driver not " "installed.\n"); pci_unregister_driver(&prism2_plx_drv_id); return -ENODEV; } return 0;#else return pci_register_driver(&prism2_plx_drv_id);#endif}static void __exit exit_prism2_plx(void){ pci_unregister_driver(&prism2_plx_drv_id); printk(KERN_INFO "%s: Driver unloaded\n", dev_info);}module_init(init_prism2_plx);module_exit(exit_prism2_plx);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -