Add support for the Addtron AWA100 PCI wireless card.

The AWA100 is a PCI board with a PLX 9052 chip that's used to talk to
the pccard inserted into the board.

Remove a redundant $FreeBSD while I'm here.
This commit is contained in:
alfred 2001-03-28 05:05:05 +00:00
parent 6ed0e9c365
commit 0d2956305c
2 changed files with 157 additions and 16 deletions

View File

@ -28,8 +28,6 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/ */
/* /*
@ -85,6 +83,9 @@
#include <machine/bus_pio.h> #include <machine/bus_pio.h>
#include <sys/rman.h> #include <sys/rman.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <net/ethernet.h> #include <net/ethernet.h>
@ -148,13 +149,16 @@ void wi_cache_store __P((struct wi_softc *, struct ether_header *,
struct mbuf *, unsigned short)); struct mbuf *, unsigned short));
#endif #endif
static int wi_generic_attach __P((device_t));
static int wi_pccard_match __P((device_t)); static int wi_pccard_match __P((device_t));
static int wi_pccard_probe __P((device_t)); static int wi_pccard_probe __P((device_t));
static int wi_pci_probe __P((device_t));
static int wi_pccard_attach __P((device_t)); static int wi_pccard_attach __P((device_t));
static int wi_pci_attach __P((device_t));
static int wi_pccard_detach __P((device_t)); static int wi_pccard_detach __P((device_t));
static void wi_shutdown __P((device_t)); static void wi_shutdown __P((device_t));
static int wi_alloc __P((device_t)); static int wi_alloc __P((device_t, int));
static void wi_free __P((device_t)); static void wi_free __P((device_t));
static device_method_t wi_pccard_methods[] = { static device_method_t wi_pccard_methods[] = {
@ -172,15 +176,33 @@ static device_method_t wi_pccard_methods[] = {
{ 0, 0 } { 0, 0 }
}; };
static device_method_t wi_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, wi_pci_probe),
DEVMETHOD(device_attach, wi_pci_attach),
DEVMETHOD(device_detach, wi_pccard_detach),
DEVMETHOD(device_shutdown, wi_shutdown),
{ 0, 0 }
};
static driver_t wi_pccard_driver = { static driver_t wi_pccard_driver = {
"wi", "wi",
wi_pccard_methods, wi_pccard_methods,
sizeof(struct wi_softc) sizeof(struct wi_softc)
}; };
static driver_t wi_pci_driver = {
"wi",
wi_pci_methods,
sizeof(struct wi_softc)
};
static devclass_t wi_pccard_devclass; static devclass_t wi_pccard_devclass;
static devclass_t wi_pci_devclass;
DRIVER_MODULE(if_wi, pccard, wi_pccard_driver, wi_pccard_devclass, 0, 0); DRIVER_MODULE(if_wi, pccard, wi_pccard_driver, wi_pccard_devclass, 0, 0);
DRIVER_MODULE(if_wi, pci, wi_pci_driver, wi_pci_devclass, 0, 0);
static const struct pccard_product wi_pccard_products[] = { static const struct pccard_product wi_pccard_products[] = {
{ PCCARD_STR_LUCENT_WAVELAN_IEEE, PCCARD_VENDOR_LUCENT, { PCCARD_STR_LUCENT_WAVELAN_IEEE, PCCARD_VENDOR_LUCENT,
@ -188,6 +210,8 @@ static const struct pccard_product wi_pccard_products[] = {
PCCARD_CIS_LUCENT_WAVELAN_IEEE }, PCCARD_CIS_LUCENT_WAVELAN_IEEE },
}; };
static char wi_device_desc[] = "WaveLAN/IEEE 802.11";
static int wi_pccard_match(dev) static int wi_pccard_match(dev)
device_t dev; device_t dev;
{ {
@ -210,11 +234,10 @@ static int wi_pccard_probe(dev)
sc = device_get_softc(dev); sc = device_get_softc(dev);
sc->wi_gone = 0; sc->wi_gone = 0;
error = wi_alloc(dev); error = wi_alloc(dev, 0);
if (error) if (error)
return (error); return (error);
device_set_desc(dev, "WaveLAN/IEEE 802.11");
wi_free(dev); wi_free(dev);
/* Make sure interrupts are disabled. */ /* Make sure interrupts are disabled. */
@ -224,6 +247,22 @@ static int wi_pccard_probe(dev)
return (0); return (0);
} }
static int
wi_pci_probe(dev)
device_t dev;
{
struct wi_softc *sc;
sc = device_get_softc(dev);
if ((pci_get_vendor(dev) == WI_PCI_VENDOR_Eumitcom) &&
(pci_get_device(dev) == WI_PCI_DEVICE_PRISM2STA)) {
sc->wi_prism2 = 1;
device_set_desc(dev, "PRISM2STA PCI WaveLAN/IEEE 802.11");
return (0);
}
return(ENXIO);
}
static int wi_pccard_detach(dev) static int wi_pccard_detach(dev)
device_t dev; device_t dev;
{ {
@ -257,14 +296,10 @@ static int wi_pccard_detach(dev)
static int wi_pccard_attach(device_t dev) static int wi_pccard_attach(device_t dev)
{ {
struct wi_softc *sc; struct wi_softc *sc;
struct wi_ltv_macaddr mac;
struct wi_ltv_gen gen;
struct ifnet *ifp;
int error; int error;
u_int32_t flags; u_int32_t flags;
sc = device_get_softc(dev); sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
/* /*
* XXX: quick hack to support Prism II chip. * XXX: quick hack to support Prism II chip.
@ -289,11 +324,91 @@ static int wi_pccard_attach(device_t dev)
} }
} }
error = wi_alloc(dev); error = wi_alloc(dev, 0);
if (error) { if (error) {
device_printf(dev, "wi_alloc() failed! (%d)\n", error); device_printf(dev, "wi_alloc() failed! (%d)\n", error);
return (error); return (error);
} }
return (wi_generic_attach(dev));
}
static int
wi_pci_attach(device_t dev)
{
struct wi_softc *sc;
u_int32_t command, wanted;
u_int16_t reg;
int error;
sc = device_get_softc(dev);
command = pci_read_config(dev, PCIR_COMMAND, 4);
wanted = PCIM_CMD_PORTEN|PCIM_CMD_MEMEN;
command |= wanted;
pci_write_config(dev, PCIR_COMMAND, command, 4);
command = pci_read_config(dev, PCIR_COMMAND, 4);
if ((command & wanted) != wanted) {
device_printf(dev, "wi_pci_attach() failed to enable pci!\n");
return (ENXIO);
}
error = wi_alloc(dev, WI_PCI_IORES);
if (error)
return (error);
device_set_desc(dev, wi_device_desc);
/* Make sure interrupts are disabled. */
CSR_WRITE_2(sc, WI_INT_EN, 0);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
sc->mem_rid = 0x18;
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
* (FOR GREAT JUSTICE)
*/
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);
if (reg != WI_PRISM2STA_MAGIC) {
device_printf(dev,
"CSR_READ_2(WI_HFA384x_SWSUPPORT0_OFF) wanted %d, got %d\n",
WI_PRISM2STA_MAGIC, reg);
wi_free(dev);
return (ENXIO);
}
error = wi_generic_attach(dev);
if (error != 0)
return (error);
return (0);
}
static int
wi_generic_attach(device_t dev)
{
struct wi_softc *sc;
struct wi_ltv_macaddr mac;
struct wi_ltv_gen gen;
struct ifnet *ifp;
int error;
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
wi_intr, sc, &sc->wi_intrhand); wi_intr, sc, &sc->wi_intrhand);
@ -1541,14 +1656,15 @@ static void wi_watchdog(ifp)
return; return;
} }
static int wi_alloc(dev) static int
wi_alloc(dev, io_rid)
device_t dev; device_t dev;
int io_rid;
{ {
struct wi_softc *sc = device_get_softc(dev); struct wi_softc *sc = device_get_softc(dev);
int rid;
rid = 0; sc->iobase_rid = io_rid;
sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->iobase_rid,
0, ~0, (1 << 6), 0, ~0, (1 << 6),
rman_make_alignment_flags(1 << 6) | RF_ACTIVE); rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
if (!sc->iobase) { if (!sc->iobase) {
@ -1556,8 +1672,8 @@ static int wi_alloc(dev)
return (ENXIO); return (ENXIO);
} }
rid = 0; sc->irq_rid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
0, ~0, 1, RF_ACTIVE); 0, ~0, 1, RF_ACTIVE);
if (!sc->irq) { if (!sc->irq) {
device_printf(dev, "No irq?!\n"); device_printf(dev, "No irq?!\n");
@ -1582,6 +1698,8 @@ static void wi_free(dev)
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->iobase); bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->iobase);
if (sc->irq != NULL) if (sc->irq != NULL)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
if (sc->mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
return; return;
} }

