diff options
-rw-r--r-- | sys/dev/isa/files.isa | 6 | ||||
-rw-r--r-- | sys/dev/isa/if_ep.c | 202 | ||||
-rw-r--r-- | sys/dev/isa/if_epreg.h | 6 |
3 files changed, 174 insertions, 40 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index 809eaba5572..9f83fefe196 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,4 +1,4 @@ -# $NetBSD: files.isa,v 1.8 1995/07/19 19:58:42 brezak Exp $ +# $NetBSD: files.isa,v 1.9 1995/11/10 19:39:21 christos Exp $ # # Config.new file and device description for machine-independent ISA code. # Included by ports that need it. Requires that the SCSI files be @@ -127,8 +127,8 @@ file dev/isa/if_eg.c eg device el at isa: ether, ifnet file dev/isa/if_el.c el -# 3Com 3C5x9 (EtherLink III) family -device ep at isa: ether, ifnet, elink +# 3Com 3C5x9, 3c59x (EtherLink III) family +device ep at isa, pci: ether, ifnet, elink file dev/isa/if_ep.c ep # Fujitsu MB8696[05]-based boards diff --git a/sys/dev/isa/if_ep.c b/sys/dev/isa/if_ep.c index 8c663483e3c..f3edf1424b6 100644 --- a/sys/dev/isa/if_ep.c +++ b/sys/dev/isa/if_ep.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ep.c,v 1.82 1995/10/10 03:11:28 mycroft Exp $ */ +/* $NetBSD: if_ep.c,v 1.85 1995/12/05 03:30:15 christos Exp $ */ /* * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> @@ -65,6 +65,8 @@ #include <net/bpfdesc.h> #endif +#include "pci.h" + #include <machine/cpu.h> #include <machine/pio.h> @@ -72,7 +74,18 @@ #include <dev/isa/if_epreg.h> #include <dev/isa/elink.h> -#define ETHER_MIN_LEN 64 +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcidevs.h> + +/* PCI constants */ +#define PCI_VENDORID(x) ((x) & 0xFFFF) +#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF) +#define PCI_CONN 0x48 /* Connector type */ +#define PCI_CBMA 0x10 /* Configuration Base Memory Address */ + + +#define ETHER_MIN_LEN 64 #define ETHER_MAX_LEN 1518 #define ETHER_ADDR_LEN 6 /* @@ -92,7 +105,13 @@ struct ep_softc { int tx_start_thresh; /* Current TX_start_thresh. */ int tx_succ_ok; /* # packets sent in sequence */ /* w/o underrun */ - char bus32bit; /* 32bit access possible */ + u_char bustype; +#define EP_BUS_ISA 0x0 +#define EP_BUS_PCMCIA 0x1 +#define EP_BUS_EISA 0x2 +#define EP_BUS_PCI 0x3 + +#define EP_IS_BUS_32(a) ((a) & 0x2) }; static int epprobe __P((struct device *, void *, void *)); @@ -115,8 +134,9 @@ struct mbuf *epget __P((struct ep_softc *, int)); void epmbuffill __P((struct ep_softc *)); void epmbufempty __P((struct ep_softc *)); void epstop __P((struct ep_softc *)); -void epsetfilter __P((struct ep_softc *sc)); -void epsetlink __P((struct ep_softc *sc)); +void epsetfilter __P((struct ep_softc *)); +void epsetlink __P((struct ep_softc *)); +static void epconfig __P((struct ep_softc *, u_int)); static u_short epreadeeprom __P((int id_port, int offset)); static int epbusyeeprom __P((struct ep_softc *)); @@ -127,15 +147,15 @@ static struct epcard { int iobase; int irq; char available; - char bus32bit; + char bustype; } epcards[MAXEPCARDS]; static int nepcards; static void -epaddcard(iobase, irq, bus32bit) +epaddcard(iobase, irq, bustype) int iobase; int irq; - char bus32bit; + char bustype; { if (nepcards >= MAXEPCARDS) @@ -143,10 +163,10 @@ epaddcard(iobase, irq, bus32bit) epcards[nepcards].iobase = iobase; epcards[nepcards].irq = (irq == 2) ? 9 : irq; epcards[nepcards].available = 1; - epcards[nepcards].bus32bit = bus32bit; + epcards[nepcards].bustype = bustype; nepcards++; } - + /* * 3c579 cards on the EISA bus are probed by their slot number. 3c509 * cards on the ISA bus are probed in ethernet address order. The probe @@ -167,6 +187,24 @@ epprobe(parent, match, aux) u_short vendor, model; int k, k2; +#if NPCI > 0 + extern struct cfdriver pcicd; + + if (parent->dv_cfdata->cf_driver == &pcicd) { + struct pci_attach_args *pa = (struct pci_attach_args *) aux; + + if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_3COM || + PCI_CHIPID(pa->pa_id) != PCI_PRODUCT_3COM_3C590) + return 0; + + if (nepcards >= MAXEPCARDS) + return 0; + + epcards[nepcards++].available = 0; + return 1; + } +#endif + if (!probed) { probed = 1; @@ -197,7 +235,7 @@ epprobe(parent, match, aux) k2 = inw(iobase + EP_W0_RESOURCE_CFG); k2 >>= 12; - epaddcard(iobase, k2, 1); + epaddcard(iobase, k2, EP_BUS_EISA); } for (slot = 0; slot < 10; slot++) { @@ -227,7 +265,7 @@ epprobe(parent, match, aux) k2 = epreadeeprom(ELINK_ID_PORT, EEPROM_RESOURCE_CFG); k2 >>= 12; - epaddcard(k, k2, 0); + epaddcard(k, k2, EP_BUS_ISA); /* so card will not respond to contention again */ outb(ELINK_ID_PORT, TAG_ADAPTER + 1); @@ -258,7 +296,7 @@ epprobe(parent, match, aux) good: epcards[i].available = 0; - sc->bus32bit = epcards[i].bus32bit; + sc->bustype = epcards[i].bustype; ia->ia_iobase = epcards[i].iobase; ia->ia_irq = epcards[i].irq; ia->ia_iosize = 0x10; @@ -267,34 +305,27 @@ good: } static void -epattach(parent, self, aux) - struct device *parent, *self; - void *aux; +epconfig(sc, conn) + struct ep_softc *sc; + u_int conn; { - struct ep_softc *sc = (void *)self; - struct isa_attach_args *ia = aux; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; u_short i; - printf(": "); - - sc->ep_iobase = ia->ia_iobase; - - GO_WINDOW(0); + struct ifnet *ifp = &sc->sc_arpcom.ac_if; sc->ep_connectors = 0; - i = inw(ia->ia_iobase + EP_W0_CONFIG_CTRL); - if (i & IS_AUI) { + printf(": "); + if (conn & IS_AUI) { printf("aui"); sc->ep_connectors |= AUI; } - if (i & IS_BNC) { + if (conn & IS_BNC) { if (sc->ep_connectors) printf("/"); printf("bnc"); sc->ep_connectors |= BNC; } - if (i & IS_UTP) { + if (conn & IS_UTP) { if (sc->ep_connectors) printf("/"); printf("utp"); @@ -337,9 +368,81 @@ epattach(parent, self, aux) #endif sc->tx_start_thresh = 20; /* probably a good starting point. */ +} - sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, ISA_IPL_NET, - epintr, sc); +static void +epattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ep_softc *sc = (void *)self; + u_short conn = 0; +#if NPCI > 0 + extern struct cfdriver pcicd; + + if (parent->dv_cfdata->cf_driver == &pcicd) { + struct pci_attach_args *pa = aux; + int iobase; + u_short i; + + if (pci_map_io(pa->pa_tag, PCI_CBMA, &iobase)) { + printf("%s: couldn't map io\n", sc->sc_dev.dv_xname); + return; + } + sc->bustype = EP_BUS_PCI; + sc->ep_iobase = iobase; /* & 0xfffffff0 */ + i = pci_conf_read(pa->pa_tag, PCI_CONN); + + /* + * Bits 13,12,9 of the isa adapter are the same as bits + * 5,4,3 of the pci adapter + */ + if (i & IS_PCI_AUI) + conn |= IS_AUI; + if (i & IS_PCI_BNC) + conn |= IS_BNC; + if (i & IS_PCI_UTP) + conn |= IS_UTP; + + GO_WINDOW(0); + } + else +#endif + { + struct isa_attach_args *ia = aux; + + sc->ep_iobase = ia->ia_iobase; + GO_WINDOW(0); + conn = inw(ia->ia_iobase + EP_W0_CONFIG_CTRL); + } + + epconfig(sc, conn); + + +#if NPCI > 0 + if (parent->dv_cfdata->cf_driver == &pcicd) { + struct pci_attach_args *pa = aux; + + pci_conf_write(pa->pa_tag, PCI_COMMAND_STATUS_REG, + pci_conf_read(pa->pa_tag, + PCI_COMMAND_STATUS_REG) | + PCI_COMMAND_MASTER_ENABLE); + + sc->sc_ih = pci_map_int(pa->pa_tag, PCI_IPL_NET, epintr, sc); + if (sc->sc_ih == NULL) { + printf("%s: couldn't map interrupt\n", + sc->sc_dev.dv_xname); + return; + } + epstop(sc); + } + else +#endif + { + struct isa_attach_args *ia = aux; + sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, + ISA_IPL_NET, epintr, sc); + } } /* @@ -356,9 +459,20 @@ epinit(sc) while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) ; - GO_WINDOW(0); - outw(BASE + EP_W0_CONFIG_CTRL, 0); /* Disable the card */ - outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); /* Enable the card */ + if (sc->bustype != EP_BUS_PCI) { + GO_WINDOW(0); + outw(BASE + EP_W0_CONFIG_CTRL, 0); + outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); + } + + if (sc->bustype == EP_BUS_PCMCIA) { +#ifdef EP_COAX_DEFAULT + outw(BASE + EP_W0_ADDRESS_CFG,3<<14); +#else + outw(BASE + EP_W0_ADDRESS_CFG,0<<14); +#endif + outw(BASE + EP_W0_RESOURCE_CFG, 0x3f00); + } GO_WINDOW(2); for (i = 0; i < 6; i++) /* Reload the ether_addr. */ @@ -430,14 +544,25 @@ epsetlink(sc) GO_WINDOW(4); outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP); if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) { + if (sc->bustype == EP_BUS_PCMCIA) { + GO_WINDOW(0); + outw(BASE + EP_W0_ADDRESS_CFG,3<<14); + GO_WINDOW(1); + } outw(BASE + EP_COMMAND, START_TRANSCEIVER); delay(1000); } if (ifp->if_flags & IFF_LINK0) { outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); delay(1000); - if ((ifp->if_flags & IFF_LINK1) && (sc->ep_connectors & UTP)) + if ((ifp->if_flags & IFF_LINK1) && (sc->ep_connectors & UTP)) { + if (sc->bustype == EP_BUS_PCMCIA) { + GO_WINDOW(0); + outw(BASE + EP_W0_ADDRESS_CFG,0<<14); + GO_WINDOW(4); + } outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP); + } } GO_WINDOW(1); } @@ -513,7 +638,7 @@ startagain: outw(BASE + EP_W1_TX_PIO_WR_1, len); outw(BASE + EP_W1_TX_PIO_WR_1, 0xffff); /* Second dword meaningless */ - if (sc->bus32bit) { + if (EP_IS_BUS_32(sc->bustype)) { for (m = m0; m; ) { if (m->m_len > 3) outsl(BASE + EP_W1_TX_PIO_WR_1, @@ -896,7 +1021,7 @@ epget(sc, totlen) len = MCLBYTES; } len = min(totlen, len); - if (sc->bus32bit) { + if (EP_IS_BUS_32(sc->bustype)) { if (len > 3) { len &= ~3; insl(BASE + EP_W1_RX_PIO_RD_1, @@ -1107,6 +1232,11 @@ epbusyeeprom(sc) { int i = 100, j; + if (sc->bustype == EP_BUS_PCMCIA) { + delay(1000); + return 0; + } + while (i--) { j = inw(BASE + EP_W0_EEPROM_COMMAND); if (j & EEPROM_BUSY) diff --git a/sys/dev/isa/if_epreg.h b/sys/dev/isa/if_epreg.h index ecd47b088d4..e215d7cee43 100644 --- a/sys/dev/isa/if_epreg.h +++ b/sys/dev/isa/if_epreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_epreg.h,v 1.13 1995/04/27 14:50:58 hpeyerl Exp $ */ +/* $NetBSD: if_epreg.h,v 1.14 1995/11/10 19:39:25 christos Exp $ */ /* * Copyright (c) 1995 Herb Peyerl <hpeyerl@novatel.ca> @@ -333,6 +333,10 @@ #define DISABLE_UTP 0x0 #define RX_BYTES_MASK (u_short) (0x07ff) +#define IS_PCI_AUI (1<<5) +#define IS_PCI_BNC (1<<4) +#define IS_PCI_UTP (1<<3) + /* * EISA registers (offset from slot base) */ |