Index: if_wi.c =================================================================== RCS file: /cvsroot/kame/kame/freebsd4/sys/i386/isa/if_wi.c,v retrieving revision 1.1.1.6 retrieving revision 1.12 diff -u -r1.1.1.6 -r1.12 --- if_wi.c 2002/02/07 01:32:00 1.1.1.6 +++ if_wi.c 2002/02/16 23:10:49 1.12 @@ -123,6 +123,13 @@ static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 }; #endif +/* + * The following is for compatibility with NetBSD, but should really be + * brought in from NetBSD en toto. + */ +#define le16toh(a) (a) +#define LE16TOH(a) + static void wi_intr __P((void *)); static void wi_reset __P((struct wi_softc *)); static int wi_ioctl __P((struct ifnet *, u_long, caddr_t)); @@ -168,6 +175,7 @@ static void wi_free __P((device_t)); static int wi_get_cur_ssid __P((struct wi_softc *, char *, int *)); +static void wi_get_id __P((struct wi_softc *, device_t)); static int wi_media_change __P((struct ifnet *)); static void wi_media_status __P((struct ifnet *, struct ifmediareq *)); @@ -208,11 +216,14 @@ static struct { unsigned int vendor,device; + int bus_type; char *desc; } pci_ids[] = { - {0x1638, 0x1100, "PRISM2STA PCI WaveLAN/IEEE 802.11"}, - {0x1385, 0x4100, "Netgear MA301 PCI IEEE 802.11b"}, - {0x16ab, 0x1102, "Linksys WDT11 PCI IEEE 802.11b"}, + {0x1638, 0x1100, WI_BUS_PCI_PLX, "PRISM2STA PCI WaveLAN/IEEE 802.11"}, + {0x1385, 0x4100, WI_BUS_PCI_PLX, "Netgear MA301 PCI IEEE 802.11b"}, + {0x16ab, 0x1101, WI_BUS_PCI_PLX, "GLPRISM2 PCI WaveLAN/IEEE 802.11"}, + {0x16ab, 0x1102, WI_BUS_PCI_PLX, "Linksys WDT11 PCI IEEE 802.11b"}, + {0x1260, 0x3873, WI_BUS_PCI_NATIVE, "Linksys WMP11 PCI Prism2.5"}, {0, 0, NULL} }; #endif @@ -234,6 +245,7 @@ sc = device_get_softc(dev); sc->wi_gone = 0; + sc->wi_bus_type = WI_BUS_PCCARD; error = wi_alloc(dev, 0); if (error) @@ -262,6 +274,7 @@ if ((pci_get_vendor(dev) == pci_ids[i].vendor) && (pci_get_device(dev) == pci_ids[i].device)) { sc->wi_prism2 = 1; + sc->wi_bus_type = pci_ids[i].bus_type; device_set_desc(dev, pci_ids[i].desc); return (0); } @@ -306,33 +319,9 @@ { struct wi_softc *sc; int error; - u_int32_t flags; sc = device_get_softc(dev); - /* - * XXX: quick hack to support Prism II chip. - * Currently, we need to set a flags in pccard.conf to specify - * which type chip is used. - * - * We need to replace this code in a future. - * It is better to use CIS than using a flag. - */ - flags = device_get_flags(dev); -#define WI_FLAGS_PRISM2 0x10000 - if (flags & WI_FLAGS_PRISM2) { - sc->wi_prism2 = 1; - if (bootverbose) { - device_printf(dev, "found PrismII chip\n"); - } - } - else { - sc->wi_prism2 = 0; - if (bootverbose) { - device_printf(dev, "found Lucent chip\n"); - } - } - error = wi_alloc(dev, 0); if (error) { device_printf(dev, "wi_alloc() failed! (%d)\n", error); @@ -349,6 +338,7 @@ u_int32_t command, wanted; u_int16_t reg; int error; + int timeout; sc = device_get_softc(dev); @@ -362,56 +352,79 @@ return (ENXIO); } - error = wi_alloc(dev, WI_PCI_IORES); - if (error) - return (error); + if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) { + error = wi_alloc(dev, WI_PCI_IORES); + if (error) + return (error); - /* Make sure interrupts are disabled. */ - CSR_WRITE_2(sc, WI_INT_EN, 0); - CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); + /* Make sure interrupts are disabled. */ + CSR_WRITE_2(sc, WI_INT_EN, 0); + CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); - /* We have to do a magic PLX poke to enable interrupts */ - sc->local_rid = WI_PCI_LOCALRES; - sc->local = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->local_rid, - 0, ~0, 1, RF_ACTIVE); - sc->wi_localtag = rman_get_bustag(sc->local); - sc->wi_localhandle = rman_get_bushandle(sc->local); - command = bus_space_read_4(sc->wi_localtag, sc->wi_localhandle, - WI_LOCAL_INTCSR); - command |= WI_LOCAL_INTEN; - bus_space_write_4(sc->wi_localtag, sc->wi_localhandle, - WI_LOCAL_INTCSR, command); - bus_release_resource(dev, SYS_RES_IOPORT, sc->local_rid, sc->local); - sc->local = NULL; - - sc->mem_rid = WI_PCI_MEMRES; - sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->mem == NULL) { - device_printf(dev, "couldn't allocate memory\n"); - wi_free(dev); - return (ENXIO); - } - sc->wi_bmemtag = rman_get_bustag(sc->mem); - sc->wi_bmemhandle = rman_get_bushandle(sc->mem); + /* We have to do a magic PLX poke to enable interrupts */ + sc->local_rid = WI_PCI_LOCALRES; + sc->local = bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->local_rid, 0, ~0, 1, RF_ACTIVE); + sc->wi_localtag = rman_get_bustag(sc->local); + sc->wi_localhandle = rman_get_bushandle(sc->local); + command = bus_space_read_4(sc->wi_localtag, sc->wi_localhandle, + WI_LOCAL_INTCSR); + command |= WI_LOCAL_INTEN; + bus_space_write_4(sc->wi_localtag, sc->wi_localhandle, + WI_LOCAL_INTCSR, command); + bus_release_resource(dev, SYS_RES_IOPORT, sc->local_rid, + sc->local); + sc->local = NULL; - /* - * From Linux driver: - * Write COR to enable PC card - * This is a subset of the protocol that the pccard bus code - * would do. - */ - CSM_WRITE_1(sc, WI_COR_OFFSET, WI_COR_VALUE); - reg = CSM_READ_1(sc, WI_COR_OFFSET); - if (reg != WI_COR_VALUE) { - device_printf(dev, - "CSM_READ_1(WI_COR_OFFSET) " - "wanted %d, got %d\n", WI_COR_VALUE, reg); - wi_free(dev); - return (ENXIO); + sc->mem_rid = WI_PCI_MEMRES; + sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->mem == NULL) { + device_printf(dev, "couldn't allocate memory\n"); + wi_free(dev); + return (ENXIO); + } + sc->wi_bmemtag = rman_get_bustag(sc->mem); + sc->wi_bmemhandle = rman_get_bushandle(sc->mem); + + /* + * From Linux driver: + * Write COR to enable PC card + * This is a subset of the protocol that the pccard bus code + * would do. + */ + CSM_WRITE_1(sc, WI_COR_OFFSET, WI_COR_VALUE); + reg = CSM_READ_1(sc, WI_COR_OFFSET); + if (reg != WI_COR_VALUE) { + device_printf(dev, "CSM_READ_1(WI_COR_OFFSET) " + "wanted %d, got %d\n", WI_COR_VALUE, reg); + wi_free(dev); + return (ENXIO); + } + } else { + error = wi_alloc(dev, WI_PCI_LMEMRES); + if (error) + return (error); + + CSR_WRITE_2(sc, WI_HFA384X_PCICOR_OFF, 0x0080); + DELAY(250000); + + CSR_WRITE_2(sc, WI_HFA384X_PCICOR_OFF, 0x0000); + DELAY(500000); + + timeout=2000000; + while ((--timeout > 0) && + (CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) + DELAY(10); + + if (timeout == 0) { + device_printf(dev, "couldn't reset prism2.5 core.\n"); + wi_free(dev); + return(ENXIO); + } } - CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC); + CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC); reg = CSR_READ_2(sc, WI_HFA384X_SWSUPPORT0_OFF); if (reg != WI_PRISM2STA_MAGIC) { device_printf(dev, @@ -469,9 +482,10 @@ } bcopy((char *)&mac.wi_mac_addr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); + + device_printf(dev, "802.11 address: %6D\n", sc->arpcom.ac_enaddr, ":"); - device_printf(dev, "Ethernet address: %6D\n", - sc->arpcom.ac_enaddr, ":"); + wi_get_id(sc, dev); ifp->if_softc = sc; ifp->if_unit = sc->wi_unit; @@ -484,7 +498,8 @@ ifp->if_watchdog = wi_watchdog; ifp->if_init = wi_init; ifp->if_baudrate = 10000000; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_READY(&ifp->if_snd); bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name, @@ -570,6 +585,80 @@ return(0); } +static void +wi_get_id(sc, dev) + struct wi_softc *sc; + device_t dev; +{ + struct wi_ltv_ver ver; + + /* getting chip identity */ + memset(&ver, 0, sizeof(ver)); + ver.wi_type = WI_RID_CARDID; + ver.wi_len = 5; + wi_read_record(sc, (struct wi_ltv_gen *)&ver); + device_printf(dev, "using "); + switch (le16toh(ver.wi_ver[0])) { + case WI_NIC_EVB2: + printf("RF:PRISM2 MAC:HFA3841"); + sc->wi_prism2 = 1; + break; + case WI_NIC_HWB3763: + printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3763 rev.B"); + sc->wi_prism2 = 1; + break; + case WI_NIC_HWB3163: + printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A"); + sc->wi_prism2 = 1; + break; + case WI_NIC_HWB3163B: + printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.B"); + sc->wi_prism2 = 1; + break; + case WI_NIC_EVB3: + printf("RF:PRISM2 MAC:HFA3842"); + sc->wi_prism2 = 1; + break; + case WI_NIC_HWB1153: + printf("RF:PRISM1 MAC:HFA3841 CARD:HWB1153"); + sc->wi_prism2 = 1; + break; + case WI_NIC_P2_SST: + printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163-SST-flash"); + sc->wi_prism2 = 1; + break; + case WI_NIC_PRISM2_5: + printf("RF:PRISM2.5 MAC:ISL3873"); + sc->wi_prism2 = 1; + break; + case WI_NIC_3874A: + printf("RF:PRISM2.5 MAC:ISL3874A(PCI)"); + sc->wi_prism2 = 1; + break; + default: + printf("Lucent chip or unknown chip\n"); + sc->wi_prism2 = 0; + break; + } + + if (sc->wi_prism2) { + /* try to get prism2 firm version */ + memset(&ver, 0, sizeof(ver)); + ver.wi_type = WI_RID_IDENT; + ver.wi_len = 5; + wi_read_record(sc, (struct wi_ltv_gen *)&ver); + LE16TOH(ver.wi_ver[1]); + LE16TOH(ver.wi_ver[2]); + LE16TOH(ver.wi_ver[3]); + printf(", Firmware: %i.%i variant %i\n", ver.wi_ver[2], + ver.wi_ver[3], ver.wi_ver[1]); + sc->wi_prism2_ver = ver.wi_ver[2] * 100 + + ver.wi_ver[3] * 10 + ver.wi_ver[1]; + } + + return; +} + static void wi_rxeof(sc) struct wi_softc *sc; { @@ -816,7 +905,7 @@ /* Re-enable interrupts. */ CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); - if (ifp->if_snd.ifq_head != NULL) { + if (!IFQ_IS_EMPTY(&ifp->if_snd)) { wi_start(ifp); } @@ -838,6 +927,7 @@ DELAY(10*1000); /* 10 m sec */ } if (i == 0) { + device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" ); return(ETIMEDOUT); } @@ -851,8 +941,8 @@ * Wait for 'command complete' bit to be * set in the event status register. */ - s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD; - if (s) { + s = CSR_READ_2(sc, WI_EVENT_STAT); + if (s & WI_EV_CMD) { /* Ack the event and read result code. */ s = CSR_READ_2(sc, WI_STATUS); CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); @@ -864,11 +954,14 @@ return(EIO); break; } + DELAY(WI_DELAY); } - if (i == WI_TIMEOUT) { - return(ETIMEDOUT); - } + if (i == WI_TIMEOUT) { + device_printf(sc->dev, + "timeout in wi_cmd %x; event status %x\n", cmd, s); + return(ETIMEDOUT); + } return(0); } @@ -882,7 +975,7 @@ for (i = 0; i < WI_INIT_TRIES; i++) { if (wi_cmd(sc, WI_CMD_INI, 0) == 0) break; - DELAY(50 * 1000); /* 50ms */ + DELAY(WI_DELAY * 1000); } if (i == WI_INIT_TRIES) device_printf(sc->dev, "init failed\n"); @@ -1094,6 +1187,7 @@ status = CSR_READ_2(sc, offreg); if (!(status & (WI_OFF_BUSY|WI_OFF_ERR))) break; + DELAY(WI_DELAY); } if (i == WI_TIMEOUT) { @@ -1197,6 +1291,7 @@ for (i = 0; i < WI_TIMEOUT; i++) { if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) break; + DELAY(WI_DELAY); } if (i == WI_TIMEOUT) { @@ -1783,7 +1878,7 @@ return; } - IF_DEQUEUE(&ifp->if_snd, m0); + IFQ_DEQUEUE(&ifp->if_snd, m0); if (m0 == NULL) { return; } @@ -1936,23 +2031,45 @@ return; } -static int wi_alloc(dev, io_rid) +static int wi_alloc(dev, rid) device_t dev; - int io_rid; + int rid; { struct wi_softc *sc = device_get_softc(dev); - sc->iobase_rid = io_rid; - sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->iobase_rid, - 0, ~0, 1, RF_ACTIVE); - if (!sc->iobase) { - device_printf(dev, "No I/O space?!\n"); - return (ENXIO); + if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) { + sc->iobase_rid = rid; + sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->iobase_rid, 0, ~0, (1 << 6), + rman_make_alignment_flags(1 << 6) | RF_ACTIVE); + if (!sc->iobase) { + device_printf(dev, "No I/O space?!\n"); + return (ENXIO); + } + + sc->wi_io_addr = rman_get_start(sc->iobase); + sc->wi_btag = rman_get_bustag(sc->iobase); + sc->wi_bhandle = rman_get_bushandle(sc->iobase); + } else { + sc->mem_rid = rid; + sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, + &sc->mem_rid, 0, ~0, 1, RF_ACTIVE); + + if (!sc->mem) { + device_printf(dev, "No Mem space on prism2.5?\n"); + return (ENXIO); + } + + sc->wi_btag = rman_get_bustag(sc->mem); + sc->wi_bhandle = rman_get_bushandle(sc->mem); } + sc->irq_rid = 0; sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, - 0, ~0, 1, RF_ACTIVE); + 0, ~0, 1, RF_ACTIVE | + ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE)); + if (!sc->irq) { wi_free(dev); device_printf(dev, "No irq?!\n"); @@ -1961,9 +2078,6 @@ sc->dev = dev; sc->wi_unit = device_get_unit(dev); - sc->wi_io_addr = rman_get_start(sc->iobase); - sc->wi_btag = rman_get_bustag(sc->iobase); - sc->wi_bhandle = rman_get_bushandle(sc->iobase); return (0); } Index: if_wireg.h =================================================================== RCS file: /cvsroot/kame/kame/freebsd4/sys/i386/isa/if_wireg.h,v retrieving revision 1.1.1.2 retrieving revision 1.5 diff -u -r1.1.1.2 -r1.5 --- if_wireg.h 2001/09/25 05:08:08 1.1.1.2 +++ if_wireg.h 2002/02/16 23:10:49 1.5 @@ -135,10 +135,13 @@ int wi_nextitem; #endif struct callout_handle wi_stat_ch; - int wi_prism2; /* set to 1 if it uses a Prism II chip */ + int wi_prism2; + int wi_prism2_ver; + int wi_bus_type; /* Bus attachment type */ }; -#define WI_TIMEOUT 65536 +#define WI_DELAY 5 +#define WI_TIMEOUT (500000/WI_DELAY) /* 500 ms */ #define WI_PORT0 0 #define WI_PORT1 1 @@ -147,6 +150,7 @@ #define WI_PORT4 4 #define WI_PORT5 5 +#define WI_PCI_LMEMRES 0x10 /* PCI Memory (native PCI implementations) */ #define WI_PCI_LOCALRES 0x14 /* The PLX chip's local registers */ #define WI_PCI_MEMRES 0x18 /* The PCCard's attribute memory */ #define WI_PCI_IORES 0x1C /* The PCCard's I/O space */ @@ -155,6 +159,7 @@ #define WI_LOCAL_INTEN 0x40 /* poke this into INTCSR */ #define WI_HFA384X_SWSUPPORT0_OFF 0x28 #define WI_PRISM2STA_MAGIC 0x4A2D +#define WI_HFA384X_PCICOR_OFF 0x26 /* Default port: 0 (only 0 exists on stations) */ #define WI_DEFAULT_PORT (WI_PORT0 << 8) @@ -183,29 +188,38 @@ #define WI_DEFAULT_CHAN 3 +#define WI_BUS_PCCARD 0 /* pccard device */ +#define WI_BUS_PCI_PLX 1 /* PCI card w/ PLX PCI/PCMICA bridge */ +#define WI_BUS_PCI_NATIVE 2 /* native PCI device (Prism 2.5) */ + /* * register space access macros */ -#define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4(sc->wi_btag, sc->wi_bhandle, reg, val) -#define CSR_WRITE_2(sc, reg, val) \ - bus_space_write_2(sc->wi_btag, sc->wi_bhandle, reg, val) -#define CSR_WRITE_1(sc, reg, val) \ - bus_space_write_1(sc->wi_btag, sc->wi_bhandle, reg, val) - -#define CSR_READ_4(sc, reg) \ - bus_space_read_4(sc->wi_btag, sc->wi_bhandle, reg) -#define CSR_READ_2(sc, reg) \ - bus_space_read_2(sc->wi_btag, sc->wi_bhandle, reg) -#define CSR_READ_1(sc, reg) \ - bus_space_read_1(sc->wi_btag, sc->wi_bhandle, reg) +#define CSR_WRITE_4(sc, reg, val) \ + bus_space_write_4((sc)->wi_btag, (sc)->wi_bhandle, \ + (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg), val) +#define CSR_WRITE_2(sc, reg, val) \ + bus_space_write_2((sc)->wi_btag, (sc)->wi_bhandle, \ + (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg), val) +#define CSR_WRITE_1(sc, reg, val) \ + bus_space_write_1((sc)->wi_btag, (sc)->wi_bhandle, \ + (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg), val) + +#define CSR_READ_4(sc, reg) \ + bus_space_read_4((sc)->wi_btag, (sc)->wi_bhandle, \ + (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg)) +#define CSR_READ_2(sc, reg) \ + bus_space_read_2((sc)->wi_btag, (sc)->wi_bhandle, \ + (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg)) +#define CSR_READ_1(sc, reg) \ + bus_space_read_1((sc)->wi_btag, (sc)->wi_bhandle, \ + (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg)) #define CSM_WRITE_1(sc, off, val) \ - bus_space_write_1(sc->wi_bmemtag, sc->wi_bmemhandle, off, val) + bus_space_write_1((sc)->wi_bmemtag, (sc)->wi_bmemhandle, off, val) #define CSM_READ_1(sc, off) \ - bus_space_read_1(sc->wi_bmemtag, sc->wi_bmemhandle, off) - + bus_space_read_1((sc)->wi_bmemtag, (sc)->wi_bmemhandle, off) /* * The WaveLAN/IEEE cards contain an 802.11 MAC controller which Lucent @@ -438,6 +452,26 @@ u_int16_t wi_type; u_int16_t wi_mem_ram; u_int16_t wi_mem_nvram; +}; + +/* + * NIC Identification (0xFD0B) + */ +#define WI_RID_CARDID 0xFD0B +#define WI_RID_IDENT 0xFD20 +struct wi_ltv_ver { + u_int16_t wi_len; + u_int16_t wi_type; + u_int16_t wi_ver[4]; +#define WI_NIC_EVB2 0x8000 +#define WI_NIC_HWB3763 0x8001 +#define WI_NIC_HWB3163 0x8002 +#define WI_NIC_HWB3163B 0x8003 +#define WI_NIC_EVB3 0x8004 +#define WI_NIC_HWB1153 0x8007 +#define WI_NIC_P2_SST 0x8008 /* Prism2 with SST flush */ +#define WI_NIC_PRISM2_5 0x800C +#define WI_NIC_3874A 0x8013 /* Prism2.5 Mini-PCI */ }; /*