View File

@ -90,9 +90,15 @@ struct wi_softc {
device_t dev; device_t dev;
int wi_unit; int wi_unit;
struct resource * iobase; struct resource * iobase;
int iobase_rid;
struct resource * irq; struct resource * irq;
int irq_rid;
struct resource * mem;
int mem_rid;
bus_space_handle_t wi_bhandle; bus_space_handle_t wi_bhandle;
bus_space_tag_t wi_btag; bus_space_tag_t wi_btag;
bus_space_handle_t wi_bmemhandle;
bus_space_tag_t wi_bmemtag;
void * wi_intrhand; void * wi_intrhand;
int wi_io_addr; int wi_io_addr;
int wi_tx_data_id; int wi_tx_data_id;
@ -140,6 +146,13 @@ struct wi_softc {
#define WI_PORT4 4 #define WI_PORT4 4
#define WI_PORT5 5 #define WI_PORT5 5
#define WI_PCI_IORES 0x1c
#define WI_PCI_VENDOR_Eumitcom 0x1638
#define WI_PCI_DEVICE_PRISM2STA 0x1100
#define WI_HFA384x_SWSUPPORT0_OFF 0x28
#define WI_PRISM2STA_MAGIC 0x4a2d
/* Default port: 0 (only 0 exists on stations) */ /* Default port: 0 (only 0 exists on stations) */
#define WI_DEFAULT_PORT (WI_PORT0 << 8) #define WI_DEFAULT_PORT (WI_PORT0 << 8)
@ -184,6 +197,13 @@ struct wi_softc {
#define CSR_READ_1(sc, reg) \ #define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->wi_btag, sc->wi_bhandle, reg) bus_space_read_1(sc->wi_btag, sc->wi_bhandle, reg)
#define CSM_WRITE_1(sc, 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)
/* /*
* The WaveLAN/IEEE cards contain an 802.11 MAC controller which Lucent * The WaveLAN/IEEE cards contain an 802.11 MAC controller which Lucent
* calls 'Hermes.' In typical fashion, getting documentation about this * calls 'Hermes.' In typical fashion, getting documentation about this
@ -349,6 +369,9 @@ struct wi_softc {
#define WI_AUX_OFFSET 0x3C #define WI_AUX_OFFSET 0x3C
#define WI_AUX_DATA 0x3E #define WI_AUX_DATA 0x3E
#define WI_COR_OFFSET 0x3e0
#define WI_COR_VALUE 0x41
/* /*
* One form of communication with the Hermes is with what Lucent calls * One form of communication with the Hermes is with what Lucent calls
* LTV records, where LTV stands for Length, Type and Value. The length * LTV records, where LTV stands for Length, Type and Value. The length