summaryrefslogtreecommitdiffstats
path: root/sys/dev/ed/if_ed_pccard.c
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2000-07-23 15:15:43 +0000
committertanimura <tanimura@FreeBSD.org>2000-07-23 15:15:43 +0000
commit314fd9990b8d7318d55df0fd6e87d0af6aa4cbf0 (patch)
tree068d1c849661b2f20e43b8ed237230489fd041bf /sys/dev/ed/if_ed_pccard.c
parent2ae5c3dffce3ca0150eb28e8e2e79b27183490c4 (diff)
downloadFreeBSD-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.c157
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);
+}
OpenPOWER on IntegriCloud