From 6b8fd2d936cbbd530c9de9d23036cbfb6506aff5 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 7 Dec 2003 19:23:40 +0000 Subject: [PATCH] PCI compat cleanup, part 1. This brings in the LNC and VX drivers from FreeBSD-5. They are not the newest versions, just new enough to use newbus, not the PCI compat code. Submitted-by: Joerg Sonnenberger --- sys/bus/isa/i386/isa_compat.h | 7 +- sys/conf/files | 6 +- sys/conf/files.i386 | 3 +- sys/conf/files.pc98 | 3 +- sys/dev/netif/Makefile | 6 +- sys/dev/netif/lnc/Makefile | 8 + sys/dev/netif/lnc/if_lnc.c | 705 +++++++-------------------------- sys/dev/netif/lnc/if_lnc_isa.c | 287 ++++++++++++++ sys/dev/netif/lnc/if_lnc_pci.c | 224 +++++++++++ sys/dev/netif/lnc/if_lncreg.h | 210 ++++++++++ sys/dev/netif/lnc/if_lncvar.h | 266 +++++++++++++ sys/dev/netif/vx/Makefile | 8 + sys/dev/netif/vx/if_vx.c | 185 ++++----- sys/dev/netif/vx/if_vx_eisa.c | 16 +- sys/dev/netif/vx/if_vx_pci.c | 157 +++++--- sys/dev/netif/vx/if_vxreg.h | 28 +- 16 files changed, 1368 insertions(+), 751 deletions(-) create mode 100644 sys/dev/netif/lnc/Makefile create mode 100644 sys/dev/netif/lnc/if_lnc_isa.c create mode 100644 sys/dev/netif/lnc/if_lnc_pci.c create mode 100644 sys/dev/netif/lnc/if_lncreg.h create mode 100644 sys/dev/netif/lnc/if_lncvar.h create mode 100644 sys/dev/netif/vx/Makefile diff --git a/sys/bus/isa/i386/isa_compat.h b/sys/bus/isa/i386/isa_compat.h index b1726dd758..6317503f12 100644 --- a/sys/bus/isa/i386/isa_compat.h +++ b/sys/bus/isa/i386/isa_compat.h @@ -24,14 +24,13 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/isa/isa_compat.h,v 1.27.2.11 2002/10/05 18:31:48 scottl Exp $ - * $DragonFly: src/sys/bus/isa/i386/isa_compat.h,v 1.4 2003/11/22 09:50:35 asmodai Exp $ + * $DragonFly: src/sys/bus/isa/i386/isa_compat.h,v 1.5 2003/12/07 19:23:35 dillon Exp $ */ #include "use_vt.h" #include "use_cx.h" #include "use_el.h" #include "use_le.h" -#include "use_lnc.h" #include "use_rdp.h" #include "use_wl.h" #include "use_pcm.h" @@ -75,7 +74,6 @@ extern struct isa_driver vtdriver; extern struct isa_driver cxdriver; extern struct isa_driver eldriver; extern struct isa_driver ledriver; -extern struct isa_driver lncdriver; extern struct isa_driver rdpdriver; extern struct isa_driver wldriver; extern struct isa_driver pasdriver; @@ -183,9 +181,6 @@ static struct old_isa_driver old_drivers[] = { #if NLE > 0 { INTR_TYPE_NET, &ledriver }, #endif -#if NLNC > 0 - { INTR_TYPE_NET, &lncdriver }, -#endif #if NCX > 0 { INTR_TYPE_NET, &cxdriver }, #endif diff --git a/sys/conf/files b/sys/conf/files index d9105e2786..20a8c3991f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.32 2003/12/02 08:00:22 asmodai Exp $ +# $DragonFly: src/sys/conf/files,v 1.33 2003/12/07 19:23:36 dillon Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -1077,7 +1077,9 @@ dev/serial/cy/cy_pci.c optional cy pci dev/netif/dc/if_dc.c optional dc dev/netif/de/if_de.c optional de dev/netif/en_pci/if_en_pci.c optional en pci -dev/netif/lnc_p/if_lnc_p.c optional lnc pci +dev/netif/lnc/if_lnc.c optional lnc +dev/netif/lnc/if_lnc_isa.c optional lnc isa +dev/netif/lnc/if_lnc_pci.c optional lnc pci dev/netif/pcn/if_pcn.c optional pcn dev/netif/mn/if_mn.c optional mn dev/netif/rl/if_rl.c optional rl diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index a0df22c419..97e9397fb0 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -2,7 +2,7 @@ # files marked standard are always included. # # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $ -# $DragonFly: src/sys/conf/Attic/files.i386,v 1.8 2003/11/22 09:50:35 asmodai Exp $ +# $DragonFly: src/sys/conf/Attic/files.i386,v 1.9 2003/12/07 19:23:36 dillon Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -256,7 +256,6 @@ dev/video/gsc/gsc.c optional gsc dev/netif/cx/if_cx.c optional cx dev/netif/el/if_el.c optional el dev/netif/le/if_le.c optional le -dev/netif/lnc/if_lnc.c optional lnc dev/netif/rdp/if_rdp.c optional rdp dev/netif/wl/if_wl.c optional wl i386/isa/intr_machdep.c standard diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index 1b541494b7..0ac6db962e 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -4,7 +4,7 @@ # modified for PC-9801 # # $FreeBSD: src/sys/conf/files.pc98,v 1.140.2.44 2003/02/10 13:11:50 nyan Exp $ -# $DragonFly: src/sys/conf/Attic/files.pc98,v 1.3 2003/07/06 21:23:45 dillon Exp $ +# $DragonFly: src/sys/conf/Attic/files.pc98,v 1.4 2003/12/07 19:23:36 dillon Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -259,7 +259,6 @@ i386/isa/gsc.c optional gsc i386/isa/if_cx.c optional cx i386/isa/if_el.c optional el i386/isa/if_le.c optional le -i386/isa/if_lnc.c optional lnc i386/isa/if_rdp.c optional rdp i386/isa/if_wl.c optional wl i386/isa/intr_machdep.c standard diff --git a/sys/dev/netif/Makefile b/sys/dev/netif/Makefile index afdbea1228..4f517f059e 100644 --- a/sys/dev/netif/Makefile +++ b/sys/dev/netif/Makefile @@ -1,8 +1,8 @@ -# $DragonFly: src/sys/dev/netif/Makefile,v 1.1 2003/08/15 08:32:30 dillon Exp $ +# $DragonFly: src/sys/dev/netif/Makefile,v 1.2 2003/12/07 19:23:37 dillon Exp $ # -SUBDIR= an ar aue bge cue dc em fwe fxp gx kue lge mii_layer my \ +SUBDIR= an ar aue bge cue dc em fwe fxp gx kue lge lnc mii_layer my \ nge pcn ray rl sbni sbsh sf sis sk snc sr ste ti tl tx \ - txp vr wb wi wx xe xl + txp vr vx wb wi wx xe xl .include diff --git a/sys/dev/netif/lnc/Makefile b/sys/dev/netif/lnc/Makefile new file mode 100644 index 0000000000..a2ce94ebbd --- /dev/null +++ b/sys/dev/netif/lnc/Makefile @@ -0,0 +1,8 @@ +# $DragonFly: src/sys/dev/netif/lnc/Makefile,v 1.1 2003/12/07 19:23:39 dillon Exp $ + +.PATH: ${.CURDIR}/../../dev/lnc +KMOD = if_lnc +SRCS = if_lnc.c if_lnc_isa.c if_lnc_pci.c +SRCS += device_if.h bus_if.h pci_if.h isa_if.h opt_inet.h + +.include diff --git a/sys/dev/netif/lnc/if_lnc.c b/sys/dev/netif/lnc/if_lnc.c index bbbfacd16a..22900a392e 100644 --- a/sys/dev/netif/lnc/if_lnc.c +++ b/sys/dev/netif/lnc/if_lnc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1994-1998 + * Copyright (c) 1994-2000 * Paul Richards. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,10 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Paul Richards. - * 4. The name Paul Richards may not be used to endorse or promote products + * 3. The name Paul Richards may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND @@ -30,8 +27,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/i386/isa/if_lnc.c,v 1.68.2.5 2002/02/13 00:43:10 dillon Exp $ - * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lnc.c,v 1.5 2003/11/20 22:07:29 dillon Exp $ + * $FreeBSD: src/sys/dev/lnc/if_lnc.c,v 1.89 2001/07/04 13:00:19 nyan Exp $ + * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lnc.c,v 1.6 2003/12/07 19:23:39 dillon Exp $ */ /* @@ -40,9 +37,6 @@ * * TODO ---- * - * This driver will need bounce buffer support when dma'ing to mbufs above the - * 16Mb mark. - * * Check all the XXX comments -- some of them are just things I've left * unfinished rather than "difficult" problems that were hacked around. * @@ -61,9 +55,6 @@ * */ -#include "use_pci.h" -#include "use_lnc.h" - #include "opt_inet.h" /* Some defines that should really be in generic locations */ @@ -72,14 +63,18 @@ #include #include -#include -#include +#include +#include #include #include +#include #include +#include #include -#include -#include + +#include +#include +#include #include #include @@ -91,41 +86,14 @@ #include -#ifdef PC98 -#include -#endif #include -#include -#include "if_lnc.h" - -struct lnc_softc { - struct arpcom arpcom; /* see ../../net/if_arp.h */ - struct nic_info nic; /* NIC specific info */ - int nrdre; - struct host_ring_entry *recv_ring; /* start of alloc'd mem */ - int recv_next; - int ntdre; - struct host_ring_entry *trans_ring; - int trans_next; - struct init_block *init_block; /* Initialisation block */ - int pending_transmits; /* No. of transmit descriptors in use */ - int next_to_send; - struct mbuf *mbufs; - int mbuf_count; - int flags; - int rap; - int rdp; - int bdp; -#ifdef DEBUG - int lnc_debug; -#endif - LNCSTATS_STRUCT -}; +#include +#include DECLARE_DUMMY_MODULE(if_lnc); -static struct lnc_softc lnc_softc[NLNC]; +devclass_t lnc_devclass; static char const * const nic_ident[] = { "Unknown", @@ -150,77 +118,77 @@ static char const * const ic_ident[] = { "PCnet-Home", }; -static void lnc_setladrf (struct lnc_softc *sc); -static void lnc_stop (struct lnc_softc *sc); -static void lnc_reset (struct lnc_softc *sc); -static void lnc_free_mbufs (struct lnc_softc *sc); -static __inline int alloc_mbuf_cluster (struct lnc_softc *sc, +static void lnc_setladrf(struct lnc_softc *sc); +static void lnc_reset(struct lnc_softc *sc); +static void lnc_free_mbufs(struct lnc_softc *sc); +static __inline int alloc_mbuf_cluster(struct lnc_softc *sc, struct host_ring_entry *desc); -static __inline struct mbuf *chain_mbufs (struct lnc_softc *sc, +static __inline struct mbuf *chain_mbufs(struct lnc_softc *sc, int start_of_packet, int pkt_len); -static __inline struct mbuf *mbuf_packet (struct lnc_softc *sc, +static __inline struct mbuf *mbuf_packet(struct lnc_softc *sc, int start_of_packet, int pkt_len); -static __inline void lnc_rint (struct lnc_softc *sc); -static __inline void lnc_tint (struct lnc_softc *sc); -static int lnc_probe (struct isa_device *isa_dev); -#ifdef PC98 -static int cnet98s_probe (struct lnc_softc *sc, unsigned iobase); -#endif -static int ne2100_probe (struct lnc_softc *sc, unsigned iobase); -static int bicc_probe (struct lnc_softc *sc, unsigned iobase); -static int dec_macaddr_extract (u_char ring[], struct lnc_softc *sc); -static int depca_probe (struct lnc_softc *sc, unsigned iobase); -static int lance_probe (struct lnc_softc *sc); -static int pcnet_probe (struct lnc_softc *sc); -static int lnc_attach_sc (struct lnc_softc *sc, int unit); -static int lnc_attach (struct isa_device *isa_dev); -static void lnc_init (void *); -static ointhand2_t lncintr; -static __inline int mbuf_to_buffer (struct mbuf *m, char *buffer); -static __inline struct mbuf *chain_to_cluster (struct mbuf *m); -static void lnc_start (struct ifnet *ifp); -static int lnc_ioctl (struct ifnet *ifp, u_long command, caddr_t data); -static void lnc_watchdog (struct ifnet *ifp); +static __inline void lnc_rint(struct lnc_softc *sc); +static __inline void lnc_tint(struct lnc_softc *sc); + +static void lnc_init(void *); +static __inline int mbuf_to_buffer(struct mbuf *m, char *buffer); +static __inline struct mbuf *chain_to_cluster(struct mbuf *m); +static void lnc_start(struct ifnet *ifp); +static int lnc_ioctl(struct ifnet *ifp, u_long command, caddr_t data); +static void lnc_watchdog(struct ifnet *ifp); #ifdef DEBUG -void lnc_dump_state (struct lnc_softc *sc); -void mbuf_dump_chain (struct mbuf *m); -#endif - -#if NPCI > 0 -void *lnc_attach_ne2100_pci (int unit, unsigned iobase); +void lnc_dump_state(struct lnc_softc *sc); +void mbuf_dump_chain(struct mbuf *m); #endif -void lncintr_sc (struct lnc_softc *sc); - -struct isa_driver lncdriver = {lnc_probe, lnc_attach, "lnc"}; -static __inline void -write_csr(struct lnc_softc *sc, u_short port, u_short val) +u_short +read_csr(struct lnc_softc *sc, u_short port) { - outw(sc->rap, port); - outw(sc->rdp, val); + lnc_outw(sc->rap, port); + return (lnc_inw(sc->rdp)); } -static __inline u_short -read_csr(struct lnc_softc *sc, u_short port) +void +write_csr(struct lnc_softc *sc, u_short port, u_short val) { - outw(sc->rap, port); - return (inw(sc->rdp)); + lnc_outw(sc->rap, port); + lnc_outw(sc->rdp, val); } static __inline void write_bcr(struct lnc_softc *sc, u_short port, u_short val) { - outw(sc->rap, port); - outw(sc->bdp, val); + lnc_outw(sc->rap, port); + lnc_outw(sc->bdp, val); } static __inline u_short read_bcr(struct lnc_softc *sc, u_short port) { - outw(sc->rap, port); - return (inw(sc->bdp)); + lnc_outw(sc->rap, port); + return (lnc_inw(sc->bdp)); +} + +int +lance_probe(struct lnc_softc *sc) +{ + write_csr(sc, CSR0, STOP); + + if ((lnc_inw(sc->rdp) & STOP) && ! (read_csr(sc, CSR3))) { + /* + * Check to see if it's a C-LANCE. For the LANCE the INEA bit + * cannot be set while the STOP bit is. This restriction is + * removed for the C-LANCE. + */ + write_csr(sc, CSR0, INEA); + if (read_csr(sc, CSR0) & INEA) + return (C_LANCE); + else + return (LANCE); + } else + return (UNKNOWN); } static __inline u_long @@ -241,6 +209,31 @@ ether_crc(const u_char *ether_addr) #undef POLYNOMIAL } +void +lnc_release_resources(device_t dev) +{ + lnc_softc_t *sc = device_get_softc(dev); + + if (sc->irqres) { + bus_teardown_intr(dev, sc->irqres, sc->intrhand); + bus_release_resource(dev, SYS_RES_IRQ, sc->irqrid, sc->irqres); + } + + if (sc->portres) + bus_release_resource(dev, SYS_RES_IOPORT, + sc->portrid, sc->portres); + if (sc->drqres) + bus_release_resource(dev, SYS_RES_DRQ, sc->drqrid, sc->drqres); + + if (sc->dmat) { + if (sc->dmamap) { + bus_dmamap_unload(sc->dmat, sc->dmamap); + bus_dmamem_free(sc->dmat, sc->recv_ring, sc->dmamap); + } + bus_dma_tag_destroy(sc->dmat); + } +} + /* * Set up the logical address filter for multicast packets */ @@ -266,8 +259,7 @@ lnc_setladrf(struct lnc_softc *sc) */ bzero(sc->init_block->ladrf, MULTICAST_FILTER_LEN); - for (ifma = ifp->if_multiaddrs.lh_first; ifma; - ifma = ifma->ifma_link.le_next) { + LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -277,7 +269,7 @@ lnc_setladrf(struct lnc_softc *sc) } } -static void +void lnc_stop(struct lnc_softc *sc) { write_csr(sc, CSR0, STOP); @@ -361,6 +353,7 @@ chain_mbufs(struct lnc_softc *sc, int start_of_packet, int pkt_len) head = desc->buff.mbuf; head->m_flags |= M_PKTHDR; + bzero(&head->m_pkthdr, sizeof(head->m_pkthdr)); m = head; do { @@ -606,19 +599,18 @@ lnc_rint(struct lnc_softc *sc) * vmware ethernet hardware emulation loops * packets back to itself, violates IFF_SIMPLEX. * drop it if it is from myself. - */ + */ if (bcmp(eh->ether_shost, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) == 0) { - m_freem(head); + m_freem(head); } else { - /* Skip over the ether header */ - head->m_data += sizeof *eh; - head->m_len -= sizeof *eh; - head->m_pkthdr.len -= sizeof *eh; + /* Skip over the ether header */ + head->m_data += sizeof *eh; + head->m_len -= sizeof *eh; + head->m_pkthdr.len -= sizeof *eh; - ether_input(&sc->arpcom.ac_if, eh, head); + ether_input(&sc->arpcom.ac_if, eh, head); } - } else { int unit = sc->arpcom.ac_if.if_unit; log(LOG_ERR,"lnc%d: Packet dropped, no mbufs\n",unit); @@ -635,7 +627,7 @@ lnc_rint(struct lnc_softc *sc) * here have been dealt with. */ - outw(sc->rdp, RINT | INEA); + lnc_outw(sc->rdp, RINT | INEA); } static __inline void @@ -844,7 +836,6 @@ lnc_tint(struct lnc_softc *sc) sc->mbuf_count++; start->buff.mbuf = 0; } else { - /* XXX shouldn't this be m_freem ?? */ m_free(start->buff.mbuf); start->buff.mbuf = NULL; } @@ -870,360 +861,25 @@ lnc_tint(struct lnc_softc *sc) * the completed transmissions. */ - outw(sc->rdp, TINT | INEA); - - /* XXX only while doing if_is comparisons */ - if (!(sc->arpcom.ac_if.if_flags & IFF_OACTIVE)) - lnc_start(&sc->arpcom.ac_if); - + lnc_outw(sc->rdp, TINT | INEA); } -static int -lnc_probe(struct isa_device * isa_dev) -{ - int nports; - int unit = isa_dev->id_unit; - struct lnc_softc *sc = &lnc_softc[unit]; - unsigned iobase = isa_dev->id_iobase; - -#ifdef DIAGNOSTIC - int vsw; - vsw = inw(isa_dev->id_iobase + PCNET_VSW); - printf("Vendor Specific Word = %x\n", vsw); -#endif - - nports = bicc_probe(sc, iobase); - if (nports == 0) - nports = ne2100_probe(sc, iobase); - if (nports == 0) - nports = depca_probe(sc, iobase); -#ifdef PC98 - if (nports == 0) - nports = cnet98s_probe(sc, iobase); -#endif - return (nports); -} - -#ifdef PC98 -/* ISA Bus Configuration Registers */ -/* XXX - Should be in ic/Am7990.h */ -#define MSRDA 0x0000 /* ISACSR0: Master Mode Read Activity */ -#define MSWRA 0x0001 /* ISACSR1: Master Mode Write Activity */ -#define MC 0x0002 /* ISACSR2: Miscellaneous Configuration */ - -#define LED1 0x0005 /* ISACSR5: LED1 Status */ -#define LED2 0x0006 /* ISACSR6: LED2 Status */ -#define LED3 0x0007 /* ISACSR7: LED3 Status */ - -#define LED_PSE 0x0080 /* Pulse Stretcher */ -#define LED_XMTE 0x0010 /* Transmit Status */ -#define LED_RVPOLE 0x0008 /* Receive Polarity */ -#define LED_RCVE 0x0004 /* Receive Status */ -#define LED_JABE 0x0002 /* Jabber */ -#define LED_COLE 0x0001 /* Collision */ - -static int -cnet98s_probe(struct lnc_softc *sc, unsigned iobase) -{ - int i; - ushort tmp; - - sc->rap = iobase + CNET98S_RAP; - sc->rdp = iobase + CNET98S_RDP; - - /* Reset */ - tmp = inw(iobase + CNET98S_RESET); - outw(iobase + CNET98S_RESET, tmp); - DELAY(500); - - sc->nic.ic = pcnet_probe(sc); - if ((sc->nic.ic == UNKNOWN) || (sc->nic.ic > PCnet_32)) { - return (0); - } - - sc->nic.ident = CNET98S; - sc->nic.mem_mode = DMA_FIXED; - - /* XXX - For now just use the defines */ - sc->nrdre = NRDRE; - sc->ntdre = NTDRE; - - /* Extract MAC address from PROM */ - for (i = 0; i < ETHER_ADDR_LEN; i++) { - sc->arpcom.ac_enaddr[i] = inb(iobase + (i * 2)); - } - - /* - * ISA Configuration - * - * XXX - Following parameters are Contec C-NET(98)S only. - * So, check the Ethernet address here. - * - * Contec uses 00 80 4c ?? ?? ?? - */ - if (sc->arpcom.ac_enaddr[0] == (u_char)0x00 - && sc->arpcom.ac_enaddr[1] == (u_char)0x80 - && sc->arpcom.ac_enaddr[2] == (u_char)0x4c) { - outw(sc->rap, MSRDA); - outw(iobase + CNET98S_IDP, 0x0006); - outw(sc->rap, MSWRA); - outw(iobase + CNET98S_IDP, 0x0006); -#ifdef DIAGNOSTIC - outw(sc->rap, MC); - printf("ISACSR2 = %x\n", inw(iobase + CNET98S_IDP)); -#endif - outw(sc->rap, LED1); - outw(iobase + CNET98S_IDP, LED_PSE | LED_XMTE); - outw(sc->rap, LED2); - outw(iobase + CNET98S_IDP, LED_PSE | LED_RCVE); - outw(sc->rap, LED3); - outw(iobase + CNET98S_IDP, LED_PSE | LED_COLE); - } - - return (CNET98S_IOSIZE); -} -#endif - -static int -ne2100_probe(struct lnc_softc *sc, unsigned iobase) +int +lnc_attach_common(device_t dev) { + int unit = device_get_unit(dev); + lnc_softc_t *sc = device_get_softc(dev); int i; + int skip; - sc->rap = iobase + PCNET_RAP; - sc->rdp = iobase + PCNET_RDP; - - sc->nic.ic = pcnet_probe(sc); - if ((sc->nic.ic > 0) && (sc->nic.ic < PCnet_PCI)) { - sc->nic.ident = NE2100; - sc->nic.mem_mode = DMA_FIXED; - - /* XXX - For now just use the defines */ - sc->nrdre = NRDRE; - sc->ntdre = NTDRE; - - /* Extract MAC address from PROM */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - sc->arpcom.ac_enaddr[i] = inb(iobase + i); - return (NE2100_IOSIZE); - } else { - return (0); - } -} - -static int -bicc_probe(struct lnc_softc *sc, unsigned iobase) -{ - int i; - - /* - * There isn't any way to determine if a NIC is a BICC. Basically, if - * the lance probe succeeds using the i/o addresses of the BICC then - * we assume it's a BICC. - * - */ - - sc->rap = iobase + BICC_RAP; - sc->rdp = iobase + BICC_RDP; - - /* I think all these cards us the Am7990 */ - - if ((sc->nic.ic = lance_probe(sc))) { - sc->nic.ident = BICC; - sc->nic.mem_mode = DMA_FIXED; - - /* XXX - For now just use the defines */ - sc->nrdre = NRDRE; - sc->ntdre = NTDRE; - - /* Extract MAC address from PROM */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - sc->arpcom.ac_enaddr[i] = inb(iobase + (i * 2)); - - return (BICC_IOSIZE); - } else { - return (0); - } -} - -/* - * I don't have data sheets for the dec cards but it looks like the mac - * address is contained in a 32 byte ring. Each time you read from the port - * you get the next byte in the ring. The mac address is stored after a - * signature so keep searching for the signature first. - */ -static int -dec_macaddr_extract(u_char ring[], struct lnc_softc * sc) -{ - const unsigned char signature[] = {0xff, 0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa}; - - int i, j, rindex; - - for (i = 0; i < sizeof ring; i++) { - for (j = 0, rindex = i; j < sizeof signature; j++) { - if (ring[rindex] != signature[j]) - break; - if (++rindex > sizeof ring) - rindex = 0; - } - if (j == sizeof signature) { - for (j = 0, rindex = i; j < ETHER_ADDR_LEN; j++) { - sc->arpcom.ac_enaddr[j] = ring[rindex]; - if (++rindex > sizeof ring) - rindex = 0; - } - return (1); - } - } - return (0); -} - -static int -depca_probe(struct lnc_softc *sc, unsigned iobase) -{ - int i; - unsigned char maddr_ring[DEPCA_ADDR_ROM_SIZE]; - - sc->rap = iobase + DEPCA_RAP; - sc->rdp = iobase + DEPCA_RDP; - - if ((sc->nic.ic = lance_probe(sc))) { - sc->nic.ident = DEPCA; - sc->nic.mem_mode = SHMEM; - - /* Extract MAC address from PROM */ - for (i = 0; i < DEPCA_ADDR_ROM_SIZE; i++) - maddr_ring[i] = inb(iobase + DEPCA_ADP); - if (dec_macaddr_extract(maddr_ring, sc)) { - return (DEPCA_IOSIZE); - } - } - return (0); -} - -static int -lance_probe(struct lnc_softc *sc) -{ - write_csr(sc, CSR0, STOP); - - if ((inw(sc->rdp) & STOP) && !(read_csr(sc, CSR3))) { - /* - * Check to see if it's a C-LANCE. For the LANCE the INEA bit - * cannot be set while the STOP bit is. This restriction is - * removed for the C-LANCE. - */ - write_csr(sc, CSR0, INEA); - if (read_csr(sc, CSR0) & INEA) - return (C_LANCE); - else - return (LANCE); - } else - return (UNKNOWN); -} - -static int -pcnet_probe(struct lnc_softc *sc) -{ - u_long chip_id; - int type; - - /* - * The PCnet family don't reset the RAP register on reset so we'll - * have to write during the probe :-) It does have an ID register - * though so the probe is just a matter of reading it. - */ - - if ((type = lance_probe(sc))) { - chip_id = read_csr(sc, CSR89); - chip_id <<= 16; - chip_id |= read_csr(sc, CSR88); - if (chip_id & AMD_MASK) { - chip_id >>= 12; - switch (chip_id & PART_MASK) { - case Am79C960: - return (PCnet_ISA); - case Am79C961: - return (PCnet_ISAplus); - case Am79C961A: - return (PCnet_ISA_II); - case Am79C965: - return (PCnet_32); - case Am79C970: - return (PCnet_PCI); - case Am79C970A: - return (PCnet_PCI_II); - case Am79C971: - return (PCnet_FAST); - case Am79C972: - case Am79C973: - return (PCnet_FASTplus); - case Am79C978: - return (PCnet_Home); - default: - break; - } - } - } - return (type); -} - -static int -lnc_attach_sc(struct lnc_softc *sc, int unit) -{ - int lnc_mem_size; - - /* - * Allocate memory for use by the controller. - * - * XXX -- the Am7990 and Am79C960 only have 24 address lines and so can - * only access the lower 16Mb of physical memory. For the moment we - * assume that malloc will allocate memory within the lower 16Mb - * range. This is not a very valid assumption but there's nothing - * that can be done about it yet. For shared memory NICs this isn't - * relevant. - * - */ - - lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) * - sizeof(struct host_ring_entry)); - - if (sc->nic.mem_mode != SHMEM) - lnc_mem_size += sizeof(struct init_block) + (sizeof(struct mds) * - (NDESC(sc->nrdre) + NDESC(sc->ntdre))) + - MEM_SLEW; - - /* If using DMA to fixed host buffers then allocate memory for them */ - - if (sc->nic.mem_mode == DMA_FIXED) - lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) + (NDESC(sc->ntdre) * TRANSBUFSIZE); - - if (sc->nic.mem_mode != SHMEM) { - if (sc->nic.ic < PCnet_32) { - /* ISA based cards */ - sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT, - 0ul, 0xfffffful, 4ul, 0x1000000); - } else { - /* Non-ISA based cards, 32 bit capable */ -#ifdef notyet - /* - * For the 32 bit driver we're not fussed where we DMA to - * though it'll still need to be contiguous - */ - sc->recv_ring = malloc(lnc_mem_size, M_DEVBUF, M_NOWAIT); -#else - /* - * For now it still needs to be below 16MB because the - * descriptor's can only hold 16 bit addresses. - */ - sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT, - 0ul, 0xfffffful, 4ul, 0x1000000); -#endif - } - } - - if (!sc->recv_ring) { - log(LOG_ERR, "lnc%d: Couldn't allocate memory for NIC\n", unit); - return (0); /* XXX -- attach failed -- not tested in - * calling routines */ + switch (sc->nic.ident) { + case BICC: + case CNET98S: + skip = 2; + break; + default: + skip = 1; + break; } /* Set default mode */ @@ -1232,9 +888,8 @@ lnc_attach_sc(struct lnc_softc *sc, int unit) /* Fill in arpcom structure entries */ sc->arpcom.ac_if.if_softc = sc; - sc->arpcom.ac_if.if_name = lncdriver.name; + sc->arpcom.ac_if.if_name = "lnc"; sc->arpcom.ac_if.if_unit = unit; - sc->arpcom.ac_if.if_mtu = ETHERMTU; sc->arpcom.ac_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; sc->arpcom.ac_if.if_timer = 0; sc->arpcom.ac_if.if_output = ether_output; @@ -1242,11 +897,16 @@ lnc_attach_sc(struct lnc_softc *sc, int unit) sc->arpcom.ac_if.if_ioctl = lnc_ioctl; sc->arpcom.ac_if.if_watchdog = lnc_watchdog; sc->arpcom.ac_if.if_init = lnc_init; - sc->arpcom.ac_if.if_type = IFT_ETHER; - sc->arpcom.ac_if.if_addrlen = ETHER_ADDR_LEN; - sc->arpcom.ac_if.if_hdrlen = ETHER_HDR_LEN; sc->arpcom.ac_if.if_snd.ifq_maxlen = IFQ_MAXLEN; + /* Extract MAC address from PROM */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + sc->arpcom.ac_enaddr[i] = lnc_inb(i * skip); + + /* + * XXX -- should check return status of if_attach + */ + ether_ifattach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); printf("lnc%d: ", unit); @@ -1260,72 +920,6 @@ lnc_attach_sc(struct lnc_softc *sc, int unit) return (1); } -static int -lnc_attach(struct isa_device * isa_dev) -{ - int unit = isa_dev->id_unit; - struct lnc_softc *sc = &lnc_softc[unit]; - int result; - - isa_dev->id_ointr = lncintr; - result = lnc_attach_sc (sc, unit); - if (result == 0) - return (0); - -#ifndef PC98 - /* - * XXX - is it safe to call isa_dmacascade() after if_attach() - * and ether_ifattach() have been called in lnc_attach() ??? - */ - if ((sc->nic.mem_mode != SHMEM) && - (sc->nic.ic < PCnet_32)) - isa_dmacascade(isa_dev->id_drq); -#endif - - return result; -} - -#if NPCI > 0 -void * -lnc_attach_ne2100_pci(int unit, unsigned iobase) -{ - int i; - struct lnc_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); - - if (sc) { - bzero (sc, sizeof *sc); - - sc->rap = iobase + PCNET_RAP; - sc->rdp = iobase + PCNET_RDP; - sc->bdp = iobase + PCNET_BDP; - - sc->nic.ic = pcnet_probe(sc); - if (sc->nic.ic >= PCnet_32) { - sc->nic.ident = NE2100; - sc->nic.mem_mode = DMA_FIXED; - - /* XXX - For now just use the defines */ - sc->nrdre = NRDRE; - sc->ntdre = NTDRE; - - /* Extract MAC address from PROM */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - sc->arpcom.ac_enaddr[i] = inb(iobase + i); - - if (lnc_attach_sc(sc, unit) == 0) { - free(sc, M_DEVBUF); - sc = NULL; - } - } - else { - free(sc, M_DEVBUF); - sc = NULL; - } - } - return sc; -} -#endif - static void lnc_init(xsc) void *xsc; @@ -1336,8 +930,10 @@ lnc_init(xsc) /* Check that interface has valid address */ - if (TAILQ_EMPTY(&sc->arpcom.ac_if.if_addrhead)) /* XXX unlikely */ + if (TAILQ_EMPTY(&sc->arpcom.ac_if.if_addrhead)) { /* XXX unlikely */ +printf("XXX no address?\n"); return; + } /* Shut down interface */ @@ -1355,8 +951,6 @@ lnc_init(xsc) * The alignment tests are particularly paranoid. */ - - sc->recv_next = 0; sc->trans_ring = sc->recv_ring + NDESC(sc->nrdre); sc->trans_next = 0; @@ -1474,11 +1068,11 @@ lnc_init(xsc) write_csr(sc, CSR3, 0); /* Let's see if it starts */ - - write_csr(sc, CSR0, INIT); - for (i = 0; i < 1000; i++) - if (read_csr(sc, CSR0) & IDON) - break; +/* +printf("Enabling lnc interrupts\n"); + sc->arpcom.ac_if.if_timer = 10; + write_csr(sc, CSR0, INIT|INEA); +*/ /* * Now that the initialisation is complete there's no reason to @@ -1487,6 +1081,11 @@ lnc_init(xsc) * time. */ + write_csr(sc, CSR0, INIT); + for(i=0; i < 1000; i++) + if (read_csr(sc, CSR0) & IDON) + break; + if (read_csr(sc, CSR0) & IDON) { /* * Enable interrupts, start the LANCE, mark the interface as @@ -1525,8 +1124,9 @@ lnc_init(xsc) */ void -lncintr_sc(struct lnc_softc *sc) +lncintr(void *arg) { + lnc_softc_t *sc = arg; int unit = sc->arpcom.ac_if.if_unit; u_short csr0; @@ -1535,7 +1135,7 @@ lncintr_sc(struct lnc_softc *sc) * we have to include it in any writes that clear other flags. */ - while ((csr0 = inw(sc->rdp)) & INTR) { + while ((csr0 = lnc_inw(sc->rdp)) & INTR) { /* * Clear interrupt flags early to avoid race conditions. The @@ -1545,10 +1145,20 @@ lncintr_sc(struct lnc_softc *sc) * be missed. */ -/* outw(sc->rdp, IDON | CERR | BABL | MISS | MERR | RINT | TINT | INEA); */ - outw(sc->rdp, csr0); + lnc_outw(sc->rdp, csr0); + /*lnc_outw(sc->rdp, IDON | CERR | BABL | MISS | MERR | RINT | TINT | INEA);*/ - /* We don't do anything with the IDON flag */ +#ifdef notyet + if (csr0 & IDON) { +printf("IDON\n"); + sc->arpcom.ac_if.if_timer = 0; + write_csr(sc, CSR0, STRT | INEA); + sc->arpcom.ac_if.if_flags |= IFF_RUNNING; + sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + lnc_start(&sc->arpcom.ac_if); + continue; + } +#endif if (csr0 & ERR) { if (csr0 & CERR) { @@ -1592,13 +1202,6 @@ lncintr_sc(struct lnc_softc *sc) } } -static void -lncintr(int unit) -{ - struct lnc_softc *sc = &lnc_softc[unit]; - lncintr_sc (sc); -} - static __inline int mbuf_to_buffer(struct mbuf *m, char *buffer) { @@ -1769,7 +1372,7 @@ lnc_start(struct ifnet *ifp) } /* Force an immediate poll of the transmit ring */ - outw(sc->rdp, TDMD | INEA); + lnc_outw(sc->rdp, TDMD | INEA); /* * Set a timer so if the buggy Am7990.h shuts @@ -1928,7 +1531,7 @@ lnc_dump_state(struct lnc_softc *sc) read_csr(sc, CSR2), read_csr(sc, CSR3)); /* Set RAP back to CSR0 */ - outw(sc->rap, CSR0); + lnc_outw(sc->rap, CSR0); } void diff --git a/sys/dev/netif/lnc/if_lnc_isa.c b/sys/dev/netif/lnc/if_lnc_isa.c new file mode 100644 index 0000000000..1ff72c3223 --- /dev/null +++ b/sys/dev/netif/lnc/if_lnc_isa.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 1994-2000 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/lnc/if_lnc_isa.c,v 1.12 2001/07/04 13:00:19 nyan Exp $ + * $DragonFly: src/sys/dev/netif/lnc/if_lnc_isa.c,v 1.1 2003/12/07 19:23:39 dillon Exp $ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +static struct isa_pnp_id lnc_pnp_ids[] = { + {0, NULL} +}; + +static int +lnc_legacy_probe(device_t dev) +{ + struct lnc_softc *sc = device_get_softc(dev); + + sc->portrid = 0; + sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->portrid, + 0, ~0, 1, RF_ACTIVE); + + if (! sc->portres) { + device_printf(dev, "Failed to allocate I/O ports\n"); + lnc_release_resources(dev); + return (ENXIO); + } + + sc->lnc_btag = rman_get_bustag(sc->portres); + sc->lnc_bhandle = rman_get_bushandle(sc->portres); + + /* + * There isn't any way to determine if a NIC is a BICC. Basically, if + * the lance probe succeeds using the i/o addresses of the BICC then + * we assume it's a BICC. + * + */ + sc->rap = BICC_RAP; + sc->rdp = BICC_RDP; + sc->nic.mem_mode = DMA_FIXED; + /* XXX Should set BICC_IOSIZE et al somewhere to alloc + resources correctly */ + + if ((sc->nic.ic = lance_probe(sc))) { + device_set_desc(dev, "BICC Isolan"); + sc->nic.ident = BICC; + lnc_release_resources(dev); + return (0); + } else { + /* It's not a BICC so try the standard NE2100 ports */ + sc->rap = PCNET_RAP; + sc->rdp = PCNET_RDP; + if ((sc->nic.ic = lance_probe(sc))) { + sc->nic.ident = NE2100; + device_set_desc(dev, "NE2100"); + lnc_release_resources(dev); + return (0); + } else { + lnc_release_resources(dev); + return (ENXIO); + } + } +} + +static int +lnc_isa_probe(device_t dev) +{ + int pnp; + + pnp = ISA_PNP_PROBE(device_get_parent(dev), dev, lnc_pnp_ids); + if (pnp == ENOENT) { + /* It's not a PNP card, see if we support it by probing it */ + return (lnc_legacy_probe(dev)); + } else if (pnp == ENXIO) { + return (ENXIO); + } else { + /* Found PNP card we support */ + return (0); + } +} + +static void +lnc_alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error) +{ + /* Do nothing */ + return; +} + +static int +lnc_isa_attach(device_t dev) +{ + lnc_softc_t *sc = device_get_softc(dev); + int err = 0; + bus_size_t lnc_mem_size; + + device_printf(dev, "Attaching %s\n", device_get_desc(dev)); + + sc->portrid = 0; + sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->portrid, + 0, ~0, 1, RF_ACTIVE); + + if (! sc->portres) { + device_printf(dev, "Failed to allocate I/O ports\n"); + lnc_release_resources(dev); + return (ENXIO); + } + + sc->drqrid = 0; + sc->drqres = bus_alloc_resource(dev, SYS_RES_DRQ, &sc->drqrid, + 0, ~0, 1, RF_ACTIVE); + + if (! sc->drqres) { + device_printf(dev, "Failed to allocate DMA channel\n"); + lnc_release_resources(dev); + return (ENXIO); + } + + if (isa_get_irq(dev) == -1) + bus_set_resource(dev, SYS_RES_IRQ, 0, 10, 1); + + sc->irqrid = 0; + sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqrid, 0, ~0, 1, + RF_ACTIVE); + + if (! sc->irqres) { + device_printf(dev, "Failed to allocate irq\n"); + lnc_release_resources(dev); + return (ENXIO); + } + + err = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, lncintr, + sc, &sc->intrhand); + + if (err) { + device_printf(dev, "Failed to setup irq handler\n"); + lnc_release_resources(dev); + return (err); + } + + /* XXX temp setting for nic */ + sc->nic.mem_mode = DMA_FIXED; + sc->nrdre = NRDRE; + sc->ntdre = NTDRE; + + if (sc->nic.ident == NE2100) { + sc->rap = PCNET_RAP; + sc->rdp = PCNET_RDP; + sc->bdp = PCNET_BDP; + } else { + sc->rap = BICC_RAP; + sc->rdp = BICC_RDP; + } + + /* Create a DMA tag describing the ring memory we need */ + + lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) * + sizeof(struct host_ring_entry)); + + lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) + + (NDESC(sc->ntdre) * TRANSBUFSIZE); + + err = bus_dma_tag_create(NULL, /* parent */ + 4, /* alignement */ + 0, /* boundary */ + BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + lnc_mem_size, /* segsize */ + 1, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + &sc->dmat); + + if (err) { + device_printf(dev, "Can't create DMA tag\n"); + lnc_release_resources(dev); + return (ENOMEM); + } + + err = bus_dmamem_alloc(sc->dmat, (void **)&sc->recv_ring, + BUS_DMA_NOWAIT, &sc->dmamap); + + if (err) { + device_printf(dev, "Couldn't allocate memory\n"); + lnc_release_resources(dev); + return (ENOMEM); + } + + err = bus_dmamap_load(sc->dmat, sc->dmamap, sc->recv_ring, lnc_mem_size, + lnc_alloc_callback, sc->recv_ring, BUS_DMA_NOWAIT); + + if (err) { + device_printf(dev, "Couldn't load DMA map\n"); + lnc_release_resources(dev); + return (ENOMEM); + } + + isa_dmacascade(rman_get_start(sc->drqres)); + + /* Call generic attach code */ + if (! lnc_attach_common(dev)) { + device_printf(dev, "Generic attach code failed\n"); + lnc_release_resources(dev); + return (ENXIO); + } + return (0); +} + +static int +lnc_isa_detach(device_t dev) +{ + lnc_softc_t *sc = device_get_softc(dev); + int s = splimp(); + + ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); + splx(s); + + lnc_stop(sc); + lnc_release_resources(dev); + + return (0); +} + +static device_method_t lnc_isa_methods[] = { +/* DEVMETHOD(device_identify, lnc_isa_identify), */ + DEVMETHOD(device_probe, lnc_isa_probe), + DEVMETHOD(device_attach, lnc_isa_attach), + DEVMETHOD(device_detach, lnc_isa_detach), +#ifdef notyet + DEVMETHOD(device_suspend, lnc_isa_suspend), + DEVMETHOD(device_resume, lnc_isa_resume), + DEVMETHOD(device_shutdown, lnc_isa_shutdown), +#endif + { 0, 0 } +}; + +static driver_t lnc_isa_driver = { + "lnc", + lnc_isa_methods, + sizeof(struct lnc_softc), +}; + +DRIVER_MODULE(if_lnc, isa, lnc_isa_driver, lnc_devclass, 0, 0); diff --git a/sys/dev/netif/lnc/if_lnc_pci.c b/sys/dev/netif/lnc/if_lnc_pci.c new file mode 100644 index 0000000000..8cb83b725d --- /dev/null +++ b/sys/dev/netif/lnc/if_lnc_pci.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 1994-2000 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/lnc/if_lnc_pci.c,v 1.25 2001/07/04 13:00:19 nyan Exp $ + * $DragonFly: src/sys/dev/netif/lnc/if_lnc_pci.c,v 1.1 2003/12/07 19:23:39 dillon Exp $ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#define AMD_VENDOR_ID 0x1022 +#define PCI_DEVICE_ID_PCNet_PCI 0x2000 +#define PCI_DEVICE_ID_PCHome_PCI 0x2001 + +#define LNC_PROBE_PRIORITY -1 + +static int +lnc_pci_probe(device_t dev) +{ + if (pci_get_vendor(dev) != AMD_VENDOR_ID) + return (ENXIO); + + switch(pci_get_device(dev)) { + case PCI_DEVICE_ID_PCNet_PCI: + device_set_desc(dev, "PCNet/PCI Ethernet adapter"); + return(LNC_PROBE_PRIORITY); + break; + case PCI_DEVICE_ID_PCHome_PCI: + device_set_desc(dev, "PCHome/PCI Ethernet adapter"); + return(LNC_PROBE_PRIORITY); + break; + default: + return (ENXIO); + break; + } + return (ENXIO); +} + +static void +lnc_alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error) +{ + /* Do nothing */ + return; +} + +static int +lnc_pci_attach(device_t dev) +{ + lnc_softc_t *sc = device_get_softc(dev); + unsigned command; + int rid = 0; + int err = 0; + bus_size_t lnc_mem_size; + + device_printf(dev, "Attaching %s\n", device_get_desc(dev)); + + command = pci_read_config(dev, PCIR_COMMAND, 4); + command |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN; + pci_write_config(dev, PCIR_COMMAND, command, 4); + + rid = PCIR_MAPS; + sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, + RF_ACTIVE); + + if (! sc->portres) + device_printf(dev, "Cannot allocate I/O ports\n"); + + rid = 0; + sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_ACTIVE|RF_SHAREABLE); + + if (! sc->irqres) + device_printf(dev, "Cannot allocate irq\n"); + + err = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, lncintr, + sc, &sc->intrhand); + if (err) + device_printf(dev, "Cannot setup irq handler\n"); + + sc->lnc_btag = rman_get_bustag(sc->portres); + sc->lnc_bhandle = rman_get_bushandle(sc->portres); + + /* XXX temp setting for nic */ + sc->nic.ic = PCnet_PCI; + sc->nic.ident = NE2100; + sc->nic.mem_mode = DMA_FIXED; + sc->nrdre = NRDRE; + sc->ntdre = NTDRE; + sc->rap = PCNET_RAP; + sc->rdp = PCNET_RDP; + sc->bdp = PCNET_BDP; + + /* Create a DMA tag describing the ring memory we need */ + + lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) * + sizeof(struct host_ring_entry)); + + lnc_mem_size += sizeof(struct init_block) + (sizeof(struct mds) * + (NDESC(sc->nrdre) + NDESC(sc->ntdre))) + MEM_SLEW; + + lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) + + (NDESC(sc->ntdre) * TRANSBUFSIZE); + + err = bus_dma_tag_create(NULL, /* parent */ + 1, /* alignement */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + lnc_mem_size, /* segsize */ + 1, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + &sc->dmat); + + if (err) { + device_printf(dev, "Can't create DMA tag\n"); + /* XXX need to free currently allocated resources here */ + return (ENOMEM); + } + + err = bus_dmamem_alloc(sc->dmat, (void **)&sc->recv_ring, + BUS_DMA_NOWAIT, &sc->dmamap); + + if (err) { + device_printf(dev, "Couldn't allocate memory\n"); + /* XXX need to free currently allocated resources here */ + return (ENOMEM); + } + + bus_dmamap_load(sc->dmat, sc->dmamap, sc->recv_ring, lnc_mem_size, + lnc_alloc_callback, sc->recv_ring, BUS_DMA_NOWAIT); + + /* Call generic attach code */ + if (! lnc_attach_common(dev)) { + device_printf(dev, "Generic attach code failed\n"); + } + return (0); +} + +static int +lnc_pci_detach(device_t dev) +{ + lnc_softc_t *sc = device_get_softc(dev); + int s = splimp(); + + ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); + + lnc_stop(sc); + bus_teardown_intr(dev, sc->irqres, sc->intrhand); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irqres); + bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, sc->portres); + + bus_dmamap_unload(sc->dmat, sc->dmamap); + bus_dmamem_free(sc->dmat, sc->recv_ring, sc->dmamap); + bus_dma_tag_destroy(sc->dmat); + + splx(s); + return (0); +} + +static device_method_t lnc_pci_methods[] = { + DEVMETHOD(device_probe, lnc_pci_probe), + DEVMETHOD(device_attach, lnc_pci_attach), + DEVMETHOD(device_detach, lnc_pci_detach), +#ifdef notyet + DEVMETHOD(device_suspend, lnc_pci_suspend), + DEVMETHOD(device_resume, lnc_pci_resume), + DEVMETHOD(device_shutdown, lnc_pci_shutdown), +#endif + { 0, 0 } +}; + +static driver_t lnc_pci_driver = { + "lnc", + lnc_pci_methods, + sizeof(struct lnc_softc), +}; + +DRIVER_MODULE(if_lnc, pci, lnc_pci_driver, lnc_devclass, 0, 0); diff --git a/sys/dev/netif/lnc/if_lncreg.h b/sys/dev/netif/lnc/if_lncreg.h new file mode 100644 index 0000000000..7084a5c50c --- /dev/null +++ b/sys/dev/netif/lnc/if_lncreg.h @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 1994-2000 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/lnc/if_lncreg.h,v 1.7 2001/07/04 13:00:19 nyan Exp $ + * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lncreg.h,v 1.1 2003/12/07 19:23:39 dillon Exp $ + */ + +/* + * Am7990, Local Area Network Controller for Ethernet (LANCE) + * + * The LANCE has four Control and Status Registers(CSRs) which are accessed + * through two bus addressable ports, the address port (RAP) and the data + * port (RDP). + * + */ + +#define CSR0 0 +#define CSR1 1 +#define CSR2 2 +#define CSR3 3 +#define CSR88 88 +#define CSR89 89 + +#define BCR49 49 +#define BCR32 32 +#define BCR33 33 +#define BCR34 34 + + +/* Control and Status Register Masks */ + +/* CSR0 */ + +#define ERR 0x8000 +#define BABL 0x4000 +#define CERR 0x2000 +#define MISS 0x1000 +#define MERR 0x0800 +#define RINT 0x0400 +#define TINT 0x0200 +#define IDON 0x0100 +#define INTR 0x0080 +#define INEA 0x0040 +#define RXON 0x0020 +#define TXON 0x0010 +#define TDMD 0x0008 +#define STOP 0x0004 +#define STRT 0x0002 +#define INIT 0x0001 + +/* + * CSR3 + * + * Bits 3-15 are reserved. + * + */ + +#define BSWP 0x0004 +#define ACON 0x0002 +#define BCON 0x0001 + +/* ISA Bus Configuration Registers */ +#define MSRDA 0x0000 /* ISACSR0: Master Mode Read Activity */ +#define MSWRA 0x0001 /* ISACSR1: Master Mode Write Activity */ +#define MC 0x0002 /* ISACSR2: Miscellaneous Configuration */ + +#define LED1 0x0005 /* ISACSR5: LED1 Status */ +#define LED2 0x0006 /* ISACSR6: LED2 Status */ +#define LED3 0x0007 /* ISACSR7: LED3 Status */ + +#define LED_PSE 0x0080 /* Pulse Stretcher */ +#define LED_XMTE 0x0010 /* Transmit Status */ +#define LED_RVPOLE 0x0008 /* Receive Polarity */ +#define LED_RCVE 0x0004 /* Receive Status */ +#define LED_JABE 0x0002 /* Jabber */ +#define LED_COLE 0x0001 /* Collision */ + +/* Initialisation block */ + +struct init_block { + u_short mode; /* Mode register */ + u_char padr[6]; /* Ethernet address */ + u_char ladrf[8]; /* Logical address filter (multicast) */ + u_short rdra; /* Low order pointer to receive ring */ + u_short rlen; /* High order pointer and no. rings */ + u_short tdra; /* Low order pointer to transmit ring */ + u_short tlen; /* High order pointer and no rings */ +}; + +/* Initialisation Block Mode Register Masks */ + +#define PROM 0x8000 /* Promiscuous Mode */ +#define DRCVBC 0x4000 /* Disable Receive Broadcast */ +#define DRCVPA 0x2000 /* Disable Receive Physical Address */ +#define DLNKTST 0x1000 /* Disable Link Status */ +#define DAPC 0x0800 /* Disable Automatic Polarity Correction */ +#define MENDECL 0x0400 /* MENDEC Loopback Mode */ +#define LRT 0x0200 /* Low Receive Threshold (T-MAU mode only) */ +#define TSEL 0x0200 /* Transmit Mode Select (AUI mode only) */ +#define PORTSEL 0x0180 /* Port Select bits */ +#define INTL 0x0040 /* Internal Loopback */ +#define DRTY 0x0020 /* Disable Retry */ +#define FCOLL 0x0010 /* Force Collision */ +#define DXMTFCS 0x0008 /* Disable transmit CRC (FCS) */ +#define LOOP 0x0004 /* Loopback Enabl */ +#define DTX 0x0002 /* Disable the transmitter */ +#define DRX 0x0001 /* Disable the receiver */ + +/* + * Message Descriptor Structure + * + * Each transmit or receive descriptor ring entry (RDRE's and TDRE's) + * is composed of 4, 16-bit, message descriptors. They contain the following + * information. + * + * 1. The address of the actual message data buffer in user (host) memory. + * 2. The length of that message buffer. + * 3. The status information for that particular buffer. The eight most + * significant bits of md1 are collectively termed the STATUS of the + * descriptor. + * + * Descriptor md0 contains LADR 0-15, the low order 16 bits of the 24-bit + * address of the actual data buffer. Bits 0-7 of descriptor md1 contain + * HADR, the high order 8-bits of the 24-bit data buffer address. Bits 8-15 + * of md1 contain the status flags of the buffer. Descriptor md2 contains the + * buffer byte count in bits 0-11 as a two's complement number and must have + * 1's written to bits 12-15. For the receive entry md3 has the Message Byte + * Count in bits 0-11, this is the length of the received message and is valid + * only when ERR is cleared and ENP is set. For the transmit entry it contains + * more status information. + * + */ + +struct mds { + u_short md0; + u_short md1; + short md2; + u_short md3; +}; + +/* Receive STATUS flags for md1 */ + +#define OWN 0x8000 /* Owner bit, 0=host, 1=Lance */ +#define MDERR 0x4000 /* Error */ +#define FRAM 0x2000 /* Framing error error */ +#define OFLO 0x1000 /* Silo overflow */ +#define CRC 0x0800 /* CRC error */ +#define RBUFF 0x0400 /* Buffer error */ +#define STP 0x0200 /* Start of packet */ +#define ENP 0x0100 /* End of packet */ +#define HADR 0x00FF /* High order address bits */ + +/* Receive STATUS flags for md2 */ + +#define BCNT 0x0FFF /* Size of data buffer as 2's comp. no. */ + +/* Receive STATUS flags for md3 */ + +#define MCNT 0x0FFF /* Total size of data for received packet */ + +/* Transmit STATUS flags for md1 */ + +#define ADD_FCS 0x2000 /* Controls generation of FCS */ +#define MORE 0x1000 /* Indicates more than one retry was needed */ +#define ONE 0x0800 /* Exactly one retry was needed */ +#define DEF 0x0400 /* Packet transmit deferred -- channel busy */ + +/* + * Transmit status flags for md2 + * + * Same as for receive descriptor. + * + * BCNT 0x0FFF Size of data buffer as 2's complement number. + * + */ + +/* Transmit status flags for md3 */ + +#define TBUFF 0x8000 /* Buffer error */ +#define UFLO 0x4000 /* Silo underflow */ +#define LCOL 0x1000 /* Late collision */ +#define LCAR 0x0800 /* Loss of carrier */ +#define RTRY 0x0400 /* Tried 16 times */ +#define TDR 0x03FF /* Time domain reflectometry */ diff --git a/sys/dev/netif/lnc/if_lncvar.h b/sys/dev/netif/lnc/if_lncvar.h new file mode 100644 index 0000000000..e7e6a0c5ec --- /dev/null +++ b/sys/dev/netif/lnc/if_lncvar.h @@ -0,0 +1,266 @@ +/*- + * Copyright (c) 1994-1998 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Richards. + * 4. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/lnc/if_lncvar.h,v 1.23 2001/07/04 13:00:20 nyan Exp $ + * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lncvar.h,v 1.1 2003/12/07 19:23:39 dillon Exp $ + */ + +/* + * Initialize multicast address hashing registers to accept + * all multicasts (only used when in promiscuous mode) + */ +#define MULTI_INIT_ADDR 0xff + +#define NORMAL 0 + +#define NRDRE 3 +#define NTDRE 3 +#define RECVBUFSIZE 1518 /* Packet size rounded to dword boundary */ +#define TRANSBUFSIZE 1518 +#define MBUF_CACHE_LIMIT 0 + +#define MEM_SLEW 8 + +/* LNC Flags */ +#define LNC_INITIALISED 1 +#define LNC_ALLMULTI 2 + +/* BICC port addresses */ +#define BICC_IOSIZE 16 +#define BICC_RDP 0x0c /* Register Data Port */ +#define BICC_RAP 0x0e /* Register Address Port */ + +/* NE2100 port addresses */ +#define NE2100_IOSIZE 24 +#define PCNET_RDP 0x10 /* Register Data Port */ +#define PCNET_RAP 0x12 /* Register Address Port */ +#define PCNET_RESET 0x14 +#define PCNET_BDP 0x16 +#define PCNET_VSW 0x18 + +/* DEPCA port addresses */ +#define DEPCA_IOSIZE 16 +#define DEPCA_CTRL 0x00 /* NIC Control and status register */ +#define DEPCA_RDP 0x04 /* Register Data Port */ +#define DEPCA_RAP 0x06 /* Register Address Port */ +#define DEPCA_ADP 0x0c + +/* DEPCA specific defines */ +#define DEPCA_ADDR_ROM_SIZE 32 + +/* C-NET(98)S port addresses */ +/* Notice, we can ignore fragmantation by using isa_alloc_resourcev(). */ +#define CNET98S_IOSIZE 32 +#define CNET98S_RDP 0x10 /* Register Data Port */ +#define CNET98S_RAP 0x12 /* Register Address Port */ +#define CNET98S_RESET 0x14 +#define CNET98S_IDP 0x16 +#define CNET98S_EEPROM 0x1e + +/* Chip types */ +#define LANCE 1 /* Am7990 */ +#define C_LANCE 2 /* Am79C90 */ +#define PCnet_ISA 3 /* Am79C960 */ +#define PCnet_ISAplus 4 /* Am79C961 */ +#define PCnet_ISA_II 5 /* Am79C961A */ +#define PCnet_32 6 /* Am79C965 */ +#define PCnet_PCI 7 /* Am79C970 */ +#define PCnet_PCI_II 8 /* Am79C970A */ +#define PCnet_FAST 9 /* Am79C971 */ +#define PCnet_FASTplus 10 /* Am79C972 */ +#define PCnet_Home 11 /* Am79C978 */ + + +/* CSR88-89: Chip ID masks */ +#define AMD_MASK 0x003 +#define PART_MASK 0xffff +#define Am79C960 0x0003 +#define Am79C961 0x2260 +#define Am79C961A 0x2261 +#define Am79C965 0x2430 +#define Am79C970 0x0242 +#define Am79C970A 0x2621 +#define Am79C971 0x2623 +#define Am79C972 0x2624 +#define Am79C973 0x2625 +#define Am79C978 0x2626 + +/* Board types */ +#define UNKNOWN 0 +#define BICC 1 +#define NE2100 2 +#define DEPCA 3 +#define CNET98S 4 /* PC-98 */ + +/* mem_mode values */ +#define DMA_FIXED 1 +#define DMA_MBUF 2 +#define SHMEM 4 + +#define MEM_MODES \ + "\20\3SHMEM\2DMA_MBUF\1DMA_FIXED" + +#define CSR0_FLAGS \ + "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\ + \10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT" + +#define INIT_MODE \ + "\20\20PROM\07INTL\06DRTY\05COLL\04DTCR\03LOOP\02DTX\01DRX" + +#define RECV_MD1 \ + "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP" + +#define TRANS_MD1 \ + "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP" + +#define TRANS_MD3 \ + "\20\6BUFF\5UFLO\4RES\3LCOL\2LCAR\1RTRY" + +#ifdef LNC_KEEP_STATS +#define LNCSTATS_STRUCT \ + struct lnc_stats { \ + int idon; \ + int rint; \ + int tint; \ + int cerr; \ + int babl; \ + int miss; \ + int merr; \ + int rxoff; \ + int txoff; \ + int terr; \ + int lcol; \ + int lcar; \ + int tbuff; \ + int def; \ + int more; \ + int one; \ + int uflo; \ + int rtry; \ + int rerr; \ + int fram; \ + int oflo; \ + int crc; \ + int rbuff; \ + int drop_packet; \ + int trans_ring_full; \ + } lnc_stats; +#define LNCSTATS(X) ++(sc->lnc_stats.X); +#else +#define LNCSTATS_STRUCT +#define LNCSTATS(X) +#endif + +struct nic_info { + int ident; /* Type of card */ + int ic; /* Type of ic, Am7990, Am79C960 etc. */ + int mem_mode; + int iobase; + int mode; /* Mode setting at initialization */ +}; + +typedef struct lnc_softc { + struct resource *irqres; + int irqrid; + struct resource *drqres; + int drqrid; + struct resource *portres; + int portrid; + bus_space_tag_t lnc_btag; + bus_space_handle_t lnc_bhandle; + void *intrhand; + bus_dma_tag_t dmat; + bus_dmamap_t dmamap; + struct arpcom arpcom; /* see ../../net/if_arp.h */ + struct nic_info nic; /* NIC specific info */ + int nrdre; + struct host_ring_entry *recv_ring; /* start of alloc'd mem */ + int recv_next; + int ntdre; + struct host_ring_entry *trans_ring; + int trans_next; + struct init_block *init_block; /* Initialisation block */ + int pending_transmits; /* No. of transmit descriptors in + use */ + int next_to_send; + struct mbuf *mbufs; + int mbuf_count; + int flags; + int rap; + int rdp; + int bdp; + #ifdef DEBUG + int lnc_debug; + #endif + LNCSTATS_STRUCT +} lnc_softc_t; + +struct host_ring_entry { + struct mds *md; + union { + struct mbuf *mbuf; + char *data; + }buff; +}; + +#define NDESC(len2) (1 << len2) + +#define INC_MD_PTR(ptr, no_entries) \ + if (++ptr >= NDESC(no_entries)) \ + ptr = 0; + +#define DEC_MD_PTR(ptr, no_entries) \ + if (--ptr < 0) \ + ptr = NDESC(no_entries) - 1; + +#define RECV_NEXT (sc->recv_ring->base + sc->recv_next) +#define TRANS_NEXT (sc->trans_ring->base + sc->trans_next) + +#define lnc_inb(port) \ + bus_space_read_1(sc->lnc_btag, sc->lnc_bhandle, (port)) +#define lnc_inw(port) \ + bus_space_read_2(sc->lnc_btag, sc->lnc_bhandle, (port)) +#define lnc_outw(port, val) \ + bus_space_write_2(sc->lnc_btag, sc->lnc_bhandle, (port), (val)) + +/* Functional declarations */ +extern int lance_probe(struct lnc_softc *); +extern void lnc_release_resources(device_t); +extern int lnc_attach_common(device_t); +extern void lnc_stop(struct lnc_softc *); + +extern void write_csr(struct lnc_softc *, u_short, u_short); +extern u_short read_csr(struct lnc_softc *, u_short); + +/* Variable declarations */ +extern driver_intr_t lncintr; +extern devclass_t lnc_devclass; diff --git a/sys/dev/netif/vx/Makefile b/sys/dev/netif/vx/Makefile new file mode 100644 index 0000000000..3cfcdf9cd8 --- /dev/null +++ b/sys/dev/netif/vx/Makefile @@ -0,0 +1,8 @@ +# $DragonFly: src/sys/dev/netif/vx/Makefile,v 1.1 2003/12/07 19:23:40 dillon Exp $ + +.PATH: ${.CURDIR}/../../dev/netif/vx +KMOD = if_vx +SRCS = if_vx.c if_vx_eisa.c if_vx_pci.c +SRCS += device_if.h bus_if.h pci_if.h isa_if.h + +.include diff --git a/sys/dev/netif/vx/if_vx.c b/sys/dev/netif/vx/if_vx.c index de3829d98e..09a8ac03ed 100644 --- a/sys/dev/netif/vx/if_vx.c +++ b/sys/dev/netif/vx/if_vx.c @@ -28,7 +28,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/vx/if_vx.c,v 1.25.2.6 2002/02/13 00:43:10 dillon Exp $ - * $DragonFly: src/sys/dev/netif/vx/if_vx.c,v 1.6 2003/11/20 22:07:32 dillon Exp $ + * $DragonFly: src/sys/dev/netif/vx/if_vx.c,v 1.7 2003/12/07 19:23:40 dillon Exp $ * */ @@ -55,14 +55,6 @@ * babkin@hq.icb.chel.su */ -#include "use_vx.h" - -#if NVX < 4 /* These cost 4 bytes apiece, so give us 4 */ -#undef NVX -#define NVX 4 -#endif - - #include #include #include @@ -77,6 +69,9 @@ #include #include +#include +#include + #include #include @@ -88,10 +83,6 @@ DECLARE_DUMMY_MODULE(if_vx); -struct vx_softc *vx_softc[NVX]; - -u_long vx_count; /* both PCI and EISA */ - static struct connector_entry { int bit; char *name; @@ -113,8 +104,6 @@ static struct connector_entry { { 0, "???"} }; -/* struct vx_softc *vxalloc (int); */ -/* void *vxfree (struct vx_softc *); */ /* int vxattach (struct vx_softc *); */ static void vxtxstat (struct vx_softc *); static int vxstatus (struct vx_softc *); @@ -133,44 +122,6 @@ static void vxgetlink (struct vx_softc *); static void vxsetlink (struct vx_softc *); /* int vxbusyeeprom (struct vx_softc *); */ -struct vx_softc * -vxalloc(unit) - int unit; -{ - struct vx_softc *sc; - - if (unit >= NVX) { - printf("vx%d: unit number too high.\n", unit); - return NULL; - } - - if (vx_softc[unit]) { - printf("vx%d: already allocated.\n", unit); - return NULL; - } - - sc = malloc(sizeof(struct vx_softc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) { - printf("vx%d: cannot malloc.\n", unit); - return NULL; - } - bzero(sc, sizeof(struct vx_softc)); - callout_handle_init(&sc->ch); - - vx_softc[unit] = sc; - sc->unit = unit; - return (sc); -} - -void -vxfree(sc) - struct vx_softc *sc; -{ - vx_softc[sc->unit] = NULL; - free(sc, M_DEVBUF); - return; -} - int vxattach(sc) struct vx_softc *sc; @@ -178,8 +129,9 @@ vxattach(sc) struct ifnet *ifp = &sc->arpcom.ac_if; int i; + callout_handle_init(&sc->ch); GO_WINDOW(0); - outw(VX_COMMAND, GLOBAL_RESET); + CSR_WRITE_2(sc, VX_COMMAND, GLOBAL_RESET); VX_BUSY_WAIT; vxgetlink(sc); @@ -192,11 +144,11 @@ vxattach(sc) int x; if (vxbusyeeprom(sc)) return 0; - outw(BASE + VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD + CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD | (EEPROM_OEM_ADDR_0 + i)); if (vxbusyeeprom(sc)) return 0; - x = inw(BASE + VX_W0_EEPROM_DATA); + x = CSR_READ_2(sc, VX_W0_EEPROM_DATA); sc->arpcom.ac_enaddr[(i << 1)] = x >> 8; sc->arpcom.ac_enaddr[(i << 1) + 1] = x; } @@ -243,20 +195,20 @@ vxinit(xsc) GO_WINDOW(2); for (i = 0; i < 6; i++) /* Reload the ether_addr. */ - outb(BASE + VX_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]); + CSR_WRITE_1(sc, VX_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]); - outw(BASE + VX_COMMAND, RX_RESET); + CSR_WRITE_2(sc, VX_COMMAND, RX_RESET); VX_BUSY_WAIT; - outw(BASE + VX_COMMAND, TX_RESET); + CSR_WRITE_2(sc, VX_COMMAND, TX_RESET); VX_BUSY_WAIT; GO_WINDOW(1); /* Window 1 is operating window */ for (i = 0; i < 31; i++) - inb(BASE + VX_W1_TX_STATUS); + CSR_READ_1(sc, VX_W1_TX_STATUS); - outw(BASE + VX_COMMAND,SET_RD_0_MASK | S_CARD_FAILURE | + CSR_WRITE_2(sc, VX_COMMAND,SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL); - outw(BASE + VX_COMMAND,SET_INTR_MASK | S_CARD_FAILURE | + CSR_WRITE_2(sc, VX_COMMAND,SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL); /* @@ -265,13 +217,13 @@ vxinit(xsc) * already be queued. However, a single stray interrupt is * unimportant. */ - outw(BASE + VX_COMMAND, ACK_INTR | 0xff); + CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | 0xff); vxsetfilter(sc); vxsetlink(sc); - outw(BASE + VX_COMMAND, RX_ENABLE); - outw(BASE + VX_COMMAND, TX_ENABLE); + CSR_WRITE_2(sc, VX_COMMAND, RX_ENABLE); + CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE); vxmbuffill((caddr_t) sc); @@ -290,7 +242,7 @@ vxsetfilter(sc) struct ifnet *ifp = &sc->arpcom.ac_if; GO_WINDOW(1); /* Window 1 is operating window */ - outw(BASE + VX_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST | + CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST | FIL_MULTICAST | ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 )); } @@ -302,7 +254,7 @@ vxgetlink(sc) int n, k; GO_WINDOW(3); - sc->vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f; + sc->vx_connectors = CSR_READ_2(sc, VX_W3_RESET_OPT) & 0x7f; for (n = 0, k = 0; k < VX_CONNECTORS; k++) { if (sc->vx_connectors & conn_tab[k].bit) { if (n > 0) { @@ -317,7 +269,7 @@ vxgetlink(sc) return; } GO_WINDOW(3); - sc->vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG) + sc->vx_connector = (CSR_READ_4(sc, VX_W3_INTERNAL_CFG) & INTERNAL_CONNECTOR_MASK) >> INTERNAL_CONNECTOR_BITS; if (sc->vx_connector & 0x10) { @@ -403,29 +355,29 @@ vxsetlink(sc) /* Set the selected connector. */ GO_WINDOW(3); - j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK; - outl(BASE + VX_W3_INTERNAL_CFG, j | (i <if_unit]; + struct vx_softc *sc = ifp->if_softc; struct mbuf *m0; int sh, len, pad; @@ -474,23 +426,23 @@ startagain: goto readcheck; } VX_BUSY_WAIT; - if (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) { - outw(BASE + VX_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad + 4) >> 2)); + if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) { + CSR_WRITE_2(sc, VX_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad + 4) >> 2)); /* not enough room in FIFO */ - if (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) { /* make sure */ + if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) { /* make sure */ ifp->if_flags |= IFF_OACTIVE; ifp->if_timer = 1; return; } } - outw(BASE + VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2)); + CSR_WRITE_2(sc, VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2)); IF_DEQUEUE(&ifp->if_snd, m0); if (m0 == NULL) { /* not really needed */ return; } VX_BUSY_WAIT; - outw(BASE + VX_COMMAND, SET_TX_START_THRESH | + CSR_WRITE_2(sc, VX_COMMAND, SET_TX_START_THRESH | ((len / 4 + sc->tx_start_thresh) >> 2)); if (sc->arpcom.ac_if.if_bpf) { @@ -503,18 +455,21 @@ startagain: */ sh = splhigh(); - outl(BASE + VX_W1_TX_PIO_WR_1, len | TX_INDICATE); + CSR_WRITE_4(sc, VX_W1_TX_PIO_WR_1, len | TX_INDICATE); while (m0) { if (m0->m_len > 3) - outsl(BASE + VX_W1_TX_PIO_WR_1, mtod(m0, caddr_t), m0->m_len / 4); + bus_space_write_multi_4(sc->vx_btag, sc->vx_bhandle, + VX_W1_TX_PIO_WR_1, + (u_int32_t *)mtod(m0, caddr_t), m0->m_len / 4); if (m0->m_len & 3) - outsb(BASE + VX_W1_TX_PIO_WR_1, - mtod(m0, caddr_t) + (m0->m_len & ~3) , m0->m_len & 3); + bus_space_write_multi_1(sc->vx_btag, sc->vx_bhandle, + VX_W1_TX_PIO_WR_1, + mtod(m0, caddr_t) + (m0->m_len & ~3), m0->m_len & 3); m0 = m_free(m0); } while (pad--) - outb(BASE + VX_W1_TX_PIO_WR_1, 0); /* Padding */ + CSR_WRITE_1(sc, VX_W1_TX_PIO_WR_1, 0); /* Padding */ splx(sh); @@ -522,10 +477,10 @@ startagain: ifp->if_timer = 1; readcheck: - if ((inw(BASE + VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) { + if ((CSR_READ_2(sc, VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) { /* We received a complete packet. */ - if ((inw(BASE + VX_STATUS) & S_INTR_LATCH) == 0) { + if ((CSR_READ_2(sc, VX_STATUS) & S_INTR_LATCH) == 0) { /* * No interrupt, read the packet and continue * Is this supposed to happen? Is my motherboard @@ -564,7 +519,7 @@ vxstatus(sc) * Check the FIFO status and act accordingly */ GO_WINDOW(4); - fifost = inw(BASE + VX_W4_FIFO_DIAG); + fifost = CSR_READ_2(sc, VX_W4_FIFO_DIAG); GO_WINDOW(1); if (fifost & FIFOS_RX_UNDERRUN) { @@ -606,8 +561,8 @@ vxtxstat(sc) * We need to read+write TX_STATUS until we get a 0 status * in order to turn off the interrupt flag. */ - while ((i = inb(BASE + VX_W1_TX_STATUS)) & TXS_COMPLETE) { - outb(BASE + VX_W1_TX_STATUS, 0x0); + while ((i = CSR_READ_1(sc, VX_W1_TX_STATUS)) & TXS_COMPLETE) { + CSR_WRITE_1(sc, VX_W1_TX_STATUS, 0x0); if (i & TXS_JABBER) { ++sc->arpcom.ac_if.if_oerrors; @@ -625,7 +580,7 @@ vxtxstat(sc) vxreset(sc); } else if (i & TXS_MAX_COLLISION) { ++sc->arpcom.ac_if.if_collisions; - outw(BASE + VX_COMMAND, TX_ENABLE); + CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE); sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; } else sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127; @@ -641,9 +596,9 @@ vxintr(voidsc) struct ifnet *ifp = &sc->arpcom.ac_if; for (;;) { - outw(BASE + VX_COMMAND, C_INTR_LATCH); + CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH); - status = inw(BASE + VX_STATUS); + status = CSR_READ_2(sc, VX_STATUS); if ((status & (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE | S_CARD_FAILURE)) == 0) @@ -655,7 +610,7 @@ vxintr(voidsc) * Due to the i386 interrupt queueing, we may get spurious * interrupts occasionally. */ - outw(BASE + VX_COMMAND, ACK_INTR | status); + CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | status); if (status & S_RX_COMPLETE) vxread(sc); @@ -690,7 +645,7 @@ vxread(sc) struct ether_header *eh; u_int len; - len = inw(BASE + VX_W1_RX_STATUS); + len = CSR_READ_2(sc, VX_W1_RX_STATUS); again: @@ -771,7 +726,7 @@ again: * I'll modify vxread() so that it can handle RX_EARLY interrupts. */ if (vxstatus(sc)) { - len = inw(BASE + VX_W1_RX_STATUS); + len = CSR_READ_2(sc, VX_W1_RX_STATUS); /* Check if we are stuck and reset [see XXX comment] */ if (len & ERR_INCOMPLETE) { if (ifp->if_flags & IFF_DEBUG) @@ -785,7 +740,7 @@ again: return; abort: - outw(BASE + VX_COMMAND, RX_DISCARD_TOP_PACK); + CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); } static struct mbuf * @@ -858,9 +813,11 @@ vxget(sc, totlen) } len = min(totlen, len); if (len > 3) - insl(BASE + VX_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), len / 4); + bus_space_read_multi_4(sc->vx_btag, sc->vx_bhandle, + VX_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), len / 4); if (len & 3) { - insb(BASE + VX_W1_RX_PIO_RD_1, mtod(m, u_int8_t *) + (len & ~3), + bus_space_read_multi_1(sc->vx_btag, sc->vx_bhandle, + VX_W1_RX_PIO_RD_1, mtod(m, u_int8_t *) + (len & ~3), len & 3); } m->m_len = len; @@ -869,7 +826,7 @@ vxget(sc, totlen) mp = &m->m_next; } - outw(BASE +VX_COMMAND, RX_DISCARD_TOP_PACK); + CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); splx(sh); @@ -883,7 +840,7 @@ vxioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct vx_softc *sc = vx_softc[ifp->if_unit]; + struct vx_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; @@ -969,7 +926,7 @@ static void vxwatchdog(ifp) struct ifnet *ifp; { - struct vx_softc *sc = vx_softc[ifp->if_unit]; + struct vx_softc *sc = ifp->if_softc; if (ifp->if_flags & IFF_DEBUG) printf("vx%d: device timeout\n", ifp->if_unit); @@ -986,20 +943,20 @@ vxstop(sc) ifp->if_timer = 0; - outw(BASE + VX_COMMAND, RX_DISABLE); - outw(BASE + VX_COMMAND, RX_DISCARD_TOP_PACK); + CSR_WRITE_2(sc, VX_COMMAND, RX_DISABLE); + CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); VX_BUSY_WAIT; - outw(BASE + VX_COMMAND, TX_DISABLE); - outw(BASE + VX_COMMAND, STOP_TRANSCEIVER); + CSR_WRITE_2(sc, VX_COMMAND, TX_DISABLE); + CSR_WRITE_2(sc, VX_COMMAND, STOP_TRANSCEIVER); DELAY(800); - outw(BASE + VX_COMMAND, RX_RESET); + CSR_WRITE_2(sc, VX_COMMAND, RX_RESET); VX_BUSY_WAIT; - outw(BASE + VX_COMMAND, TX_RESET); + CSR_WRITE_2(sc, VX_COMMAND, TX_RESET); VX_BUSY_WAIT; - outw(BASE + VX_COMMAND, C_INTR_LATCH); - outw(BASE + VX_COMMAND, SET_RD_0_MASK); - outw(BASE + VX_COMMAND, SET_INTR_MASK); - outw(BASE + VX_COMMAND, SET_RX_FILTER); + CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH); + CSR_WRITE_2(sc, VX_COMMAND, SET_RD_0_MASK); + CSR_WRITE_2(sc, VX_COMMAND, SET_INTR_MASK); + CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER); vxmbufempty(sc); } @@ -1011,7 +968,7 @@ vxbusyeeprom(sc) int j, i = 100; while (i--) { - j = inw(BASE + VX_W0_EEPROM_COMMAND); + j = CSR_READ_2(sc, VX_W0_EEPROM_COMMAND); if (j & EEPROM_BUSY) DELAY(100); else diff --git a/sys/dev/netif/vx/if_vx_eisa.c b/sys/dev/netif/vx/if_vx_eisa.c index 8a83942c0d..e5c2d96cec 100644 --- a/sys/dev/netif/vx/if_vx_eisa.c +++ b/sys/dev/netif/vx/if_vx_eisa.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/vx/if_vx_eisa.c,v 1.14 2000/01/29 14:50:31 peter Exp $ - * $DragonFly: src/sys/dev/netif/vx/if_vx_eisa.c,v 1.5 2003/11/20 22:07:32 dillon Exp $ + * $DragonFly: src/sys/dev/netif/vx/if_vx_eisa.c,v 1.6 2003/12/07 19:23:40 dillon Exp $ */ #include @@ -112,7 +112,6 @@ static int vx_eisa_attach(device_t dev) { struct vx_softc *sc; - int unit = device_get_unit(dev); struct resource *io = 0; struct resource *eisa_io = 0; struct resource *irq = 0; @@ -140,29 +139,32 @@ vx_eisa_attach(device_t dev) goto bad; } - if ((sc = vxalloc(unit)) == NULL) - goto bad; + sc = device_get_softc(dev); - sc->vx_io_addr = rman_get_start(io); + sc->vx_res = io; + sc->vx_bhandle = rman_get_bushandle(io); + sc->vx_btag = rman_get_bustag(io); rid = 0; irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); if (!irq) { device_printf(dev, "No irq?!\n"); - vxfree(sc); goto bad; } + sc->vx_irq = irq; + /* Now the registers are availible through the lower ioport */ vxattach(sc); if (bus_setup_intr(dev, irq, INTR_TYPE_NET, vxintr, sc, &ih)) { - vxfree(sc); goto bad; } + sc->vx_intrhand = ih; + return 0; bad: diff --git a/sys/dev/netif/vx/if_vx_pci.c b/sys/dev/netif/vx/if_vx_pci.c index 371cfbedc3..55e802000d 100644 --- a/sys/dev/netif/vx/if_vx_pci.c +++ b/sys/dev/netif/vx/if_vx_pci.c @@ -26,115 +26,154 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/vx/if_vx_pci.c,v 1.20 2000/01/29 14:50:32 peter Exp $ - * $DragonFly: src/sys/dev/netif/vx/if_vx_pci.c,v 1.4 2003/11/20 22:07:32 dillon Exp $ + * $FreeBSD: src/sys/dev/vx/if_vx_pci.c,v 1.21 2000/05/28 15:59:52 peter Exp $ + * $DragonFly: src/sys/dev/netif/vx/if_vx_pci.c,v 1.5 2003/12/07 19:23:40 dillon Exp $ */ -#include "use_vx.h" - #include #include -#include #include #include #include #include +#include +#include +#include +#include +#include + #include +#include #include "if_vxreg.h" -static void vx_pci_shutdown(void *, int); -static const char *vx_pci_probe(pcici_t, pcidi_t); -static void vx_pci_attach(pcici_t, int unit); +static void vx_pci_shutdown(device_t); +static int vx_pci_probe(device_t); +static int vx_pci_attach(device_t); + +static device_method_t vx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vx_pci_probe), + DEVMETHOD(device_attach, vx_pci_attach), + DEVMETHOD(device_shutdown, vx_pci_shutdown), + + { 0, 0 } +}; + +static driver_t vx_driver = { + "vx", + vx_methods, + sizeof(struct vx_softc) +}; + +static devclass_t vx_devclass; + +DRIVER_MODULE(if_vx, pci, vx_driver, vx_devclass, 0, 0); static void vx_pci_shutdown( - void *sc, - int howto) + device_t dev) { + struct vx_softc *sc; + + sc = device_get_softc(dev); vxstop(sc); - vxfree(sc); + return; } -static const char* +static int vx_pci_probe( - pcici_t config_id, - pcidi_t device_id) + device_t dev) { - if(device_id == 0x590010b7ul) - return "3COM 3C590 Etherlink III PCI"; + u_int32_t device_id; + + device_id = pci_read_config(dev, PCIR_DEVVENDOR, 4); + + if(device_id == 0x590010b7ul) { + device_set_desc(dev, "3COM 3C590 Etherlink III PCI"); + return(0); + } if(device_id == 0x595010b7ul || device_id == 0x595110b7ul || - device_id == 0x595210b7ul) - return "3COM 3C595 Fast Etherlink III PCI"; + device_id == 0x595210b7ul) { + device_set_desc(dev, "3COM 3C595 Etherlink III PCI"); + return(0); + } /* * The (Fast) Etherlink XL adapters are now supported by * the xl driver, which uses bus master DMA and is much * faster. (And which also supports the 3c905B. */ #ifdef VORTEX_ETHERLINK_XL - if(device_id == 0x900010b7ul || device_id == 0x900110b7ul) - return "3COM 3C900 Etherlink XL PCI"; - if(device_id == 0x905010b7ul || device_id == 0x905110b7ul) - return "3COM 3C905 Fast Etherlink XL PCI"; + if(device_id == 0x900010b7ul || device_id == 0x900110b7ul) { + device_set_desc(dev, "3COM 3C900 Etherlink XL PCI"); + return(0); + } + if(device_id == 0x905010b7ul || device_id == 0x905110b7ul) { + device_set_desc(dev, "3COM 3C905 Etherlink XL PCI"); + return(0); + } #endif - return NULL; + return (ENXIO); } -static void +static int vx_pci_attach( - pcici_t config_id, - int unit) + device_t dev) { struct vx_softc *sc; + int rid; - if (unit >= NVX) { - printf("vx%d: not configured; kernel is built for only %d device%s.\n", - unit, NVX, NVX == 1 ? "" : "s"); - return; - } + sc = device_get_softc(dev); - if ((sc = vxalloc(unit)) == NULL) { - return; - } + rid = PCIR_MAPS; + sc->vx_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + + if (sc->vx_res == NULL) + goto bad; + + sc->vx_btag = rman_get_bustag(sc->vx_res); + sc->vx_bhandle = rman_get_bushandle(sc->vx_res); - sc->vx_io_addr = pci_conf_read(config_id, 0x10) & 0xffffffe0; + rid = 0; + sc->vx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + + if (sc->vx_irq == NULL) + goto bad; + + if (bus_setup_intr(dev, sc->vx_irq, INTR_TYPE_NET, + vxintr, sc, &sc->vx_intrhand)) + goto bad; if (vxattach(sc) == 0) { - return; + goto bad; } /* defect check for 3C590 */ - if ((pci_conf_read(config_id, 0) >> 16) == 0x5900) { + if ((pci_read_config(dev, PCIR_DEVVENDOR, 4) >> 16) == 0x5900) { GO_WINDOW(0); if (vxbusyeeprom(sc)) - return; - outw(BASE + VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD | EEPROM_SOFT_INFO_2); + goto bad; + CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, + EEPROM_CMD_RD | EEPROM_SOFT_INFO_2); if (vxbusyeeprom(sc)) - return; - if (!(inw(BASE + VX_W0_EEPROM_DATA) & NO_RX_OVN_ANOMALY)) { + goto bad; + if (!(CSR_READ_2(sc, VX_W0_EEPROM_DATA) & NO_RX_OVN_ANOMALY)) { printf("Warning! Defective early revision adapter!\n"); } } - /* - * Add shutdown hook so that DMA is disabled prior to reboot. Not - * doing do could allow DMA to corrupt kernel memory during the - * reboot before the driver initializes. - */ - EVENTHANDLER_REGISTER(shutdown_post_sync, vx_pci_shutdown, sc, - SHUTDOWN_PRI_DEFAULT); + return(0); - pci_map_int(config_id, vxintr, (void *) sc, &net_imask); +bad: + if (sc->vx_intrhand != NULL) + bus_teardown_intr(dev, sc->vx_irq, sc->vx_intrhand); + if (sc->vx_res != NULL) + bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->vx_res); + if (sc->vx_irq != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vx_irq); + return(ENXIO); } - -static struct pci_device vxdevice = { - "vx", - vx_pci_probe, - vx_pci_attach, - &vx_count, - NULL -}; - -COMPAT_PCI_DRIVER (if_vx_pci, vxdevice); diff --git a/sys/dev/netif/vx/if_vxreg.h b/sys/dev/netif/vx/if_vxreg.h index b463b02f72..60f0500860 100644 --- a/sys/dev/netif/vx/if_vxreg.h +++ b/sys/dev/netif/vx/if_vxreg.h @@ -19,8 +19,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/vx/if_vxreg.h,v 1.5.6.1 2000/08/02 22:42:34 peter Exp $ - * $DragonFly: src/sys/dev/netif/vx/if_vxreg.h,v 1.3 2003/08/27 09:38:33 rob Exp $ + * $FreeBSD: src/sys/dev/vx/if_vxreg.h,v 1.6 2000/05/01 19:54:26 peter Exp $ + * $DragonFly: src/sys/dev/netif/vx/if_vxreg.h,v 1.4 2003/12/07 19:23:40 dillon Exp $ * October 2, 1994 @@ -54,7 +54,11 @@ struct vx_softc { struct arpcom arpcom; /* Ethernet common part */ int unit; /* unit number */ - u_int vx_io_addr; /* i/o bus address */ + bus_space_handle_t vx_bhandle; + bus_space_tag_t vx_btag; + void *vx_intrhand; + struct resource *vx_irq; + struct resource *vx_res; #define MAX_MBS 8 /* # of mbufs we keep around */ struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */ int next_mb; /* Which mbuf to use next. */ @@ -68,6 +72,20 @@ struct vx_softc { int buffill_pending; }; +#define CSR_WRITE_4(sc, reg, val) \ + bus_space_write_4(sc->vx_btag, sc->vx_bhandle, reg, val) +#define CSR_WRITE_2(sc, reg, val) \ + bus_space_write_2(sc->vx_btag, sc->vx_bhandle, reg, val) +#define CSR_WRITE_1(sc, reg, val) \ + bus_space_write_1(sc->vx_btag, sc->vx_bhandle, reg, val) + +#define CSR_READ_4(sc, reg) \ + bus_space_read_4(sc->vx_btag, sc->vx_bhandle, reg) +#define CSR_READ_2(sc, reg) \ + bus_space_read_2(sc->vx_btag, sc->vx_bhandle, reg) +#define CSR_READ_1(sc, reg) \ + bus_space_read_1(sc->vx_btag, sc->vx_bhandle, reg) + /* * Some global constants */ @@ -317,7 +335,7 @@ struct vx_softc { #define S_UPD_STATS (u_short) (0x80) #define S_COMMAND_IN_PROGRESS (u_short) (0x1000) -#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) +#define VX_BUSY_WAIT while (CSR_READ_2(sc, VX_STATUS) & S_COMMAND_IN_PROGRESS) /* Address Config. Register. * Window 0/Port 06 @@ -437,7 +455,7 @@ struct vx_softc { #define ENABLE_DRQ_IRQ 0x0001 #define MFG_ID 0x506d /* `TCM' */ #define PROD_ID 0x5090 -#define GO_WINDOW(x) outw(BASE+VX_COMMAND, WINDOW_SELECT|(x)) +#define GO_WINDOW(x) CSR_WRITE_2(sc, VX_COMMAND, WINDOW_SELECT|(x)) #define JABBER_GUARD_ENABLE 0x40 #define LINKBEAT_ENABLE 0x80 #define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE) -- 2.41.0