diff options
author | tanimura <tanimura@FreeBSD.org> | 2000-07-23 15:15:43 +0000 |
---|---|---|
committer | tanimura <tanimura@FreeBSD.org> | 2000-07-23 15:15:43 +0000 |
commit | 314fd9990b8d7318d55df0fd6e87d0af6aa4cbf0 (patch) | |
tree | 068d1c849661b2f20e43b8ed237230489fd041bf /sys/dev/ed/if_ed_pccard.c | |
parent | 2ae5c3dffce3ca0150eb28e8e2e79b27183490c4 (diff) | |
download | FreeBSD-src-314fd9990b8d7318d55df0fd6e87d0af6aa4cbf0.zip FreeBSD-src-314fd9990b8d7318d55df0fd6e87d0af6aa4cbf0.tar.gz |
MFPAO: Add support for AX88190, equipped in MELCO LPC3-TX.
Diffstat (limited to 'sys/dev/ed/if_ed_pccard.c')
-rw-r--r-- | sys/dev/ed/if_ed_pccard.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c index 9d5fb7f..49bdab8 100644 --- a/sys/dev/ed/if_ed_pccard.c +++ b/sys/dev/ed/if_ed_pccard.c @@ -31,6 +31,10 @@ #include <sys/systm.h> #include <sys/socket.h> #include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/select.h> +#include <machine/clock.h> #include <sys/module.h> #include <sys/bus.h> @@ -41,8 +45,13 @@ #include <net/if_arp.h> #include <net/if_mib.h> +#include <dev/ed/if_edreg.h> #include <dev/ed/if_edvar.h> #include <dev/pccard/pccardvar.h> +#include <pccard/cardinfo.h> +#include <pccard/slot.h> + +#define CARD_MAJOR 50 /* * PC-Card (PCMCIA) specific code. @@ -51,6 +60,10 @@ static int ed_pccard_probe(device_t); static int ed_pccard_attach(device_t); static int ed_pccard_detach(device_t); +static void ax88190_geteprom(device_t); +static int ed_pccard_memwrite(device_t dev, off_t offset, u_char byte); +static int ed_pccard_memread(device_t dev, off_t offset, u_char *buf, int size); + static device_method_t ed_pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ed_pccard_probe), @@ -107,6 +120,32 @@ static int ed_pccard_probe(device_t dev) { int error; + int flags; + struct ed_softc *sc = device_get_softc(dev); + + flags = device_get_flags(dev); + + if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_AX88190) { + /* Special setup for AX88190 */ + u_char rdbuf[4]; + int iobase; + int attr_ioport; + sc->chip_type = ED_CHIP_TYPE_AX88190; + /* + * Check & Set Attribute Memory IOBASE Register + */ + ed_pccard_memread(dev,ED_AX88190_IOBASE0,rdbuf,4); + attr_ioport = rdbuf[2] << 8 | rdbuf[0]; + iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); + if (attr_ioport != iobase) { +#if notdef + printf("AX88190 IOBASE MISMATCH %04x -> %04x Setting\n",attr_ioport,iobase); +#endif /* notdef */ + ed_pccard_memwrite(dev,ED_AX88190_IOBASE0,iobase & 0xff); + ed_pccard_memwrite(dev,ED_AX88190_IOBASE1,(iobase >> 8) & 0xff); + } + ax88190_geteprom(dev); + } error = ed_probe_Novell(dev); if (error == 0) @@ -161,3 +200,121 @@ ed_pccard_attach(device_t dev) error = ed_attach(sc, device_get_unit(dev), flags); return (error); } + +static void +ax88190_geteprom(device_t dev) +{ + int prom[16],i; + u_char tmp; + struct ed_softc *sc; + struct pccard_devinfo *devi; + int iobase; + struct { + unsigned char offset,value; + } pg_seq[]={ + {ED_P0_CR ,ED_CR_RD2|ED_CR_STP}, /* Select Page0 */ + {ED_P0_DCR,0x01}, + {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */ + {ED_P0_RBCR1, 0x00}, + {ED_P0_IMR, 0x00}, /* Mask completion irq. */ + {ED_P0_ISR, 0xff}, + {ED_P0_RCR, ED_RCR_MON|ED_RCR_INTT}, /* Set To Monitor */ + {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */ + {ED_P0_RBCR0,32}, + {ED_P0_RBCR1,0x00}, + {ED_P0_RSAR0,0x00}, + {ED_P0_RSAR1,0x04}, + {ED_P0_CR ,ED_CR_RD0|ED_CR_STA}, + }; + + sc = device_get_softc(dev); + devi = device_get_ivars(dev); + iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); + + /* XXX: no bus_space_*()? */ + + /* Default Set */ + sc->asic_addr = iobase + ED_NOVELL_ASIC_OFFSET; + sc->nic_addr = iobase + ED_NOVELL_NIC_OFFSET; + /* Reset Card */ + tmp = inb(sc->asic_addr + ED_NOVELL_RESET); + outb(sc->asic_addr + ED_NOVELL_RESET, tmp); + DELAY(5000); + outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2 | ED_CR_STP); + DELAY(5000); + + /* Card Settings */ + for(i=0;i<sizeof(pg_seq)/sizeof(pg_seq[0]);i++) { + outb(sc->nic_addr + pg_seq[i].offset , pg_seq[i].value); + } + + /* Get Data */ + for(i=0;i<16;i++) { + prom[i] = inw(sc->asic_addr); + } +/* + for(i=0;i<16;i++) { + printf("ax88190 eprom [%02d] %02x %02x\n", + i,prom[i] & 0xff,prom[i] >> 8); + } +*/ + sc->arpcom.ac_enaddr[0] = prom[0] & 0xff; + sc->arpcom.ac_enaddr[1] = prom[0] >> 8; + sc->arpcom.ac_enaddr[2] = prom[1] & 0xff; + sc->arpcom.ac_enaddr[3] = prom[1] >> 8; + sc->arpcom.ac_enaddr[4] = prom[2] & 0xff; + sc->arpcom.ac_enaddr[5] = prom[2] >> 8; + + return; +} + +/* XXX: Warner-san, any plan to provide access to the attribute memory? */ +static int +ed_pccard_memwrite(device_t dev, off_t offset, u_char byte) +{ + struct pccard_devinfo *devi; + dev_t d; + struct iovec iov; + struct uio uios; + + devi = device_get_ivars(dev); + + iov.iov_base = &byte; + iov.iov_len = sizeof(byte); + + uios.uio_iov = &iov; + uios.uio_iovcnt = 1; + uios.uio_offset = offset; + uios.uio_resid = sizeof(byte); + uios.uio_segflg = UIO_SYSSPACE; + uios.uio_rw = UIO_WRITE; + uios.uio_procp = 0; + + d = makedev(CARD_MAJOR, devi->slt->slotnum); + return devsw(d)->d_write(d, &uios, 0); +} + +static int +ed_pccard_memread(device_t dev, off_t offset, u_char *buf, int size) +{ + struct pccard_devinfo *devi; + dev_t d; + struct iovec iov; + struct uio uios; + + devi = device_get_ivars(dev); + + iov.iov_base = buf; + iov.iov_len = size; + + uios.uio_iov = &iov; + uios.uio_iovcnt = 1; + uios.uio_offset = offset; + uios.uio_resid = size; + uios.uio_segflg = UIO_SYSSPACE; + uios.uio_rw = UIO_READ; + uios.uio_procp = 0; + + d = makedev(CARD_MAJOR, devi->slt->slotnum); + return devsw(d)->d_read(d, &uios, 0); +} |