Add support for the Linksys WMP-11, Prism 2.5, PCI adaptor.
Submitted by: Thomas Skibo <skibo@pacbell.net> MFC after: 2 weeks
This commit is contained in:
parent
02ccbdf67a
commit
e2119ba50b
@ -223,12 +223,14 @@ static driver_t wi_pci_driver = {
|
||||
|
||||
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, 0x1101, "GLPRISM2 PCI WaveLAN/IEEE 802.11"},
|
||||
{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
|
||||
@ -291,6 +293,7 @@ wi_pccard_probe(dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->wi_gone = 0;
|
||||
sc->wi_bus_type = WI_BUS_PCCARD;
|
||||
|
||||
error = wi_alloc(dev, 0);
|
||||
if (error)
|
||||
@ -318,6 +321,7 @@ wi_pci_probe(dev)
|
||||
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);
|
||||
}
|
||||
@ -383,6 +387,7 @@ wi_pci_attach(device_t dev)
|
||||
u_int32_t command, wanted;
|
||||
u_int16_t reg;
|
||||
int error;
|
||||
int timeout;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
@ -396,47 +401,77 @@ wi_pci_attach(device_t dev)
|
||||
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;
|
||||
/* 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->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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC);
|
||||
reg = CSR_READ_2(sc, WI_HFA384X_SWSUPPORT0_OFF);
|
||||
@ -955,6 +990,7 @@ wi_cmd(sc, cmd, val)
|
||||
DELAY(10*1000); /* 10 m sec */
|
||||
}
|
||||
if (i == 0) {
|
||||
device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" );
|
||||
return(ETIMEDOUT);
|
||||
}
|
||||
|
||||
@ -968,8 +1004,8 @@ wi_cmd(sc, cmd, val)
|
||||
* 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);
|
||||
@ -981,12 +1017,14 @@ wi_cmd(sc, cmd, val)
|
||||
return(EIO);
|
||||
break;
|
||||
}
|
||||
if (cmd == WI_CMD_INI)
|
||||
DELAY(100);
|
||||
DELAY(WI_DELAY);
|
||||
}
|
||||
|
||||
if (i == WI_TIMEOUT)
|
||||
if (i == WI_TIMEOUT) {
|
||||
device_printf(sc->dev,
|
||||
"timeout in wi_cmd %x; event status %x\n", cmd, s);
|
||||
return(ETIMEDOUT);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -1001,7 +1039,7 @@ wi_reset(sc)
|
||||
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");
|
||||
@ -1216,6 +1254,7 @@ wi_seek(sc, id, off, chan)
|
||||
status = CSR_READ_2(sc, offreg);
|
||||
if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
|
||||
break;
|
||||
DELAY(WI_DELAY);
|
||||
}
|
||||
|
||||
if (i == WI_TIMEOUT) {
|
||||
@ -1322,6 +1361,7 @@ wi_alloc_nicmem(sc, len, id)
|
||||
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) {
|
||||
@ -2077,24 +2117,45 @@ wi_watchdog(ifp)
|
||||
}
|
||||
|
||||
static int
|
||||
wi_alloc(dev, io_rid)
|
||||
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 << 6),
|
||||
rman_make_alignment_flags(1 << 6) | 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");
|
||||
@ -2103,9 +2164,6 @@ wi_alloc(dev, io_rid)
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -137,12 +137,14 @@ struct wi_softc {
|
||||
struct mtx wi_mtx;
|
||||
int wi_prism2;
|
||||
int wi_prism2_ver;
|
||||
int wi_bus_type; /* Bus attachment type */
|
||||
};
|
||||
|
||||
#define WI_LOCK(_sc)
|
||||
#define WI_UNLOCK(_sc)
|
||||
|
||||
#define WI_TIMEOUT 65536
|
||||
#define WI_DELAY 5
|
||||
#define WI_TIMEOUT (500000/WI_DELAY) /* 500 ms */
|
||||
|
||||
#define WI_PORT0 0
|
||||
#define WI_PORT1 1
|
||||
@ -151,6 +153,7 @@ struct wi_softc {
|
||||
#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 */
|
||||
@ -159,6 +162,7 @@ struct wi_softc {
|
||||
#define WI_LOCAL_INTEN 0x40
|
||||
#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)
|
||||
@ -187,29 +191,38 @@ struct wi_softc {
|
||||
|
||||
#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_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, 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_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
|
||||
|
Loading…
Reference in New Issue
Block a user