ASIX AX88190 support (Planex FNW-3700-T and Melco LPC3-TX) from FreeBSD/PAO3.

This commit is contained in:
enami 2000-02-09 15:40:23 +00:00
parent 67bc20747a
commit e00270524e
7 changed files with 145 additions and 18 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dp8390.c,v 1.32 2000/02/09 14:42:33 enami Exp $ */ /* $NetBSD: dp8390.c,v 1.33 2000/02/09 15:40:23 enami Exp $ */
/* /*
* Device driver for National Semiconductor DS8390/WD83C690 based ethernet * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
@ -296,7 +296,7 @@ dp8390_init(sc)
NIC_PUT(regt, regh, ED_P0_RBCR1, 0); NIC_PUT(regt, regh, ED_P0_RBCR1, 0);
/* Tell RCR to do nothing for now. */ /* Tell RCR to do nothing for now. */
NIC_PUT(regt, regh, ED_P0_RCR, ED_RCR_MON); NIC_PUT(regt, regh, ED_P0_RCR, ED_RCR_MON | sc->rcr_proto);
/* Place NIC in internal loopback mode. */ /* Place NIC in internal loopback mode. */
NIC_PUT(regt, regh, ED_P0_TCR, ED_TCR_LB0); NIC_PUT(regt, regh, ED_P0_TCR, ED_TCR_LB0);
@ -352,7 +352,7 @@ dp8390_init(sc)
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP); sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
/* Accept broadcast and multicast packets by default. */ /* Accept broadcast and multicast packets by default. */
i = ED_RCR_AB | ED_RCR_AM; i = ED_RCR_AB | ED_RCR_AM | sc->rcr_proto;
if (ifp->if_flags & IFF_PROMISC) { if (ifp->if_flags & IFF_PROMISC) {
/* /*
* Set promiscuous mode. Multicast filter was set earlier so * Set promiscuous mode. Multicast filter was set earlier so
@ -651,6 +651,13 @@ dp8390_intr(arg)
*/ */
NIC_PUT(regt, regh, ED_P0_ISR, isr); NIC_PUT(regt, regh, ED_P0_ISR, isr);
/* Work around for AX88190 bug */
if ((sc->sc_flags & DP8390_DO_AX88190_WORKAROUND) != 0)
while ((NIC_GET(regt, regh, ED_P0_ISR) & isr) != 0) {
NIC_PUT(regt, regh, ED_P0_ISR, 0);
NIC_PUT(regt, regh, ED_P0_ISR, isr);
}
/* /*
* Handle transmitter interrupts. Handle these first because * Handle transmitter interrupts. Handle these first because
* the receiver will reset the board under some conditions. * the receiver will reset the board under some conditions.

View File

@ -1,4 +1,4 @@
/* $NetBSD: dp8390reg.h,v 1.4 1998/10/27 23:34:17 thorpej Exp $ */ /* $NetBSD: dp8390reg.h,v 1.5 2000/02/09 15:40:24 enami Exp $ */
/* /*
* National Semiconductor DS8390 NIC register definitions. * National Semiconductor DS8390 NIC register definitions.
@ -460,7 +460,12 @@
#define ED_RCR_MON 0x20 #define ED_RCR_MON 0x20
/* /*
* Bits 6 and 7 are unused/reserved. * INTT: Interrupt Trigger Mode. Must be set if AX88190.
*/
#define ED_RCR_INTT 0x40
/*
* Bit 7 is unused/reserved.
*/ */
/* /*

View File

@ -1,4 +1,4 @@
/* $NetBSD: dp8390var.h,v 1.15 2000/02/09 14:42:34 enami Exp $ */ /* $NetBSD: dp8390var.h,v 1.16 2000/02/09 15:40:24 enami Exp $ */
/* /*
* Device driver for National Semiconductor DS8390/WD83C690 based ethernet * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
@ -41,6 +41,7 @@ struct dp8390_softc {
int is790; /* NIC is a 790 */ int is790; /* NIC is a 790 */
u_int8_t cr_proto; /* values always set in CR */ u_int8_t cr_proto; /* values always set in CR */
u_int8_t rcr_proto; /* values always set in RCR */
u_int8_t dcr_reg; /* override DCR iff LS is set */ u_int8_t dcr_reg; /* override DCR iff LS is set */
int mem_start; /* offset of NIC memory */ int mem_start; /* offset of NIC memory */
@ -126,6 +127,11 @@ struct dp8390_softc {
*/ */
#define DP8390_FORCE_PIO 0x0010 #define DP8390_FORCE_PIO 0x0010
/*
* The chip is ASIX AX88190 and needs work around.
*/
#define DP8390_DO_AX88190_WORKAROUND 0x0020
/* /*
* NIC register access macros * NIC register access macros
*/ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ne2000.c,v 1.26 2000/02/09 14:42:35 enami Exp $ */ /* $NetBSD: ne2000.c,v 1.27 2000/02/09 15:40:24 enami Exp $ */
/*- /*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@ -128,6 +128,11 @@ ne2000_attach(nsc, myea, media, nmedia, defmedia)
useword = NE2000_USE_WORD(nsc); useword = NE2000_USE_WORD(nsc);
dsc->cr_proto = ED_CR_RD2; dsc->cr_proto = ED_CR_RD2;
if (nsc->sc_type == NE2000_TYPE_AX88190) {
dsc->rcr_proto = ED_RCR_INTT;
dsc->sc_flags |= DP8390_DO_AX88190_WORKAROUND;
} else
dsc->rcr_proto = 0;
/* /*
* DCR gets: * DCR gets:
@ -157,6 +162,7 @@ ne2000_attach(nsc, myea, media, nmedia, defmedia)
memsize = 8192; memsize = 8192;
break; break;
case NE2000_TYPE_NE2000: case NE2000_TYPE_NE2000:
case NE2000_TYPE_AX88190: /* XXX really? */
memsize = 8192 * 2; memsize = 8192 * 2;
break; break;
case NE2000_TYPE_DL10019: case NE2000_TYPE_DL10019:
@ -243,10 +249,22 @@ ne2000_attach(nsc, myea, media, nmedia, defmedia)
if (myea == NULL) { if (myea == NULL) {
/* Read the station address. */ /* Read the station address. */
ne2000_readmem(nict, nich, asict, asich, 0, romdata, if (nsc->sc_type == NE2000_TYPE_AX88190) {
sizeof(romdata), useword); /* Select page 0 registers. */
for (i = 0; i < ETHER_ADDR_LEN; i++) bus_space_write_1(nict, nich, ED_P0_CR,
dsc->sc_enaddr[i] = romdata[i * (useword ? 2 : 1)]; ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Select word transfer. */
bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_WTS);
ne2000_readmem(nict, nich, asict, asich,
NE2000_AX88190_NODEID_OFFSET, dsc->sc_enaddr,
ETHER_ADDR_LEN, useword);
} else {
ne2000_readmem(nict, nich, asict, asich, 0, romdata,
sizeof(romdata), useword);
for (i = 0; i < ETHER_ADDR_LEN; i++)
dsc->sc_enaddr[i] =
romdata[i * (useword ? 2 : 1)];
}
} else } else
bcopy(myea, dsc->sc_enaddr, sizeof(dsc->sc_enaddr)); bcopy(myea, dsc->sc_enaddr, sizeof(dsc->sc_enaddr));
@ -264,6 +282,7 @@ ne2000_attach(nsc, myea, media, nmedia, defmedia)
*/ */
dsc->mem_ring = dsc->mem_ring =
dsc->mem_start + ((dsc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT); dsc->mem_start + ((dsc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
return (0); return (0);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: ne2000reg.h,v 1.2 1997/10/14 22:54:11 thorpej Exp $ */ /* $NetBSD: ne2000reg.h,v 1.3 2000/02/09 15:40:24 enami Exp $ */
/* /*
* National Semiconductor DS8390 NIC register definitions. * National Semiconductor DS8390 NIC register definitions.
@ -29,4 +29,15 @@
#define NE2000_ASIC_DATA 0x00 /* remote DMA/data register */ #define NE2000_ASIC_DATA 0x00 /* remote DMA/data register */
#define NE2000_ASIC_RESET 0x0f /* reset on read */ #define NE2000_ASIC_RESET 0x0f /* reset on read */
/*
* Offset of NODE ID in SRAM memory of ASIX AX88190.
*/
#define NE2000_AX88190_NODEID_OFFSET 0x400
/*
* Offset of LAN IOBASE0 and IOBASE1, and its size.
*/
#define NE2000_AX88190_LAN_IOBASE 0x3ca
#define NE2000_AX88190_LAN_IOSIZE 4
#endif /* _DEV_IC_NE2000REG_H_ */ #endif /* _DEV_IC_NE2000REG_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ne2000var.h,v 1.9 2000/02/09 14:42:35 enami Exp $ */ /* $NetBSD: ne2000var.h,v 1.10 2000/02/09 15:40:24 enami Exp $ */
/*- /*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@ -53,10 +53,12 @@ struct ne2000_softc {
#define NE2000_TYPE_NE1000 1 #define NE2000_TYPE_NE1000 1
#define NE2000_TYPE_NE2000 2 #define NE2000_TYPE_NE2000 2
#define NE2000_TYPE_DL10019 3 #define NE2000_TYPE_DL10019 3
#define NE2000_TYPE_AX88190 4
#define NE2000_USE_WORD(sc) \ #define NE2000_USE_WORD(sc) \
(((sc)->sc_type == NE2000_TYPE_NE2000) || \ (((sc)->sc_type == NE2000_TYPE_NE2000) || \
((sc)->sc_type == NE2000_TYPE_DL10019)) ((sc)->sc_type == NE2000_TYPE_DL10019) || \
((sc)->sc_type == NE2000_TYPE_AX88190))
int ne2000_attach __P((struct ne2000_softc *, u_int8_t *, int ne2000_attach __P((struct ne2000_softc *, u_int8_t *,
int *, int, int)); int *, int, int));

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ne_pcmcia.c,v 1.54 2000/02/09 14:54:53 enami Exp $ */ /* $NetBSD: if_ne_pcmcia.c,v 1.55 2000/02/09 15:40:26 enami Exp $ */
/* /*
* Copyright (c) 1997 Marc Horowitz. All rights reserved. * Copyright (c) 1997 Marc Horowitz. All rights reserved.
@ -80,6 +80,7 @@ u_int8_t *
u_int8_t * u_int8_t *
ne_pcmcia_dl10019_get_enaddr __P((struct ne_pcmcia_softc *, ne_pcmcia_dl10019_get_enaddr __P((struct ne_pcmcia_softc *,
u_int8_t [ETHER_ADDR_LEN])); u_int8_t [ETHER_ADDR_LEN]));
int ne_pcmcia_ax88190_set_iobase __P((struct ne_pcmcia_softc *));
struct cfattach ne_pcmcia_ca = { struct cfattach ne_pcmcia_ca = {
sizeof(struct ne_pcmcia_softc), ne_pcmcia_match, ne_pcmcia_attach, sizeof(struct ne_pcmcia_softc), ne_pcmcia_match, ne_pcmcia_attach,
@ -96,6 +97,7 @@ struct ne2000dev {
unsigned char enet_vendor[3]; unsigned char enet_vendor[3];
int flags; int flags;
#define NE2000DVF_DL10019 0x0001 /* chip is D-Link DL10019 */ #define NE2000DVF_DL10019 0x0001 /* chip is D-Link DL10019 */
#define NE2000DVF_AX88190 0x0002 /* chip is ASIX AX88190 */
} ne2000devs[] = { } ne2000devs[] = {
{ PCMCIA_STR_AMBICOM_AMB8002T, { PCMCIA_STR_AMBICOM_AMB8002T,
PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
@ -173,6 +175,11 @@ struct ne2000dev {
PCMCIA_CIS_PLANEX_FNW3600T, PCMCIA_CIS_PLANEX_FNW3600T,
0, -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 }, 0, -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 },
{ PCMCIA_STR_PLANEX_FNW3700T,
PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD,
PCMCIA_CIS_PLANEX_FNW3700T,
0, -1, { 0x00, 0x90, 0xcc }, NE2000DVF_AX88190 },
{ PCMCIA_STR_SVEC_PN650TX, { PCMCIA_STR_SVEC_PN650TX,
PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD, PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD,
PCMCIA_CIS_SVEC_PN650TX, PCMCIA_CIS_SVEC_PN650TX,
@ -292,6 +299,11 @@ struct ne2000dev {
PCMCIA_CIS_XIRCOM_CFE_10, PCMCIA_CIS_XIRCOM_CFE_10,
0, -1, { 0x00, 0x10, 0xa4 } }, 0, -1, { 0x00, 0x10, 0xa4 } },
{ PCMCIA_STR_MELCO_LPC3_TX,
PCMCIA_VENDOR_MELCO, PCMCIA_PRODUCT_MELCO_LPC3_TX,
PCMCIA_CIS_MELCO_LPC3_TX,
0, -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 },
#if 0 #if 0
/* the rest of these are stolen from the linux pcnet pcmcia device /* the rest of these are stolen from the linux pcnet pcmcia device
driver. Since I don't know the manfid or cis info strings for driver. Since I don't know the manfid or cis info strings for
@ -427,7 +439,7 @@ ne_pcmcia_attach(parent, self, aux)
struct pcmcia_config_entry *cfe; struct pcmcia_config_entry *cfe;
struct ne2000dev *ne_dev; struct ne2000dev *ne_dev;
int i; int i;
u_int8_t myea[6], *enaddr = NULL; u_int8_t myea[6], *enaddr;
void (*npp_init_media) __P((struct dp8390_softc *, int **, void (*npp_init_media) __P((struct dp8390_softc *, int **,
int *, int *)); int *, int *));
int *media, nmedia, defmedia; int *media, nmedia, defmedia;
@ -440,6 +452,9 @@ ne_pcmcia_attach(parent, self, aux)
psc->sc_pf = pa->pf; psc->sc_pf = pa->pf;
cfe = pa->pf->cfe_head.sqh_first; cfe = pa->pf->cfe_head.sqh_first;
/*
* XXX need to loop over all config entries?
*/
#if 0 #if 0
/* /*
* Some ne2000 driver's claim to have memory; others don't. * Some ne2000 driver's claim to have memory; others don't.
@ -457,6 +472,7 @@ ne_pcmcia_attach(parent, self, aux)
if (cfe->iospace[0].length != NE2000_NPORTS) { if (cfe->iospace[0].length != NE2000_NPORTS) {
printf(": unexpected I/O space configuration" printf(": unexpected I/O space configuration"
" (continued)\n%s", dsc->sc_dev.dv_xname); " (continued)\n%s", dsc->sc_dev.dv_xname);
/* XXX really safe for all other cards? */
} }
} else if (cfe->num_iospace == 2) { } else if (cfe->num_iospace == 2) {
/* /*
@ -526,6 +542,7 @@ ne_pcmcia_attach(parent, self, aux)
*/ */
i = 0; i = 0;
again: again:
enaddr = NULL; /* Ask ASIC by default */
for (; i < NE2000_NDEVS; i++) { for (; i < NE2000_NDEVS; i++) {
ne_dev = ne2000_match(pa->card, pa->pf->number, i); ne_dev = ne2000_match(pa->card, pa->pf->number, i);
if (ne_dev != NULL) { if (ne_dev != NULL) {
@ -554,6 +571,13 @@ again:
typestr = " (DL10019)"; typestr = " (DL10019)";
} }
if ((ne_dev->flags & NE2000DVF_AX88190) != 0) {
if (ne_pcmcia_ax88190_set_iobase(psc))
goto fail_5;
nsc->sc_type = NE2000_TYPE_AX88190;
typestr = " (AX88190)";
}
if (enaddr != NULL) { if (enaddr != NULL) {
/* /*
* Make sure this is what we expect. * Make sure this is what we expect.
@ -645,6 +669,7 @@ ne_pcmcia_enable(dsc)
struct dp8390_softc *dsc; struct dp8390_softc *dsc;
{ {
struct ne_pcmcia_softc *psc = (struct ne_pcmcia_softc *)dsc; struct ne_pcmcia_softc *psc = (struct ne_pcmcia_softc *)dsc;
struct ne2000_softc *nsc = &psc->sc_ne2000;
/* set up the interrupt */ /* set up the interrupt */
psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, dp8390_intr, psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, dp8390_intr,
@ -658,8 +683,14 @@ ne_pcmcia_enable(dsc)
if (pcmcia_function_enable(psc->sc_pf)) if (pcmcia_function_enable(psc->sc_pf))
goto fail_2; goto fail_2;
if (nsc->sc_type == NE2000_TYPE_AX88190)
if (ne_pcmcia_ax88190_set_iobase(psc))
goto fail_3;
return (0); return (0);
fail_3:
pcmcia_function_disable(psc->sc_pf);
fail_2: fail_2:
pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
fail_1: fail_1:
@ -736,3 +767,49 @@ ne_pcmcia_dl10019_get_enaddr(psc, myea)
#undef PAR0 #undef PAR0
return (myea); return (myea);
} }
int
ne_pcmcia_ax88190_set_iobase(psc)
struct ne_pcmcia_softc *psc;
{
struct ne2000_softc *nsc = &psc->sc_ne2000;
struct dp8390_softc *dsc = &nsc->sc_dp8390;
struct pcmcia_mem_handle pcmh;
bus_addr_t offset;
int rv = 1, mwindow;
if (pcmcia_mem_alloc(psc->sc_pf, NE2000_AX88190_LAN_IOSIZE, &pcmh)) {
printf("%s: can't alloc mem for LAN iobase\n",
dsc->sc_dev.dv_xname);
goto fail_1;
}
if (pcmcia_mem_map(psc->sc_pf, PCMCIA_MEM_ATTR,
NE2000_AX88190_LAN_IOBASE, NE2000_AX88190_LAN_IOSIZE,
&pcmh, &offset, &mwindow)) {
printf("%s: can't map mem for LAN iobase\n",
dsc->sc_dev.dv_xname);
goto fail_2;
}
#ifdef DIAGNOSTIC
printf("%s: LAN iobase 0x%x (0x%x) ->", dsc->sc_dev.dv_xname,
bus_space_read_1(pcmh.memt, pcmh.memh, offset + 0) |
bus_space_read_1(pcmh.memt, pcmh.memh, offset + 2) << 8,
(u_int)psc->sc_pcioh.addr);
#endif
bus_space_write_1(pcmh.memt, pcmh.memh, offset,
psc->sc_pcioh.addr & 0xff);
bus_space_write_1(pcmh.memt, pcmh.memh, offset + 2,
psc->sc_pcioh.addr >> 8);
#ifdef DIAGNOSTIC
printf(" 0x%x\n", bus_space_read_1(pcmh.memt, pcmh.memh, offset + 0) |
bus_space_read_1(pcmh.memt, pcmh.memh, offset + 2) << 8);
#endif
rv = 0;
pcmcia_mem_unmap(psc->sc_pf, mwindow);
fail_2:
pcmcia_mem_free(psc->sc_pf, &pcmh);
fail_1:
return (rv);
}