--- orinoco_plx.c.orig Thu Jul 25 11:00:58 2002 +++ orinoco_plx.c Fri Aug 2 10:34:45 2002 @@ -1,4 +1,4 @@ -/* orinoco_plx.c 0.11b +/* orinoco_plx.c 0.11b-jd-pheecompatch * * Driver for Prism II devices which would usually be driven by orinoco_cs, * but are connected to the PCI bus by a PLX9052. @@ -145,6 +145,7 @@ #define COR_OFFSET (0x3e0 / 2) /* COR attribute offset of Prism2 PC card */ #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ +#define TMD_COR_VALUE (COR_LEVEL_REQ | COR_IREQ_ENA | COR_FUNC_ENA) /* Enable Card with level triggered irqs and irq requests */ #define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */ #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ @@ -203,67 +204,92 @@ if (err) return -EIO; - /* Resource 2 is mapped to the PCMCIA space */ - attr_mem = ioremap(pci_resource_start(pdev, 2), PAGE_SIZE); - if (! attr_mem) - goto fail; + if ((pdev->vendor != 0x15e8) && (pdev->device != 0x0131)) { + /* PLX chip initialization */ + /* Resource 2 is mapped to the PCMCIA space */ + attr_mem = ioremap(pci_resource_start(pdev, 2), PAGE_SIZE); + if (! attr_mem) + goto fail; - printk(KERN_DEBUG "orinoco_plx: CIS: "); - for (i = 0; i < 16; i++) { - printk("%02X:", (int)attr_mem[i]); - } - printk("\n"); + printk(KERN_DEBUG "orinoco_plx: CIS: "); + for (i = 0; i < 16; i++) { + printk("%02X:", (int)attr_mem[i]); + } + printk("\n"); - /* Verify whether PC card is present */ - /* FIXME: we probably need to be smarted about this */ - if (memcmp(attr_mem, cis_magic, sizeof(cis_magic)) != 0) { - printk(KERN_ERR "orinoco_plx: The CIS value of Prism2 PC card is invalid.\n"); - err = -EIO; - goto fail; - } + /* Verify whether PC card is present */ + /* FIXME: we probably need to be smarted about this */ + if (memcmp(attr_mem, cis_magic, sizeof(cis_magic)) != 0) { + printk(KERN_ERR "orinoco_plx: The CIS value of Prism2 PC card is invalid.\n"); + err = -EIO; + goto fail; + } - /* PCMCIA COR is the first byte following CIS: this write should - * enable I/O mode and select level-triggered interrupts */ - attr_mem[COR_OFFSET] = COR_VALUE; - mdelay(1); - reg = attr_mem[COR_OFFSET]; - if (reg != COR_VALUE) { - printk(KERN_ERR "orinoco_plx: Error setting COR value (reg=%x)\n", reg); - goto fail; - } + /* PCMCIA COR is the first byte following CIS: this write should + * enable I/O mode and select level-triggered interrupts */ + attr_mem[COR_OFFSET] = COR_VALUE; + mdelay(1); + reg = attr_mem[COR_OFFSET]; + if (reg != COR_VALUE) { + printk(KERN_ERR "orinoco_plx: Error setting COR value (reg=%x)\n", reg); + goto fail; + } - iounmap(attr_mem); - attr_mem = NULL; /* done with this now, it seems */ + iounmap(attr_mem); + attr_mem = NULL; /* done with this now, it seems */ - /* bjoern: We need to tell the card to enable interrupts, in - case the serial eprom didn't do this already. See the - PLX9052 data book, p8-1 and 8-24 for reference. */ - addr = pci_resource_start(pdev, 1); - reg = 0; - reg = inl(addr+PLX_INTCSR); - if(reg & PLX_INTCSR_INTEN) - printk(KERN_DEBUG "orinoco_plx: " - "Local Interrupt already enabled\n"); - else { - reg |= PLX_INTCSR_INTEN; - outl(reg, addr+PLX_INTCSR); + /* bjoern: We need to tell the card to enable interrupts, in + case the serial eprom didn't do this already. See the + PLX9052 data book, p8-1 and 8-24 for reference. */ + addr = pci_resource_start(pdev, 1); + reg = 0; reg = inl(addr+PLX_INTCSR); - if(!(reg & PLX_INTCSR_INTEN)) { - printk(KERN_ERR "orinoco_plx: " - "Couldn't enable Local Interrupts\n"); - goto fail; + if(reg & PLX_INTCSR_INTEN) + printk(KERN_DEBUG "orinoco_plx: " + "Local Interrupt already enabled\n"); + else { + reg |= PLX_INTCSR_INTEN; + outl(reg, addr+PLX_INTCSR); + reg = inl(addr+PLX_INTCSR); + if(!(reg & PLX_INTCSR_INTEN)) { + printk(KERN_ERR "orinoco_plx: " + "Couldn't enable Local Interrupts\n"); + goto fail; + } } - } - /* and 3 to the PCMCIA slot I/O address space */ - pccard_ioaddr = pci_resource_start(pdev, 3); - pccard_iolen = pci_resource_len(pdev, 3); - if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) { - printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n", - pccard_iolen, pccard_ioaddr); - pccard_ioaddr = 0; - err = -EBUSY; - goto fail; + /* and 3 to the PCMCIA slot I/O address space */ + pccard_ioaddr = pci_resource_start(pdev, 3); + pccard_iolen = pci_resource_len(pdev, 3); + if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) { + printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n", + pccard_iolen, pccard_ioaddr); + pccard_ioaddr = 0; + err = -EBUSY; + goto fail; + } + } else { + /* This is initialization for pheecom card with TMD7160 + chip, also referred to as ASIC version */ + printk(KERN_DEBUG "TMD setup\n"); + pccard_ioaddr = pci_resource_start(pdev, 2); + pccard_iolen = pci_resource_len(pdev, 2); + if ( !request_region(pccard_ioaddr, pccard_iolen, dev_info)) { + printk(KERN_ERR "orinoco_plx: I/O resource at 0x%lx len 0x%lx busy\n", + pccard_ioaddr, pccard_iolen); + pccard_ioaddr = 0; + err = -EBUSY; + goto fail; + } + addr = pci_resource_start(pdev, 1); + outb(TMD_COR_VALUE, addr); + mdelay(1); + reg = inb(addr); + if (reg != TMD_COR_VALUE) { + printk(KERN_ERR "orinoco_plx: Error setting TMD corr values %x\n", reg); + err = -EIO; + goto fail; + } } dev = alloc_orinocodev(0); @@ -354,7 +380,11 @@ kfree(dev); - release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); + if ((pdev->vendor != 0x15e8) && (pdev->device != 0x0131)) { + release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); + } else { + release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + } pci_disable_device(pdev); @@ -366,6 +396,7 @@ {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ + {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W, Eumitcom PCI WL11000, Addtron AWA-100*/