diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2000-10-17 15:47:13 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2000-10-17 15:47:13 +0000 |
commit | 553d0e61cf255f490b685bad14614b74b45e9c43 (patch) | |
tree | ea7c912c35de3d897c89cde90ad2f5551c536289 /sys/dev | |
parent | 41014f56a95c4c12dd1fa58b06cccabdda87baf9 (diff) |
update tx from freebsd sources based on patch from pr#1405
(dadams@sleethal.com), but local changes preserved and ifmedia ioctls
fixed; deraadt/aaron ok
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/files.pci | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_tx.c | 1550 | ||||
-rw-r--r-- | sys/dev/pci/if_txvar.h | 250 |
3 files changed, 807 insertions, 997 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 9fe134326c3..1c685c5d91f 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.84 2000/09/15 13:44:23 mickey Exp $ +# $OpenBSD: files.pci,v 1.85 2000/10/17 15:47:12 jason Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -211,7 +211,7 @@ attach dc at pci with dc_pci file dev/pci/if_dc_pci.c dc_pci # SMC EPIC, 83c170 -device tx: ether, ifnet, ifmedia +device tx: ether, ifnet, mii, ifmedia attach tx at pci file dev/pci/if_tx.c tx diff --git a/sys/dev/pci/if_tx.c b/sys/dev/pci/if_tx.c index a5ec0f7782e..3972637b47b 100644 --- a/sys/dev/pci/if_tx.c +++ b/sys/dev/pci/if_tx.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_tx.c,v 1.10 2000/02/21 20:54:04 jason Exp $ */ -/* $FreeBSD: src/sys/pci/if_tx.c,v 1.34 1999/12/21 11:14:10 eivind Exp $ */ +/* $OpenBSD: if_tx.c,v 1.11 2000/10/17 15:47:12 jason Exp $ */ +/* $FreeBSD: src/sys/pci/if_tx.c,v 1.40 2000/07/13 22:54:34 archie Exp $ */ /*- * Copyright (c) 1997 Semen Ustimenko (semen@iclub.nsu.ru) @@ -35,61 +35,69 @@ * * todo: * Implement FULL IFF_MULTICAST support. - * Test, test and test again:-( + * Refactor out Free/Open compat cruft + * Modularize, Modularize, and Modularize some more * */ /* We should define compile time options before if_txvar.h included */ -/*#define EPIC_NOIFMEDIA 1*/ -/*#define EPIC_USEIOSPACE 1*/ #define EARLY_RX 1 /*#define EPIC_DEBUG 1*/ -#if defined(EPIC_DEBUG) -#define dprintf(a) printf a -#else -#define dprintf(a) -#endif - -/* Macro to get either mbuf cluster or nothing */ -#define EPIC_MGETCLUSTER(m) \ - { MGETHDR((m),M_DONTWAIT,MT_DATA); \ - if (m) { \ - MCLGET((m),M_DONTWAIT); \ - if( 0 == ((m)->m_flags & M_EXT) ){ \ - m_freem(m); \ - (m) = NULL; \ - } \ - } \ - } - -#include "bpfilter.h" -#include "pci.h" - -#if NPCI > 0 #include <sys/param.h> #include <sys/systm.h> +#include <sys/sockio.h> #include <sys/mbuf.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/socket.h> -#include <sys/sockio.h> +#include <sys/queue.h> + +#if defined(__FreeBSD__) +#define NBPFILTER 1 + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_media.h> + +#include <net/bpf.h> + +#include <vm/vm.h> /* for vtophys */ +#include <vm/pmap.h> /* for vtophys */ +#include <machine/clock.h> /* for DELAY */ +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +#include "miibus_if.h" + +#include <pci/if_txvar.h> +#else /* __OpenBSD__ */ +#include "bpfilter.h" + +#include <sys/device.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> - -#if !defined(SIOCSIFMEDIA) || defined(EPIC_NOIFMEDIA) -#define EPIC_NOIFMEDIA 1 -#else #include <net/if_media.h> -#endif #ifdef INET #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/in_var.h> #include <netinet/ip.h> +#include <netinet/if_ether.h> #endif #ifdef IPX @@ -104,99 +112,77 @@ #if NBPFILTER > 0 #include <net/bpf.h> -#include <net/bpfdesc.h> #endif -#if defined(__OpenBSD__) -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/device.h> - -#include <netinet/if_ether.h> - #include <vm/vm.h> +#include <vm/pmap.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcidevs.h> #include <dev/pci/if_txvar.h> -#else /* __FreeBSD__ */ -#include <net/if_mib.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <machine/clock.h> - -#include <pci/pcivar.h> -#include <pci/if_txvar.h> #endif #if defined(__FreeBSD__) -#if __FreeBSD_version >= 300000 -#define EPIC_IFIOCTL_CMD_TYPE u_long -#else -#define EPIC_IFIOCTL_CMD_TYPE int +MODULE_DEPEND(tx, miibus, 1, 1, 1); #endif + +#if defined(__FreeBSD__) #define EPIC_INTR_RET_TYPE void #else /* __OpenBSD__ */ -#define EPIC_IFIOCTL_CMD_TYPE u_long #define EPIC_INTR_RET_TYPE int #endif -int epic_ifioctl __P((register struct ifnet *, EPIC_IFIOCTL_CMD_TYPE, caddr_t)); -EPIC_INTR_RET_TYPE epic_intr __P((void *)); -int epic_common_attach __P((epic_softc_t *)); -void epic_ifstart __P((struct ifnet *)); -void epic_ifwatchdog __P((struct ifnet *)); -int epic_init __P((epic_softc_t *)); -void epic_stop __P((epic_softc_t *)); -void epic_rx_done __P((epic_softc_t *)); -void epic_tx_done __P((epic_softc_t *)); -int epic_init_rings __P((epic_softc_t *)); -void epic_free_rings __P((epic_softc_t *)); -void epic_stop_activity __P((epic_softc_t *)); -void epic_start_activity __P((epic_softc_t *)); -void epic_set_rx_mode __P((epic_softc_t *)); -void epic_set_tx_mode __P((epic_softc_t *)); -void epic_set_mc_table __P((epic_softc_t *)); -void epic_set_media_speed __P((epic_softc_t *)); -void epic_init_phy __P((epic_softc_t *)); -void epic_dump_state __P((epic_softc_t *)); -int epic_autoneg __P((epic_softc_t *)); -int epic_read_eeprom __P((epic_softc_t *,u_int16_t)); -void epic_output_eepromw __P((epic_softc_t *, u_int16_t)); -u_int16_t epic_input_eepromw __P((epic_softc_t *)); -u_int8_t epic_eeprom_clock __P((epic_softc_t *,u_int8_t)); -void epic_write_eepromreg __P((epic_softc_t *,u_int8_t)); -u_int8_t epic_read_eepromreg __P((epic_softc_t *)); -u_int16_t epic_read_phy_register __P((epic_softc_t *, u_int16_t)); -void epic_write_phy_register __P((epic_softc_t *, u_int16_t, u_int16_t)); -#if 0 -void epic_dump_phy_regs __P((epic_softc_t *)); +#if defined(__FreeBSD__) +#define EPIC_MIIBUS_WRITEREG_RET_TYPE int +#else /* __OpenBSD__ */ +#define EPIC_MIIBUS_WRITEREG_RET_TYPE void #endif -#if !defined(EPIC_NOIFMEDIA) -int epic_ifmedia_change __P((struct ifnet *)); -void epic_ifmedia_status __P((struct ifnet *, struct ifmediareq *)); +#if defined(__FreeBSD__) +#define EPIC_STATIC static +#else /* __OpenBSD__ */ +#define EPIC_STATIC #endif -int epic_mtypes [] = { - IFM_ETHER | IFM_10_T, - IFM_ETHER | IFM_10_T | IFM_FDX, - IFM_ETHER | IFM_100_TX, - IFM_ETHER | IFM_100_TX | IFM_FDX, - IFM_ETHER | IFM_10_T | IFM_LOOP, - IFM_ETHER | IFM_10_T | IFM_FDX | IFM_LOOP, - IFM_ETHER | IFM_10_T | IFM_LOOP | IFM_FLAG1, - IFM_ETHER | IFM_100_TX | IFM_LOOP, - IFM_ETHER | IFM_100_TX | IFM_LOOP | IFM_FLAG1, - IFM_ETHER | IFM_100_TX | IFM_FDX | IFM_LOOP, - IFM_ETHER | IFM_AUTO -}; -#define EPIC_MTYPESNUM (sizeof(epic_mtypes) / sizeof(epic_mtypes[0])) - +EPIC_STATIC int epic_ifioctl __P((register struct ifnet *, u_long, caddr_t)); +EPIC_STATIC EPIC_INTR_RET_TYPE epic_intr __P((void *)); +EPIC_STATIC int epic_common_attach __P((epic_softc_t *)); +EPIC_STATIC void epic_ifstart __P((struct ifnet *)); +EPIC_STATIC void epic_ifwatchdog __P((struct ifnet *)); +EPIC_STATIC int epic_init __P((epic_softc_t *)); +EPIC_STATIC void epic_reset __P((epic_softc_t *)); +EPIC_STATIC void epic_stop __P((epic_softc_t *)); +EPIC_STATIC void epic_rx_done __P((epic_softc_t *)); +EPIC_STATIC void epic_tx_done __P((epic_softc_t *)); +EPIC_STATIC int epic_init_rings __P((epic_softc_t *)); +EPIC_STATIC void epic_free_rings __P((epic_softc_t *)); +EPIC_STATIC void epic_stop_activity __P((epic_softc_t *)); +EPIC_STATIC void epic_start_activity __P((epic_softc_t *)); +EPIC_STATIC void epic_set_rx_mode __P((epic_softc_t *)); +EPIC_STATIC void epic_set_tx_mode __P((epic_softc_t *)); +EPIC_STATIC void epic_set_mc_table __P((epic_softc_t *)); +EPIC_STATIC int epic_read_eeprom __P((epic_softc_t *,u_int16_t)); +EPIC_STATIC void epic_output_eepromw __P((epic_softc_t *, u_int16_t)); +EPIC_STATIC u_int16_t epic_input_eepromw __P((epic_softc_t *)); +EPIC_STATIC u_int8_t epic_eeprom_clock __P((epic_softc_t *,u_int8_t)); +EPIC_STATIC void epic_write_eepromreg __P((epic_softc_t *,u_int8_t)); +EPIC_STATIC u_int8_t epic_read_eepromreg __P((epic_softc_t *)); + +EPIC_STATIC int epic_read_phy_reg __P((epic_softc_t *, int, int)); +EPIC_STATIC void epic_write_phy_reg __P((epic_softc_t *, int, int, int)); + +EPIC_STATIC int epic_miibus_readreg __P((struct device*, int, int)); +EPIC_STATIC void epic_miibus_statchg __P((struct device *)); + +EPIC_STATIC EPIC_MIIBUS_WRITEREG_RET_TYPE epic_miibus_writereg __P((struct device*, int, int, int)); + +EPIC_STATIC int epic_ifmedia_upd __P((struct ifnet *)); +EPIC_STATIC void epic_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); /* ------------------------------------------------------------------------- OS-specific part @@ -205,9 +191,9 @@ int epic_mtypes [] = { #if defined(__OpenBSD__) /* -----------------------------OpenBSD------------------------------------- */ -int epic_openbsd_probe __P((struct device *,void *,void *)); -void epic_openbsd_attach __P((struct device *, struct device *, void *)); -void epic_shutdown __P((void *)); +EPIC_STATIC int epic_openbsd_probe __P((struct device *,void *,void *)); +EPIC_STATIC void epic_openbsd_attach __P((struct device *, struct device *, void *)); +EPIC_STATIC void epic_openbsd_shutdown __P((void *)); struct cfattach tx_ca = { sizeof(epic_softc_t), epic_openbsd_probe, epic_openbsd_attach @@ -217,7 +203,7 @@ struct cfdriver tx_cd = { }; /* Synopsis: Check if device id corresponds with SMC83C170 id. */ -int +EPIC_STATIC int epic_openbsd_probe( struct device *parent, void *match, @@ -227,13 +213,13 @@ epic_openbsd_probe( if( PCI_VENDOR(pa->pa_id) != SMC_VENDORID ) return 0; - if( PCI_PRODUCT(pa->pa_id) == CHIPID_83C170 ) + if( PCI_PRODUCT(pa->pa_id) == SMC_DEVICEID_83C170 ) return 1; return 0; } -void +EPIC_STATIC void epic_openbsd_attach( struct device *parent, struct device *self, @@ -247,25 +233,21 @@ epic_openbsd_attach( struct ifnet *ifp; bus_addr_t iobase; bus_size_t iosize; - int i; u_int32_t command; -#if !defined(EPIC_NOIFMEDIA) - int tmp; -#endif command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); - command |= PCI_COMMAND_IO_ENABLE | - PCI_COMMAND_MEM_ENABLE | + command |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; + pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); #ifdef EPIC_USEIOSPACE if (!(command & PCI_COMMAND_IO_ENABLE)) { - printf(": failed to enable memory mapping\n"); + printf(": failed to enable I/O ports\n"); return; } - if( pci_io_find(pc, pa->pa_tag, PCI_CBIO, &iobase, &iosize)) { + if( pci_io_find(pc, pa->pa_tag, PCI_BASEIO, &iobase, &iosize)) { printf(": can't find i/o space\n"); return; } @@ -279,7 +261,7 @@ epic_openbsd_attach( printf(": failed to enable memory mapping\n"); return; } - if( pci_mem_find(pc, pa->pa_tag, PCI_CBMA, &iobase, &iosize, NULL)) { + if( pci_mem_find(pc, pa->pa_tag, PCI_BASEMEM, &iobase, &iosize, NULL)) { printf(": can't find mem space\n"); return; } @@ -290,18 +272,25 @@ epic_openbsd_attach( sc->sc_st = pa->pa_memt; #endif + /* + * Set up if + */ ifp = &sc->sc_if; - bcopy(sc->sc_dev.dv_xname, ifp->if_xname,IFNAMSIZ); + bcopy(sc->dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = epic_ifioctl; ifp->if_start = epic_ifstart; ifp->if_watchdog = epic_ifwatchdog; - /* Do common attach procedure */ + /* + * Do common attach procedure + */ if( epic_common_attach(sc) ) return; - /* Map interrupt */ + /* + * Map interrupt + */ if( pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline, &ih)) { printf(": can't map interrupt\n"); @@ -320,59 +309,31 @@ epic_openbsd_attach( printf(": %s",intrstr); /* Display some info */ - printf(" address %s",ether_sprintf(sc->sc_macaddr)); - /* Read current media config and display it too */ - i = PHY_READ_2( sc, DP83840_BMCR ); -#if !defined(EPIC_NOIFMEDIA) - tmp = IFM_ETHER; -#endif - if( i & BMCR_AUTONEGOTIATION ){ - printf(", Auto-Neg "); - - /* To avoid bug in QS6612 read LPAR enstead of BMSR */ - i = PHY_READ_2( sc, DP83840_LPAR ); - if( i & (ANAR_100_TX|ANAR_100_TX_FD) ) printf("100Mbps"); - else printf("10Mbps"); - if( i & (ANAR_10_FD|ANAR_100_TX_FD) ) printf(" FD"); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_AUTO; -#endif - } else { -#if defined(EPIC_NOIFMEDIA) - ifp->if_flags |= IFF_LINK0; -#endif - if( i & BMCR_100MBPS ) { - printf(", 100Mbps"); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_100_TX; -#else - ifp->if_flags |= IFF_LINK2; -#endif - } else { - printf(", 10Mbps"); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_10_T; -#endif - } - if( i & BMCR_FULL_DUPLEX ) { - printf(" FD"); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_FDX; -#else - ifp->if_flags |= IFF_LINK1; -#endif - } - } + printf(" address %s\n",ether_sprintf(sc->sc_macaddr)); - /* Init ifmedia interface */ -#if !defined(EPIC_NOIFMEDIA) - ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status); + /* + * ifmedia setup + */ + ifmedia_init(&sc->miibus.mii_media, 0, epic_ifmedia_upd, epic_ifmedia_sts); - for (i=0; i<EPIC_MTYPESNUM; i++) - ifmedia_add(&sc->ifmedia,epic_mtypes[i],0,NULL); + /* + * mii setup + */ + sc->miibus.mii_ifp = ifp; + sc->miibus.mii_readreg = epic_miibus_readreg; + sc->miibus.mii_writereg = epic_miibus_writereg; + sc->miibus.mii_statchg = epic_miibus_statchg; + + mii_attach(self, &sc->miibus, 0xffffffff, MII_PHY_ANY, + MII_OFFSET_ANY, 0); + + if (LIST_FIRST(&sc->miibus.mii_phys) == NULL) { + ifmedia_add(&sc->miibus.mii_media, IFM_ETHER|IFM_NONE,0,NULL); + ifmedia_set(&sc->miibus.mii_media, IFM_ETHER|IFM_NONE); + } else { + ifmedia_set(&sc->miibus.mii_media, IFM_ETHER|IFM_AUTO); + } - ifmedia_set(&sc->ifmedia, tmp); -#endif /* Attach os interface and bpf */ if_attach(ifp); @@ -383,13 +344,14 @@ epic_openbsd_attach( #endif /* Set shutdown routine to stop DMA process */ - shutdownhook_establish(epic_shutdown, sc); - printf("\n"); + shutdownhook_establish(epic_openbsd_shutdown, sc); } -/* Simple call epic_stop() */ -void -epic_shutdown( +/* + * Simply call epic_stop() + */ +EPIC_STATIC void +epic_openbsd_shutdown( void *sc) { epic_stop(sc); @@ -398,66 +360,115 @@ epic_shutdown( #else /* __FreeBSD__ */ /* -----------------------------FreeBSD------------------------------------- */ -const char* epic_freebsd_probe __P((pcici_t, pcidi_t)); -void epic_freebsd_attach __P((pcici_t, int)); -void epic_shutdown __P((int, void *)); - -/* Global variables */ -u_long epic_pci_count; -struct pci_device txdevice = { - "tx", - epic_freebsd_probe, - epic_freebsd_attach, - &epic_pci_count, - NULL +EPIC_STATIC int epic_freebsd_probe __P((struct device*)); +EPIC_STATIC int epic_freebsd_attach __P((struct device*)); +EPIC_STATIC void epic_freebsd_shutdown __P((struct device*)); +EPIC_STATIC int epic_freebsd_detach __P((struct device*)); +EPIC_STATIC struct epic_type *epic_devtype __P((struct device*)); +EPIC_STATIC void epic_miibus_mediainit __P((struct device*)); + +EPIC_STATIC device_method_t epic_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, epic_freebsd_probe), + DEVMETHOD(device_attach, epic_freebsd_attach), + DEVMETHOD(device_detach, epic_freebsd_detach), + DEVMETHOD(device_shutdown, epic_freebsd_shutdown), + + /* bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, epic_miibus_readreg), + DEVMETHOD(miibus_writereg, epic_miibus_writereg), + DEVMETHOD(miibus_statchg, epic_miibus_statchg), + DEVMETHOD(miibus_mediainit, epic_miibus_mediainit), + + { 0, 0 } }; -/* Append this driver to pci drivers list */ -COMPAT_PCI_DRIVER (tx, txdevice); +EPIC_STATIC driver_t epic_driver = { + "tx", + epic_methods, + sizeof(epic_softc_t) +}; + +EPIC_STATIC devclass_t epic_devclass; + +DRIVER_MODULE(if_tx, pci, epic_driver, epic_devclass, 0, 0); +DRIVER_MODULE(miibus, tx, miibus_driver, miibus_devclass, 0, 0); -/* Synopsis: Check if device id corresponds with SMC83C170 id. */ -const char* -epic_freebsd_probe( - pcici_t config_id, - pcidi_t device_id) +EPIC_STATIC struct epic_type epic_devs[] = { + { SMC_VENDORID, SMC_DEVICEID_83C170, + "SMC EtherPower II 10/100" }, + { 0, 0, NULL } +}; + +EPIC_STATIC int +epic_freebsd_probe(dev) + struct device* dev; { - if( PCI_VENDORID(device_id) != SMC_VENDORID ) - return NULL; + struct epic_type *t; - if( PCI_CHIPID(device_id) == CHIPID_83C170 ) - return "SMC 83c170"; + t = epic_devtype(dev); + + if (t != NULL) { + device_set_desc(dev, t->name); + return(0); + } - return NULL; + return(ENXIO); } +EPIC_STATIC struct epic_type * +epic_devtype(dev) + struct device* dev; +{ + struct epic_type *t; + + t = epic_devs; + + while(t->name != NULL) { + if ((pci_get_vendor(dev) == t->ven_id) && + (pci_get_device(dev) == t->dev_id)) { + return(t); + } + t++; + } + return (NULL); +} + +#if defined(EPIC_USEIOSPACE) +#define EPIC_RES SYS_RES_IOPORT +#define EPIC_RID PCIR_BASEIO +#else +#define EPIC_RES SYS_RES_MEMORY +#define EPIC_RID PCIR_BASEMEM +#endif + /* * Do FreeBSD-specific attach routine, like map registers, alloc softc * structure and etc. */ -void -epic_freebsd_attach( - pcici_t config_id, - int unit) +EPIC_STATIC int +epic_freebsd_attach(dev) + struct device* dev; { struct ifnet *ifp; epic_softc_t *sc; -#if defined(EPIC_USEIOSPACE) - u_int32_t iobase; -#else - caddr_t pmembase; -#endif u_int32_t command; - int i,s,tmp; + int unit, error; + int i, s, rid, tmp; - printf("tx%d",unit); + s = splimp (); - /* Allocate memory for softc, hardware descriptors and frag lists */ - sc = (epic_softc_t *) malloc( sizeof(epic_softc_t), M_DEVBUF, M_NOWAIT); - if (sc == NULL) return; + sc = device_get_softc(dev); + unit = device_get_unit(dev); /* Preinitialize softc structure */ bzero(sc, sizeof(epic_softc_t)); sc->unit = unit; + sc->dev = dev; /* Fill ifnet structure */ ifp = &sc->sc_if; @@ -466,61 +477,94 @@ epic_freebsd_attach( ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST; ifp->if_ioctl = epic_ifioctl; + ifp->if_output = ether_output; ifp->if_start = epic_ifstart; ifp->if_watchdog = epic_ifwatchdog; ifp->if_init = (if_init_f_t*)epic_init; ifp->if_timer = 0; - ifp->if_output = ether_output; - ifp->if_snd.ifq_maxlen = TX_RING_SIZE; + ifp->if_baudrate = 10000000; + ifp->if_snd.ifq_maxlen = TX_RING_SIZE - 1; + + /* Enable ports, memory and busmastering */ + command = pci_read_config(dev, PCIR_COMMAND, 4); + command |= PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN; + pci_write_config(dev, PCIR_COMMAND, command, 4); + command = pci_read_config(dev, PCIR_COMMAND, 4); - /* Get iobase or membase */ #if defined(EPIC_USEIOSPACE) - command = PCI_CONF_READ(PCI_CFCS); - command |= PCI_CFCS_IOEN; - PCI_CONF_WRITE(PCI_CFCS, command); - command = PCI_CONF_READ(PCI_CFCS); - - if (!(command & PCI_CFCS_IOEN)) { - printf(": failed to enable memory mapping!\n"); - free(sc, M_DEVBUF); - return; + if (!(command & PCIM_CMD_PORTEN)) { + device_printf(dev, "failed to enable I/O mapping!\n"); + error = ENXIO; + goto fail; + } +#else + if (!(command & PCIM_CMD_MEMEN)) { + device_printf(dev, "failed to enable memory mapping!\n"); + error = ENXIO; + goto fail; } +#endif - if (!pci_map_port(config_id, PCI_CBIO,(u_short *) &(sc->iobase))) { - printf(": cannot map port\n"); - free(sc, M_DEVBUF); - return; + rid = EPIC_RID; + sc->res = bus_alloc_resource(dev, EPIC_RES, &rid, 0, ~0, 1, + RF_ACTIVE); + + if (sc->res == NULL) { + device_printf(dev, "couldn't map ports/memory\n"); + error = ENXIO; + goto fail; } -#else - command = PCI_CONF_READ(PCI_CFCS); - command |= PCI_CFCS_MAEN; - PCI_CONF_WRITE(PCI_CFCS, command); - command = PCI_CONF_READ(PCI_CFCS); - - if (!(command & PCI_CFCS_MAEN)) { - printf(": failed to enable memory mapping!\n"); - free(sc, M_DEVBUF); - return; + + sc->sc_st = rman_get_bustag(sc->res); + sc->sc_sh = rman_get_bushandle(sc->res); + + /* Allocate interrupt */ + rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + + if (sc->irq == NULL) { + device_printf(dev, "couldn't map interrupt\n"); + bus_release_resource(dev, EPIC_RES, EPIC_RID, sc->res); + error = ENXIO; + goto fail; } - if (!pci_map_mem(config_id, PCI_CBMA,(vm_offset_t *) &(sc->csr),(vm_offset_t *) &pmembase)) { - printf(": cannot map memory\n"); - free(sc, M_DEVBUF); - return; + error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, + epic_intr, sc, &sc->sc_ih); + + if (error) { + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, EPIC_RES, EPIC_RID, sc->res); + device_printf(dev, "couldn't set up irq\n"); + goto fail; } -#endif - /* Do OS independent part, including chip wakeup and reset */ - if( epic_common_attach(sc) ) return; + /* + * Do ifmedia setup. + */ + if (mii_phy_probe(dev, &sc->miibus, + epic_ifmedia_upd, epic_ifmedia_sts)) { + device_printf(dev, "MII without any PHY!?\n"); + bus_teardown_intr(dev, sc->irq, sc->sc_ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, EPIC_RES, EPIC_RID, sc->res); + error = ENXIO; + goto fail; + } - command = PCI_CONF_READ(PCI_CFCS); - command |= PCI_CFCS_BMEN; - PCI_CONF_WRITE(PCI_CFCS, command); + /* Do OS independent part, including chip wakeup and reset */ + if (epic_common_attach(sc)) { + device_printf(dev, "memory distribution error\n"); + bus_teardown_intr(dev, sc->irq, sc->sc_ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, EPIC_RES, EPIC_RID, sc->res); + error = ENXIO; + goto fail; + } /* Display ethernet address ,... */ - printf(": address %02x:%02x:%02x:%02x:%02x:%02x,", - sc->sc_macaddr[0],sc->sc_macaddr[1],sc->sc_macaddr[2], - sc->sc_macaddr[3],sc->sc_macaddr[4],sc->sc_macaddr[5]); + device_printf(dev, "address %6D,", sc->sc_macaddr, ":"); /* board type and ... */ printf(" type "); @@ -532,112 +576,114 @@ epic_freebsd_attach( if( ' ' == (u_int8_t)tmp ) break; printf("%c",(u_int8_t)tmp); } + printf ("\n"); - /* Read current media config and display it too */ - i = PHY_READ_2( sc, DP83840_BMCR ); -#if !defined(EPIC_NOIFMEDIA) - tmp = IFM_ETHER; -#endif - if( i & BMCR_AUTONEGOTIATION ){ - printf(", Auto-Neg "); - - /* To avoid bug in QS6612 read LPAR enstead of BMSR */ - i = PHY_READ_2( sc, DP83840_LPAR ); - if( i & (ANAR_100_TX|ANAR_100_TX_FD) ) printf("100Mbps "); - else printf("10Mbps "); - if( i & (ANAR_10_FD|ANAR_100_TX_FD) ) printf("FD"); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_AUTO; -#endif - } else { -#if defined(EPIC_NOIFMEDIA) - ifp->if_flags |= IFF_LINK0; -#endif - if( i & BMCR_100MBPS ) { - printf(", 100Mbps "); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_100_TX; -#else - ifp->if_flags |= IFF_LINK2; -#endif - } else { - printf(", 10Mbps "); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_10_T; -#endif - } - if( i & BMCR_FULL_DUPLEX ) { - printf("FD"); -#if !defined(EPIC_NOIFMEDIA) - tmp |= IFM_FDX; -#else - ifp->if_flags |= IFF_LINK1; -#endif - } - } + /* Attach to OS's managers */ + ether_ifattach(ifp, ETHER_BPF_SUPPORTED); + callout_handle_init(&sc->stat_ch); - /* Init ifmedia interface */ -#if !defined(EPIC_NOIFMEDIA) - ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status); +fail: + splx(s); - for (i=0; i<EPIC_MTYPESNUM; i++) - ifmedia_add(&sc->ifmedia,epic_mtypes[i],0,NULL); + return(error); +} - ifmedia_set(&sc->ifmedia, tmp); -#endif +/* + * Detach driver and free resources + */ +EPIC_STATIC int +epic_freebsd_detach(dev) + struct device* dev; +{ + struct ifnet *ifp; + epic_softc_t *sc; + int s; s = splimp(); - /* Map interrupt */ - if( !pci_map_int(config_id, epic_intr, (void*)sc, &net_imask) ) { - printf(": couldn't map interrupt\n"); - free(sc, M_DEVBUF); - return; - } + sc = device_get_softc(dev); + ifp = &sc->arpcom.ac_if; - /* Set shut down routine to stop DMA processes on reboot */ - at_shutdown(epic_shutdown, sc, SHUTDOWN_POST_SYNC); + ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); - /* Attach to if manager */ - if_attach(ifp); - ether_ifattach(ifp); + epic_stop(sc); -#if NBPFILTER > 0 - bpfattach(ifp,DLT_EN10MB, sizeof(struct ether_header)); -#endif + bus_generic_detach(dev); + device_delete_child(dev, sc->miibus); + + bus_teardown_intr(dev, sc->irq, sc->sc_ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, EPIC_RES, EPIC_RID, sc->res); + + free(sc->pool, M_DEVBUF); splx(s); - printf("\n"); + return(0); +} + +#undef EPIC_RES +#undef EPIC_RID + +/* + * + */ +EPIC_STATIC void epic_miibus_mediainit(dev) + struct device* dev; +{ + epic_softc_t *sc; + struct mii_data *mii; + struct ifmedia *ifm; + int media; + + sc = epic_dev_ptr(dev); + mii = epic_mii_ptr(sc); + ifm = &mii->mii_media; + + if(CSR_READ_4(sc, MIICFG) & MIICFG_PHY_PRESENT) { + media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, mii->mii_instance); + printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc)); + ifmedia_add(ifm, media, 0, NULL); + } return; } - -void -epic_shutdown( - int howto, - void *sc) +/* + * Stop all chip I/O so that the kernel's probe routines don't + * get confused by errant DMAs when rebooting. + */ +EPIC_STATIC void +epic_freebsd_shutdown(dev) + struct device* dev; { + epic_softc_t *sc; + + sc = device_get_softc(dev); + epic_stop(sc); -} + return; +} #endif /* __OpenBSD__ */ /* ------------------------------------------------------------------------ - OS-independing part + OS-independent part ------------------------------------------------------------------------ */ /* * This is if_ioctl handler. + * This is a mess */ -int -epic_ifioctl __P(( - register struct ifnet * ifp, - EPIC_IFIOCTL_CMD_TYPE command, - caddr_t data)) +EPIC_STATIC int +epic_ifioctl(ifp, command, data) + struct ifnet *ifp; + u_long command; + caddr_t data; { epic_softc_t *sc = ifp->if_softc; int x, error = 0; + struct mii_data *mii; + struct ifreq *ifr = (struct ifreq *) data; x = splimp(); @@ -660,7 +706,7 @@ epic_ifioctl __P(( epic_init(sc); arp_ifinit(&sc->arpcom,ifa); break; -#endif /* __FreeBSD__ */ +#endif #if NS case AF_NS: { register struct ns_addr * ina = &IA_SNS(ifa)->sns_addr; @@ -683,7 +729,7 @@ epic_ifioctl __P(( break; } } -#endif +#endif /* __FreeBSD__ */ case SIOCSIFFLAGS: /* @@ -702,15 +748,9 @@ epic_ifioctl __P(( } } - epic_stop_activity(sc); - /* Handle IFF_PROMISC flag */ + epic_stop_activity(sc); epic_set_rx_mode(sc); - -#if defined(EPIC_NOIFMEDIA) - /* Handle IFF_LINKx flags */ - epic_set_media_speed(sc); -#endif epic_start_activity(sc); break; @@ -732,13 +772,11 @@ epic_ifioctl __P(( #endif break; -#if !defined(EPIC_NOIFMEDIA) case SIOCSIFMEDIA: case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, (struct ifreq *)data, - &sc->ifmedia, command); + mii = epic_mii_ptr(sc); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; -#endif default: error = EINVAL; @@ -750,19 +788,22 @@ epic_ifioctl __P(( /* * OS-independed part of attach process. allocate memory for descriptors - * and frag lists, wake up chip, read MAC address and PHY identyfier. + * and frag lists, wake up chip, and read MAC address. * Return -1 on failure. */ -int -epic_common_attach( - epic_softc_t *sc) +EPIC_STATIC int +epic_common_attach(sc) + epic_softc_t *sc; { int i; caddr_t pool; + /* + * Allocate memory for io buffers + */ i = sizeof(struct epic_frag_list)*TX_RING_SIZE + sizeof(struct epic_rx_desc)*RX_RING_SIZE + - sizeof(struct epic_tx_desc)*TX_RING_SIZE + PAGE_SIZE, + sizeof(struct epic_tx_desc)*TX_RING_SIZE + PAGE_SIZE; sc->pool = (epic_softc_t *) malloc( i, M_DEVBUF, M_NOWAIT); if (sc->pool == NULL) { @@ -771,33 +812,35 @@ epic_common_attach( } bzero(sc->pool, i); - /* Align pool on PAGE_SIZE */ + /* + * Align pool on PAGE_SIZE + */ pool = (caddr_t)sc->pool; pool = (caddr_t)((u_int32_t)(pool + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); - /* Distribute memory */ + /* + * Distribute memory + */ sc->tx_flist = (void *)pool; pool += sizeof(struct epic_frag_list)*TX_RING_SIZE; sc->rx_desc = (void *)pool; pool += sizeof(struct epic_rx_desc)*RX_RING_SIZE; sc->tx_desc = (void *)pool; - /* Bring the chip out of low-power mode. */ - CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET); - - /* Workaround for Application Note 7-15 */ - for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST); + /* + * reset the chip + */ + epic_reset( sc ); - /* Read mac address from EEPROM */ + /* + * Read mac address from EEPROM + */ for (i = 0; i < ETHER_ADDR_LEN / sizeof(u_int16_t); i++) ((u_int16_t *)sc->sc_macaddr)[i] = epic_read_eeprom(sc,i); - /* Identify PHY */ - sc->phyid = PHY_READ_2(sc, DP83840_PHYIDR1 )<<6; - sc->phyid|= (PHY_READ_2( sc, DP83840_PHYIDR2 )>>10)&0x3F; - if( QS6612_OUI != sc->phyid ) - printf(": WARNING! PHY unknown (0x%x)",sc->phyid); - + /* + * Set defaults + */ sc->tx_threshold = TRANSMIT_THRESHOLD; sc->txcon = TXCON_DEFAULT; @@ -809,8 +852,10 @@ epic_common_attach( * and quque them for transmit, one by one, until TX ring become full * or quque become empty. */ -void -epic_ifstart(struct ifnet * const ifp){ +EPIC_STATIC void +epic_ifstart(ifp) + struct ifnet * ifp; +{ epic_softc_t *sc = ifp->if_softc; struct epic_tx_buffer *buf; struct epic_tx_desc *desc; @@ -819,20 +864,6 @@ epic_ifstart(struct ifnet * const ifp){ register struct mbuf *m; register int i; -#if 0 - /* If no link is established, simply free all mbufs in queue */ - PHY_READ_2( sc, DP83840_BMSR ); - if( !(BMSR_LINK_STATUS & PHY_READ_2( sc, DP83840_BMSR )) ){ - IF_DEQUEUE( &ifp->if_snd, m0 ); - while( m0 ) { - m_freem(m0); - IF_DEQUEUE( &ifp->if_snd, m0 ); - } - return; - } -#endif - - /* Link is OK, queue packets to NIC */ while( sc->pending_txs < TX_RING_SIZE ){ buf = sc->tx_buffer + sc->cur_tx; desc = sc->tx_desc + sc->cur_tx; @@ -844,17 +875,6 @@ epic_ifstart(struct ifnet * const ifp){ /* If nothing to send, return */ if( NULL == m0 ) return; - /* If descriptor is busy, set IFF_OACTIVE and exit */ - if( desc->status & 0x8000 ) { - dprintf((EPIC_FORMAT ": desc is busy in ifstart, up and down interface please\n",EPIC_ARGS(sc))); - break; - } - - if( buf->mbuf ) { - dprintf((EPIC_FORMAT ": mbuf not freed in ifstart, up and down interface please\n",EPIC_ARGS(sc))); - break; - } - /* Fill fragments list */ for( m=m0, i=0; (NULL != m) && (i < EPIC_MAX_FRAGS); @@ -900,11 +920,7 @@ epic_ifstart(struct ifnet * const ifp){ #if NBPFILTER > 0 if( ifp->if_bpf ) -#if defined(__FreeBSD__) - bpf_mtap( ifp, m0 ); -#else /* __OpenBSD__ */ - bpf_mtap( ifp->if_bpf, m0 ); -#endif /* __FreeBSD__ */ + bpf_mtap( EPIC_BPFTAP_ARG(ifp), m0 ); #endif } @@ -915,12 +931,11 @@ epic_ifstart(struct ifnet * const ifp){ } /* - * - * splimp() invoked before epic_intr_normal() + * Synopsis: Finish all received frames. */ -void -epic_rx_done __P(( - epic_softc_t *sc )) +EPIC_STATIC void +epic_rx_done(sc) + epic_softc_t *sc; { u_int16_t len; struct epic_rx_buffer *buf; @@ -968,15 +983,13 @@ epic_rx_done __P(( m->m_pkthdr.rcvif = &(sc->sc_if); m->m_pkthdr.len = m->m_len = len; +#if !defined(__FreeBSD__) #if NBPFILTER > 0 /* Give mbuf to BPFILTER */ if( sc->sc_if.if_bpf ) -#if defined(__FreeBSD__) - bpf_mtap( &sc->sc_if, m ); -#else /* __OpenBSD__ */ - bpf_mtap( sc->sc_if.if_bpf, m ); -#endif /* __FreeBSD__ */ + bpf_mtap( EPIC_BPFTAP_ARG(&sc->sc_if), m ); #endif /* NBPFILTER > 0 */ +#endif /* !__FreeBSD__ */ /* Second mbuf holds packet ifself */ m->m_pkthdr.len = m->m_len = len - sizeof(struct ether_header); @@ -998,9 +1011,9 @@ epic_rx_done __P(( * packet, switch to next descriptor and repeat until no packets * are pending or descriptor is not transmitted yet. */ -void -epic_tx_done __P(( - register epic_softc_t *sc )) +EPIC_STATIC void +epic_tx_done(sc) + epic_softc_t *sc; { struct epic_tx_buffer *buf; struct epic_tx_desc *desc; @@ -1038,12 +1051,11 @@ epic_tx_done __P(( /* * Interrupt function - * - * splimp() assumed to be done + * This is a mess */ -EPIC_INTR_RET_TYPE -epic_intr ( - void *arg) +EPIC_STATIC EPIC_INTR_RET_TYPE +epic_intr(arg) + void *arg; { epic_softc_t * sc = (epic_softc_t *) arg; int status,i=4; @@ -1051,7 +1063,6 @@ epic_intr ( int claimed = 0; #endif - while( i-- && ((status = CSR_READ_4(sc, INTSTAT)) & INTSTAT_INT_ACTV) ){ #if defined(__OpenBSD__) claimed = 1; @@ -1066,8 +1077,6 @@ epic_intr ( printf(EPIC_FORMAT ": RX buffer overflow\n",EPIC_ARGS(sc)); if( status & INTSTAT_RQE ) printf(EPIC_FORMAT ": RX FIFO overflow\n",EPIC_ARGS(sc)); - if( sc->sc_if.if_flags & IFF_DEBUG ) - epic_dump_state(sc); #endif if( !(CSR_READ_4( sc, COMMAND ) & COMMAND_RXQUEUED) ) CSR_WRITE_4( sc, COMMAND, COMMAND_RXQUEUED ); @@ -1082,46 +1091,6 @@ epic_intr ( epic_ifstart( &sc->sc_if ); } - if( (status & INTSTAT_GP2) && (QS6612_OUI == sc->phyid) ) { - u_int32_t phystatus = PHY_READ_2( sc, QS6612_INTSTAT ); - - if( phystatus & INTSTAT_AN_COMPLETE ) { - u_int32_t bmcr; - if( epic_autoneg(sc) == EPIC_FULL_DUPLEX ) { - dprintf((EPIC_FORMAT ": going fullduplex\n",EPIC_ARGS(sc))); - bmcr = BMCR_FULL_DUPLEX | PHY_READ_2( sc, DP83840_BMCR ); - sc->txcon |= TXCON_FULL_DUPLEX; - } else { - /* Default to half-duplex */ - dprintf((EPIC_FORMAT ": going halfduplex\n",EPIC_ARGS(sc))); - bmcr = ~BMCR_FULL_DUPLEX & PHY_READ_2( sc, DP83840_BMCR ); - sc->txcon &= ~TXCON_FULL_DUPLEX; - } - - /* There is apparently QS6612 chip bug: */ - /* BMCR_FULL_DUPLEX flag is not updated by */ - /* autonegotiation process, so update it by hands */ - /* so we can rely on it in epic_ifmedia_status() */ - PHY_WRITE_2( sc, DP83840_BMCR, bmcr ); - - epic_stop_activity(sc); - epic_set_tx_mode(sc); - epic_start_activity(sc); - } - - PHY_READ_2(sc, DP83840_BMSR); - if( !(PHY_READ_2(sc, DP83840_BMSR) & BMSR_LINK_STATUS) ) { - dprintf((EPIC_FORMAT ": WARNING! link down\n",EPIC_ARGS(sc))); - sc->flags |= EPIC_LINK_DOWN; - } else { - dprintf((EPIC_FORMAT ": link up\n",EPIC_ARGS(sc))); - sc->flags &= ~EPIC_LINK_DOWN; - } - - /* We should clear GP2 int again after we clear it on PHY */ - CSR_WRITE_4( sc, INTSTAT, INTSTAT_GP2 ); - } - /* Check for errors */ if( status & (INTSTAT_FATAL|INTSTAT_PMA|INTSTAT_PTA| INTSTAT_APE|INTSTAT_DPE|INTSTAT_TXU|INTSTAT_RXE) ){ @@ -1135,8 +1104,6 @@ epic_intr ( (status&INTSTAT_DPE)?" DPE":"" ); - epic_dump_state(sc); - epic_stop(sc); epic_init(sc); @@ -1180,12 +1147,10 @@ epic_intr ( * Synopsis: This one is called if packets wasn't transmitted * during timeout. Try to deallocate transmitted packets, and * if success continue to work. - * - * splimp() invoked here */ -void -epic_ifwatchdog __P(( - struct ifnet *ifp)) +EPIC_STATIC void +epic_ifwatchdog(ifp) + struct ifnet *ifp; { epic_softc_t *sc = ifp->if_softc; int x; @@ -1200,9 +1165,7 @@ epic_ifwatchdog __P(( /* If not successful */ if( sc->pending_txs > 0 ){ -#if defined(EPIC_DEBUG) - if( ifp->if_flags & IFF_DEBUG ) epic_dump_state(sc); -#endif + ifp->if_oerrors+=sc->pending_txs; /* Reinitialize board */ @@ -1219,77 +1182,166 @@ epic_ifwatchdog __P(( splx(x); } -#if defined(SIOCSIFMEDIA) && !defined(EPIC_NOIFMEDIA) -int -epic_ifmedia_change __P(( - struct ifnet * ifp)) +/* + * Set media options. + */ +EPIC_STATIC int +epic_ifmedia_upd(ifp) + struct ifnet *ifp; { - epic_softc_t *sc = (epic_softc_t *)(ifp->if_softc); + epic_softc_t *sc; + struct mii_data *mii; + struct ifmedia *ifm; + + sc = ifp->if_softc; + + mii = epic_mii_ptr(sc); - if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER) - return (EINVAL); + ifm = &mii->mii_media; - if (!(ifp->if_flags & IFF_UP)) + /* Do not do anything if interface is not up */ + if(!(ifp->if_flags & IFF_UP)) return (0); - epic_stop_activity(sc); - epic_set_media_speed(sc); - epic_start_activity(sc); + if((IFM_INST(ifm->ifm_cur->ifm_media) == mii->mii_instance) && + (IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_10_2)) { + /* Call this, to isolate (and powerdown ?) all PHYs */ + mii_mediachg(mii); - return 0; + /* Select BNC */ + CSR_WRITE_4(sc, MIICFG, MIICFG_SERIAL_ENABLE | + MIICFG_694_ENABLE | MIICFG_SMI_ENABLE); + + /* Update txcon register */ + epic_miibus_statchg(&sc->dev); + + return (0); + } else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) { + /* Select MII */ + CSR_WRITE_4(sc, MIICFG, MIICFG_SMI_ENABLE); + + /* Give it to miibus... */ + mii_mediachg(mii); + + return (0); + } + + return(EINVAL); } -void -epic_ifmedia_status __P(( - struct ifnet * ifp, - struct ifmediareq *ifmr)) +/* + * Report current media status. + */ +EPIC_STATIC void +epic_ifmedia_sts(ifp, ifmr) + struct ifnet *ifp; + struct ifmediareq *ifmr; { - epic_softc_t *sc = ifp->if_softc; - u_int32_t bmcr; - u_int32_t bmsr; + epic_softc_t *sc; + struct mii_data *mii; + struct ifmedia *ifm; + + sc = ifp->if_softc; + mii = epic_mii_ptr(sc); + ifm = &mii->mii_media; + + if(!(ifp->if_flags & IFF_UP)) { + ifmr->ifm_active = IFM_NONE; + ifmr->ifm_status = 0; - if (!(ifp->if_flags & IFF_UP)) return; + } - bmcr = PHY_READ_2( sc, DP83840_BMCR ); + if((IFM_INST(ifm->ifm_cur->ifm_media) == mii->mii_instance) && + (IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_10_2)) { + ifmr->ifm_active = ifm->ifm_cur->ifm_media; + ifmr->ifm_status = 0; + } else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) { + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; + } else { + ifmr->ifm_active = IFM_NONE; + ifmr->ifm_status = 0; + } - PHY_READ_2( sc, DP83840_BMSR ); - bmsr = PHY_READ_2( sc, DP83840_BMSR ); + return; +} - ifmr->ifm_active = IFM_ETHER; - ifmr->ifm_status = IFM_AVALID; +/* + * Callback routine, called on media change. + */ +EPIC_STATIC void +epic_miibus_statchg(dev) + struct device* dev; +{ + epic_softc_t *sc; + struct mii_data *mii; - if( !(bmsr & BMSR_LINK_STATUS) ) { - ifmr->ifm_active |= - (bmcr&BMCR_AUTONEGOTIATION)?IFM_AUTO:IFM_NONE; - return; - } + sc = epic_dev_ptr(dev); + mii = epic_mii_ptr(sc); + + sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX); + + /* + * If we are in full-duplex mode or loopback operation, + * we need to decouple receiver and transmitter. + */ + if (mii->mii_media_active & (IFM_FDX | IFM_LOOP)) + sc->txcon |= TXCON_FULL_DUPLEX; + + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) + sc->sc_if.if_baudrate = 100000000; + else + sc->sc_if.if_baudrate = 10000000; + + epic_set_tx_mode(sc); + + return; +} - ifmr->ifm_status |= IFM_ACTIVE; - ifmr->ifm_active |= (bmcr & BMCR_100MBPS) ? IFM_100_TX : IFM_10_T; - ifmr->ifm_active |= (bmcr & BMCR_FULL_DUPLEX) ? IFM_FDX : 0; - if ((sc->txcon & TXCON_LOOPBACK_MODE) == TXCON_LOOPBACK_MODE_INT) - ifmr->ifm_active |= (IFM_LOOP | IFM_FLAG1); - else if ((sc->txcon & TXCON_LOOPBACK_MODE) == TXCON_LOOPBACK_MODE_PHY) - ifmr->ifm_active |= IFM_LOOP; +#if defined(__FreeBSD__) +EPIC_STATIC void epic_miibus_mediainit(dev) + struct device* dev; +{ + epic_softc_t *sc; + struct mii_data *mii; + struct ifmedia *ifm; + int media; + + sc = epic_dev_ptr(dev); + mii = epic_mii_ptr(sc); + ifm = &mii->mii_media; + + if(CSR_READ_4(sc, MIICFG) & MIICFG_PHY_PRESENT) { + media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, mii->mii_instance); + printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc)); + ifmedia_add(ifm, media, 0, NULL); + } + return; } #endif /* - * Reset chip, PHY, allocate rings - * - * splimp() invoked here + * Reset chip, allocate rings, and update media. */ -int -epic_init __P(( - epic_softc_t * sc)) +EPIC_STATIC int +epic_init(sc) + epic_softc_t *sc; { struct ifnet *ifp = &sc->sc_if; - int s,i; + struct mii_data *mii; + int s; s = splimp(); + /* If interface is already running, then we need not do anything */ + if (ifp->if_flags & IFF_RUNNING) { + splx(s); + return 0; + } +#ifdef __reset /* Soft reset the chip (we have to power up card before) */ CSR_WRITE_4( sc, GENCTL, 0 ); CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET ); @@ -1305,6 +1357,8 @@ epic_init __P(( /* Workaround for Application Note 7-15 */ for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST); +#endif + epic_reset( sc ); /* Initialize rings */ if( epic_init_rings( sc ) ) { @@ -1335,17 +1389,13 @@ epic_init __P(( CSR_WRITE_4( sc, INTMASK, INTSTAT_RCC | INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE | INTSTAT_TXC | INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU | - INTSTAT_FATAL | - ((QS6612_OUI == sc->phyid)?INTSTAT_GP2:0) ); + INTSTAT_FATAL); /* Enable interrupts, set for PCI read multiple and etc */ CSR_WRITE_4( sc, GENCTL, GENCTL_ENABLE_INTERRUPT | GENCTL_MEMORY_READ_MULTIPLE | GENCTL_ONECOPY | GENCTL_RECEIVE_FIFO_THRESHOLD64 ); - /* Set media speed mode */ - epic_set_media_speed( sc ); - /* Mark interface running ... */ if( ifp->if_flags & IFF_UP ) ifp->if_flags |= IFF_RUNNING; else ifp->if_flags &= ~IFF_RUNNING; @@ -1356,273 +1406,77 @@ epic_init __P(( /* Start Rx process */ epic_start_activity(sc); - splx(s); - return 0; -} - -/* - * Synopsis: calculate and set Rx mode. Chip must be in idle state to - * access RXCON. - */ -void -epic_set_rx_mode( - epic_softc_t * sc) -{ - u_int32_t flags = sc->sc_if.if_flags; - u_int32_t rxcon = RXCON_DEFAULT | RXCON_RECEIVE_MULTICAST_FRAMES | RXCON_RECEIVE_BROADCAST_FRAMES; - - rxcon |= (flags & IFF_PROMISC)?RXCON_PROMISCUOUS_MODE:0; - - CSR_WRITE_4( sc, RXCON, rxcon ); + /* Reset all PHYs */ + mii = epic_mii_ptr(sc); + if (mii->mii_instance) { + struct mii_softc *miisc; + for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; + miisc = LIST_NEXT(miisc, mii_list)) + mii_phy_reset(miisc); + } - return; -} + /* Set appropriate media */ + epic_ifmedia_upd(ifp); -#if 0 -void -epic_dump_phy_regs(epic_softc_t *sc) -{ + splx(s); - printf("BMCR: 0x%04x\n", PHY_READ_2(sc, DP83840_BMCR)); - printf("BMSR: 0x%04x\n", PHY_READ_2(sc, DP83840_BMSR)); - printf("ANAR: 0x%04x\n", PHY_READ_2(sc, DP83840_ANAR)); - printf("LPAR: 0x%04x\n", PHY_READ_2(sc, DP83840_LPAR)); - printf("ANER: 0x%04x\n", PHY_READ_2(sc, DP83840_ANER)); - printf("MCTL: 0x%04x\n", PHY_READ_2(sc, QS6612_MCTL)); - printf("INTSTAT: 0x%04x\n", PHY_READ_2(sc, QS6612_INTSTAT)); - printf("INTMASK: 0x%04x\n", PHY_READ_2(sc, QS6612_INTMASK)); - printf("BPCR: 0x%04x\n", PHY_READ_2(sc, QS6612_BPCR)); + return 0; } -#endif /* - * Synopsis: Reset PHY and do PHY-special initialization: + * Reset the epic chip */ -void -epic_init_phy __P(( - epic_softc_t * sc)) +EPIC_STATIC void epic_reset(sc) + epic_softc_t *sc; { - u_int32_t i; + int i; - /* Reset PHY (We have to take the delay from manual XXX) */ - PHY_WRITE_2(sc, DP83840_BMCR, BMCR_RESET); - DELAY(10); - for(i=0;i<0x1000;i++) { - if( !(PHY_READ_2(sc, DP83840_BMCR) & BMCR_RESET) ) - break; - DELAY(1); - } - - if( PHY_READ_2(sc, DP83840_BMCR) & BMCR_RESET ) - printf(EPIC_FORMAT ": WARNING! cant reset PHY\n",EPIC_ARGS(sc)); - - PHY_WRITE_2(sc, DP83840_BMCR, 0 ); - PHY_WRITE_2(sc, DP83840_BMCR, BMCR_LOOPBACK | BMCR_ISOLATE ); - - switch( sc->phyid ){ - case QS6612_OUI: { - /* Init QS6612 and EPIC to generate interrupt */ - CSR_WRITE_4(sc, NVCTL, NVCTL_GP1_OUTPUT_ENABLE | NVCTL_GP1); + /* Soft reset the chip (we have to power up card before) */ + CSR_WRITE_4( sc, GENCTL, 0 ); + CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET ); - /* Mask interrupts sources */ - PHY_WRITE_2(sc, QS6612_INTMASK, - PHY_READ_2(sc, QS6612_INTSTAT) | - INTMASK_THUNDERLAN | INTSTAT_AN_COMPLETE | - INTSTAT_LINK_STATUS ); + /* + * Reset takes 15 pci ticks which depends on PCI bus speed. + * Assuming it >= 33000000 hz, we have wait at least 495e-6 sec. + */ + DELAY(500); - /* Enable QS6612 extended cable length capabilites */ - /* PHY_WRITE_2(sc, QS6612_MCTL, */ - /* PHY_READ_2(sc, QS6612_MCTL) | MCTL_BTEXT); */ + /* Wake up */ + CSR_WRITE_4( sc, GENCTL, 0 ); - break; - } - default: - break; - } + /* Workaround for Application Note 7-15 */ + for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST); } - /* - * Synopsis: Set PHY to media type specified by IFF_LINK* flags or - * ifmedia structure. Chip must be in idle state to access TXCON. + * Synopsis: calculate and set Rx mode. Chip must be in idle state to + * access RXCON. */ -void -epic_set_media_speed __P(( - epic_softc_t * sc)) +EPIC_STATIC void +epic_set_rx_mode(sc) + epic_softc_t *sc; { - u_int16_t media; -#if !defined(EPIC_NOIFMEDIA) - u_int32_t tgtmedia = sc->ifmedia.ifm_cur->ifm_media; -#endif - - epic_init_phy(sc); - -#if !defined(EPIC_NOIFMEDIA) - if( IFM_SUBTYPE(tgtmedia) != IFM_AUTO ){ - /* Clean previous values */ - sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX); - media = 0; - - /* Set mode */ - media |= (IFM_SUBTYPE(tgtmedia)==IFM_100_TX) ? BMCR_100MBPS : 0; - if (tgtmedia & IFM_FDX) { - media |= BMCR_FULL_DUPLEX; - sc->txcon |= TXCON_FULL_DUPLEX; - } - if (tgtmedia & IFM_LOOP) { - if (tgtmedia & IFM_FLAG1) - sc->txcon |= TXCON_LOOPBACK_MODE_INT; - else { - media |= BMCR_LOOPBACK | BMCR_ISOLATE; - sc->txcon |= TXCON_LOOPBACK_MODE_PHY; - } - } - - sc->sc_if.if_baudrate = - (IFM_SUBTYPE(tgtmedia)==IFM_100_TX)?100000000:10000000; + u_int32_t flags = sc->sc_if.if_flags; + u_int32_t rxcon = RXCON_DEFAULT; - PHY_WRITE_2( sc, DP83840_BMCR, media ); - } -#else /* EPIC_NOIFMEDIA */ - struct ifnet *ifp = &sc->sc_if; - - if( ifp->if_flags & IFF_LINK0 ) { - /* Set mode */ - media = 0; - media|= (ifp->if_flags & IFF_LINK2) ? BMCR_100MBPS : 0; - media|= (ifp->if_flags & IFF_LINK1) ? BMCR_FULL_DUPLEX : 0; - - sc->sc_if.if_baudrate = - (ifp->if_flags & IFF_LINK2)?100000000:10000000; - - PHY_WRITE_2( sc, DP83840_BMCR, media ); - - if( ifp->if_flags & IFF_LINK2 ) sc->txcon |= TXCON_FULL_DUPLEX; - else sc->txcon &= ~TXCON_FULL_DUPLEX; - - CSR_WRITE_4( sc, TXCON, sc->txcon ); - } -#endif /* !EPIC_NOIFMEDIA */ - else { - sc->sc_if.if_baudrate = 100000000; - - sc->txcon &= ~TXCON_FULL_DUPLEX; - CSR_WRITE_4(sc, TXCON, sc->txcon); - - /* Set and restart autoneg */ - PHY_WRITE_2(sc, DP83840_BMCR, BMCR_AUTONEGOTIATION ); - PHY_WRITE_2(sc, DP83840_BMCR, - BMCR_AUTONEGOTIATION | BMCR_RESTART_AUTONEG); - - /* If it is not QS6612 PHY, try to get result of autoneg. */ - if( QS6612_OUI != sc->phyid ) { - /* Wait 3 seconds for the autoneg to finish - * This is the recommended time from the DP83840A data - * sheet Section 7.1 - */ - DELAY(3000000); - - if( epic_autoneg(sc) == EPIC_FULL_DUPLEX ) { - sc->txcon |= TXCON_FULL_DUPLEX; - CSR_WRITE_4(sc, TXCON, sc->txcon); - } - } - /* Else it will be done when GP2 int occured */ - } + rxcon |= (flags & IFF_PROMISC) ? RXCON_PROMISCUOUS_MODE : 0; - epic_set_tx_mode(sc); + CSR_WRITE_4( sc, RXCON, rxcon ); return; } /* - * This functions get results of the autoneg processes of the phy - * It implements the workaround that is described in section 7.2 & 7.3 of the - * DP83840A data sheet - * http://www.national.com/ds/DP/DP83840A.pdf + * Synopsis: Set transmit control register. Chip must be in idle state to + * access TXCON. */ -int -epic_autoneg( - epic_softc_t * sc) -{ - u_int16_t media; - u_int16_t i; - - /* BMSR must be read twice to update the link status bit - * since that bit is a latch bit - */ - PHY_READ_2( sc, DP83840_BMSR); - i = PHY_READ_2( sc, DP83840_BMSR); - - if ((i & BMSR_LINK_STATUS) && (i & BMSR_AUTONEG_COMPLETE)){ - i = PHY_READ_2( sc, DP83840_LPAR ); - - if ( i & (ANAR_100_TX_FD|ANAR_10_FD) ) - return EPIC_FULL_DUPLEX; - else - return EPIC_HALF_DUPLEX; - } else { - /*Auto-negotiation or link status is not 1 - Thus the auto-negotiation failed and one - must take other means to fix it. - */ - - /* ANER must be read twice to get the correct reading for the - * Multiple link fault bit -- it is a latched bit - */ - PHY_READ_2( sc, DP83840_ANER ); - i = PHY_READ_2( sc, DP83840_ANER ); - - if ( i & ANER_MULTIPLE_LINK_FAULT ) { - /* it can be forced to 100Mb/s Half-Duplex */ - media = PHY_READ_2( sc, DP83840_BMCR ); - media &= ~(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX); - media |= BMCR_100MBPS; - PHY_WRITE_2( sc, DP83840_BMCR, media ); - - /* read BMSR again to determine link status */ - PHY_READ_2( sc, DP83840_BMSR ); - i=PHY_READ_2( sc, DP83840_BMSR ); - - if (i & BMSR_LINK_STATUS){ - /* port is linked to the non Auto-Negotiation - * 100Mbs partner. - */ - return EPIC_HALF_DUPLEX; - } - else { - media = PHY_READ_2( sc, DP83840_BMCR); - media &= ~(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX | BMCR_100MBPS); - PHY_WRITE_2( sc, DP83840_BMCR, media); - PHY_READ_2( sc, DP83840_BMSR ); - i = PHY_READ_2( sc, DP83840_BMSR ); - - if (i & BMSR_LINK_STATUS) { - /*port is linked to the non - * Auto-Negotiation10Mbs partner - */ - return EPIC_HALF_DUPLEX; - } - } - } - /* If we get here we are most likely not connected - * so lets default it to half duplex - */ - return EPIC_HALF_DUPLEX; - } - -} - -/* - */ -void -epic_set_tx_mode ( - epic_softc_t *sc ) +EPIC_STATIC void +epic_set_tx_mode(sc) + epic_softc_t *sc; { + if (sc->txcon & TXCON_EARLY_TRANSMIT_ENABLE) + CSR_WRITE_4 (sc, ETXTHR, sc->tx_threshold); - if( sc->txcon & TXCON_EARLY_TRANSMIT_ENABLE ) - CSR_WRITE_4( sc, ETXTHR, sc->tx_threshold ); - - CSR_WRITE_4( sc, TXCON, sc->txcon ); + CSR_WRITE_4 (sc, TXCON, sc->txcon); } /* @@ -1633,9 +1487,9 @@ epic_set_tx_mode ( * reprogramming MC filter. The epic_stop_activity() and * epic_start_activity() should help to do this. */ -void -epic_set_mc_table ( - epic_softc_t * sc) +EPIC_STATIC void +epic_set_mc_table(sc) + epic_softc_t *sc; { struct ifnet *ifp = &sc->sc_if; @@ -1653,24 +1507,24 @@ epic_set_mc_table ( /* * Synopsis: Start receive process and transmit one, if they need. */ -void -epic_start_activity __P(( - epic_softc_t * sc)) +EPIC_STATIC void +epic_start_activity(sc) + epic_softc_t *sc; { - /* Start rx process */ - CSR_WRITE_4(sc, COMMAND, - COMMAND_RXQUEUED | COMMAND_START_RX | - (sc->pending_txs?COMMAND_TXQUEUED:0)); - dprintf((EPIC_FORMAT ": activity started\n",EPIC_ARGS(sc))); + /* Start rx process */ + CSR_WRITE_4(sc, COMMAND, + COMMAND_RXQUEUED | COMMAND_START_RX | + (sc->pending_txs?COMMAND_TXQUEUED:0)); + dprintf((EPIC_FORMAT ": activity started\n",EPIC_ARGS(sc))); } /* * Synopsis: Completely stop Rx and Tx processes. If TQE is set additional * packet needs to be queued to stop Tx DMA. */ -void -epic_stop_activity __P(( - epic_softc_t * sc)) +EPIC_STATIC void +epic_stop_activity(sc) + epic_softc_t *sc; { int i; @@ -1762,12 +1616,10 @@ epic_stop_activity __P(( /* * Synopsis: Shut down board and deallocates rings. - * - * splimp() invoked here */ -void -epic_stop __P(( - epic_softc_t * sc)) +EPIC_STATIC void +epic_stop(sc) + epic_softc_t *sc; { int s; @@ -1802,9 +1654,9 @@ epic_stop __P(( /* * Synopsis: This function should free all memory allocated for rings. */ -void -epic_free_rings __P(( - epic_softc_t * sc)) +EPIC_STATIC void +epic_free_rings(sc) + epic_softc_t *sc; { int i; @@ -1838,8 +1690,10 @@ epic_free_rings __P(( * Point Tx descs to fragment lists. Check that all descs and fraglists * are bounded and aligned properly. */ -int -epic_init_rings(epic_softc_t * sc){ +EPIC_STATIC int +epic_init_rings(sc) + epic_softc_t *sc; +{ int i; sc->cur_rx = sc->cur_tx = sc->dirty_tx = sc->pending_txs = 0; @@ -1888,9 +1742,10 @@ epic_init_rings(epic_softc_t * sc){ /* * EEPROM operation functions */ -void epic_write_eepromreg __P(( - epic_softc_t *sc, - u_int8_t val)) +EPIC_STATIC void +epic_write_eepromreg(sc, val) + epic_softc_t *sc; + u_int8_t val; { u_int16_t i; @@ -1902,17 +1757,17 @@ void epic_write_eepromreg __P(( return; } -u_int8_t -epic_read_eepromreg __P(( - epic_softc_t *sc)) +EPIC_STATIC u_int8_t +epic_read_eepromreg(sc) + epic_softc_t *sc; { - return CSR_READ_1( sc,EECTL ); + return CSR_READ_1(sc, EECTL); } -u_int8_t -epic_eeprom_clock __P(( - epic_softc_t *sc, - u_int8_t val)) +EPIC_STATIC u_int8_t +epic_eeprom_clock(sc, val) + epic_softc_t *sc; + u_int8_t val; { epic_write_eepromreg( sc, val ); epic_write_eepromreg( sc, (val | 0x4) ); @@ -1921,10 +1776,10 @@ epic_eeprom_clock __P(( return epic_read_eepromreg( sc ); } -void -epic_output_eepromw __P(( - epic_softc_t * sc, - u_int16_t val)) +EPIC_STATIC void +epic_output_eepromw(sc, val) + epic_softc_t *sc; + u_int16_t val; { int i; for( i = 0xF; i >= 0; i--){ @@ -1933,9 +1788,9 @@ epic_output_eepromw __P(( } } -u_int16_t -epic_input_eepromw __P(( - epic_softc_t *sc)) +EPIC_STATIC u_int16_t +epic_input_eepromw(sc) + epic_softc_t *sc; { int i; int tmp; @@ -1950,10 +1805,10 @@ epic_input_eepromw __P(( return retval; } -int -epic_read_eeprom __P(( - epic_softc_t *sc, - u_int16_t loc)) +EPIC_STATIC int +epic_read_eeprom(sc, loc) + epic_softc_t *sc; + u_int16_t loc; { u_int16_t dataval; u_int16_t read_cmd; @@ -1974,75 +1829,68 @@ epic_read_eeprom __P(( return dataval; } -u_int16_t -epic_read_phy_register __P(( - epic_softc_t *sc, - u_int16_t loc)) +/* + * Here goes MII read/write routines + */ +EPIC_STATIC int +epic_read_phy_reg(sc, phy, reg) + epic_softc_t *sc; + int phy, reg; { int i; - CSR_WRITE_4( sc, MIICTL, ((loc << 4) | 0x0601) ); + CSR_WRITE_4 (sc, MIICTL, ((reg << 4) | (phy << 9) | 0x01)); for (i=0;i<0x100;i++) { - if( !(CSR_READ_4( sc, MIICTL )&1) ) break; + if( !(CSR_READ_4(sc, MIICTL) & 0x01) ) break; DELAY(1); } - return CSR_READ_4( sc, MIIDATA ); + return (CSR_READ_4 (sc, MIIDATA)); } -void -epic_write_phy_register __P(( - epic_softc_t * sc, - u_int16_t loc, - u_int16_t val)) +EPIC_STATIC void +epic_write_phy_reg(sc, phy, reg, val) + epic_softc_t *sc; + int phy, reg, val; { int i; - CSR_WRITE_4( sc, MIIDATA, val ); - CSR_WRITE_4( sc, MIICTL, ((loc << 4) | 0x0602) ); + CSR_WRITE_4 (sc, MIIDATA, val); + CSR_WRITE_4 (sc, MIICTL, ((reg << 4) | (phy << 9) | 0x02)); - for( i=0;i<0x100;i++) { - if( !(CSR_READ_4( sc, MIICTL )&2) ) break; + for(i=0;i<0x100;i++) { + if( !(CSR_READ_4(sc, MIICTL) & 0x02) ) break; DELAY(1); } return; } -void -epic_dump_state __P(( - epic_softc_t * sc)) +EPIC_STATIC int +epic_miibus_readreg(dev, phy, reg) + struct device* dev; + int phy, reg; { - int j; - struct epic_tx_desc *tdesc; - struct epic_rx_desc *rdesc; - printf(EPIC_FORMAT ": cur_rx: %d, pending_txs: %d, dirty_tx: %d, cur_tx: %d\n", EPIC_ARGS(sc),sc->cur_rx,sc->pending_txs,sc->dirty_tx,sc->cur_tx); - printf(EPIC_FORMAT ": COMMAND: 0x%08x, INTSTAT: 0x%08x\n",EPIC_ARGS(sc),CSR_READ_4(sc,COMMAND),CSR_READ_4(sc,INTSTAT)); - printf(EPIC_FORMAT ": PRCDAR: 0x%08x, PTCDAR: 0x%08x\n",EPIC_ARGS(sc),CSR_READ_4(sc,PRCDAR),CSR_READ_4(sc,PTCDAR)); - printf(EPIC_FORMAT ": dumping rx descriptors\n",EPIC_ARGS(sc)); - for(j=0;j<RX_RING_SIZE;j++){ - rdesc = sc->rx_desc + j; - printf("desc%d: %4d 0x%04x, 0x%08x, %4d, 0x%08x\n", - j, - rdesc->rxlength,rdesc->status, - rdesc->bufaddr, - rdesc->buflength, - rdesc->next - ); - } - printf(EPIC_FORMAT ": dumping tx descriptors\n",EPIC_ARGS(sc)); - for(j=0;j<TX_RING_SIZE;j++){ - tdesc = sc->tx_desc + j; - printf( - "desc%d: %4d 0x%04x, 0x%08lx, 0x%04x %4u, 0x%08lx, mbuf: %p\n", - j, - tdesc->txlength,tdesc->status, - (u_long)tdesc->bufaddr, - tdesc->control,tdesc->buflength, - (u_long)tdesc->next, - (void *)sc->tx_buffer[j].mbuf - ); - } + epic_softc_t *sc; + + sc = epic_dev_ptr(dev); + + return (PHY_READ_2(sc, phy, reg)); +} + +EPIC_STATIC EPIC_MIIBUS_WRITEREG_RET_TYPE +epic_miibus_writereg(dev, phy, reg, data) + struct device* dev; + int phy, reg, data; +{ + epic_softc_t *sc; + + sc = epic_dev_ptr(dev); + + PHY_WRITE_2(sc, phy, reg, data); + +#if !defined(__OpenBSD__) + return (0); +#endif } -#endif /* NPCI > 0 */ diff --git a/sys/dev/pci/if_txvar.h b/sys/dev/pci/if_txvar.h index 7fd538ae248..286a6467cd5 100644 --- a/sys/dev/pci/if_txvar.h +++ b/sys/dev/pci/if_txvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: if_txvar.h,v 1.7 1999/11/17 05:21:19 jason Exp $ */ -/* $FreeBSD: src/sys/pci/if_txvar.h,v 1.5 1999/10/29 09:56:52 semenu Exp $ */ +/* $OpenBSD: if_txvar.h,v 1.8 2000/10/17 15:47:12 jason Exp $ */ +/* $FreeBSD: src/sys/pci/if_txvar.h,v 1.7 2000/06/21 19:19:49 semenu Exp $ */ /*- * Copyright (c) 1997 Semen Ustimenko @@ -30,6 +30,10 @@ /* * Configuration */ +/*#define EPIC_DEBUG 1*/ +/*#define EPIC_USEIOSPACE 1*/ +#define EARLY_RX 1 + #ifndef ETHER_MAX_LEN #define ETHER_MAX_LEN 1518 #endif @@ -44,33 +48,20 @@ /* confuse RX(TX)_RING_MASK */ #define TX_RING_MASK (TX_RING_SIZE - 1) #define RX_RING_MASK (RX_RING_SIZE - 1) -#define EPIC_FULL_DUPLEX 1 -#define EPIC_HALF_DUPLEX 0 #define ETHER_MAX_FRAME_LEN (ETHER_MAX_LEN + ETHER_CRC_LEN) -#define EPIC_LINK_DOWN 0x00000001 + +/* PCI aux configuration registers */ +#if defined(__FreeBSD__) +#define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */ +#define PCIR_BASEMEM (PCIR_MAPS + 0x4) /* Base Memory Address */ +#else /* __OpenBSD__ */ +#define PCI_BASEIO (PCI_MAPS + 0x0) /* Base IO Address */ +#define PCI_BASEMEM (PCI_MAPS + 0x4) /* Base Memory Address */ +#endif /* __FreeBSD__ */ /* PCI identification */ #define SMC_VENDORID 0x10B8 -#define CHIPID_83C170 0x0005 -#define PCI_VENDORID(x) ((x) & 0xFFFF) -#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF) - -/* PCI configuration */ -#define PCI_CFID 0x00 /* Configuration ID */ -#define PCI_CFCS 0x04 /* Configurtion Command/Status */ -#define PCI_CFRV 0x08 /* Configuration Revision */ -#define PCI_CFLT 0x0c /* Configuration Latency Timer */ -#define PCI_CBIO 0x10 /* Configuration Base IO Address */ -#define PCI_CBMA 0x14 /* Configuration Base Memory Address */ -#define PCI_CFIT 0x3c /* Configuration Interrupt */ -#define PCI_CFDA 0x40 /* Configuration Driver Area */ - -#define PCI_CFCS_IOEN 0x0001 /* IO Space Enable */ -#define PCI_CFCS_MAEN 0x0002 /* Memory Space Enable */ -#define PCI_CFCS_BMEN 0x0004 /* Bus Master Enable */ - -#define PCI_CONF_WRITE(r, v) pci_conf_write(config_id, (r), (v)) -#define PCI_CONF_READ(r) pci_conf_read(config_id, (r)) +#define SMC_DEVICEID_83C170 0x0005 /* EPIC's registers */ #define COMMAND 0x0000 @@ -113,9 +104,6 @@ #define COMMAND_STOP_RDMA 0x40 #define COMMAND_TXUGO 0x80 -/* Tx threshold */ -#define TX_FIFO_THRESH 0x80 /* 0x40 or 0x10 */ - /* Interrupt register bits */ #define INTSTAT_RCC 0x00000001 #define INTSTAT_HCC 0x00000002 @@ -194,84 +182,30 @@ #define TXCON_FULL_DUPLEX 0x00000006 #define TXCON_SLOT_TIME 0x00000078 +#define MIICFG_SERIAL_ENABLE 0x00000001 +#define MIICFG_694_ENABLE 0x00000002 +#define MIICFG_694_STATUS 0x00000004 +#define MIICFG_PHY_PRESENT 0x00000008 #define MIICFG_SMI_ENABLE 0x00000010 #define TEST1_CLOCK_TEST 0x00000008 +/* + * Some default values + */ #define TXCON_DEFAULT (TXCON_SLOT_TIME | TXCON_EARLY_TRANSMIT_ENABLE) -#define TRANSMIT_THRESHOLD 0x80 +#define TRANSMIT_THRESHOLD 0x300 #if defined(EARLY_RX) - #define RXCON_DEFAULT (RXCON_EARLY_RECEIVE_ENABLE | RXCON_SAVE_ERRORED_PACKETS) +#define RXCON_EARLY (RXCON_EARLY_RECEIVE_ENABLE | \ + RXCON_SAVE_ERRORED_PACKETS) #else - #define RXCON_DEFAULT (0) +#define RXCON_EARLY (0) #endif -/* - * National Semiconductor's DP83840A Registers and bits - */ -#define DP83840_OUI 0x080017 -#define DP83840_BMCR 0x00 /* Control register */ -#define DP83840_BMSR 0x01 /* Status rgister */ -#define DP83840_ANAR 0x04 /* Autonegotiation advertising register */ -#define DP83840_LPAR 0x05 /* Link Partner Ability register */ -#define DP83840_ANER 0x06 /* Auto-Negotiation Expansion Register */ -#define DP83840_PAR 0x19 /* PHY Address Register */ -#define DP83840_PHYIDR1 0x02 -#define DP83840_PHYIDR2 0x03 - -#define BMCR_RESET 0x8000 -#define BMCR_LOOPBACK 0x4000 -#define BMCR_100MBPS 0x2000 /* 10/100 Mbps */ -#define BMCR_AUTONEGOTIATION 0x1000 /* ON/OFF */ -#define BMCR_POWERDOWN 0x0800 -#define BMCR_ISOLATE 0x0400 -#define BMCR_RESTART_AUTONEG 0x0200 -#define BMCR_FULL_DUPLEX 0x0100 -#define BMCR_COL_TEST 0x0080 - -#define BMSR_100BASE_T4 0x8000 -#define BMSR_100BASE_TX_FD 0x4000 -#define BMSR_100BASE_TX 0x2000 -#define BMSR_10BASE_T_FD 0x1000 -#define BMSR_10BASE_T 0x0800 -#define BMSR_AUTONEG_COMPLETE 0x0020 -#define BMSR_AUTONEG_ABLE 0x0008 -#define BMSR_LINK_STATUS 0x0004 - -#define PAR_FULL_DUPLEX 0x0400 - -#define ANER_MULTIPLE_LINK_FAULT 0x10 - -/* ANAR and LPAR have the same bits, define them only once */ -#define ANAR_10 0x0020 -#define ANAR_10_FD 0x0040 -#define ANAR_100_TX 0x0080 -#define ANAR_100_TX_FD 0x0100 -#define ANAR_100_T4 0x0200 -/* - * Quality Semiconductor's QS6612 registers and bits - */ -#define QS6612_OUI 0x006051 -#define QS6612_MCTL 17 -#define QS6612_INTSTAT 29 -#define QS6612_INTMASK 30 -#define QS6612_BPCR 31 - -#define MCTL_T4_PRESENT 0x1000 /* External T4 Enabled, ignored */ - /* if AutoNeg is enabled */ -#define MCTL_BTEXT 0x0800 /* Reduces 10baset squelch level */ - /* for extended cable length */ - -#define INTSTAT_AN_COMPLETE 0x40 /* Autonegotiation complete */ -#define INTSTAT_RF_DETECTED 0x20 /* Remote Fault detected */ -#define INTSTAT_LINK_STATUS 0x10 /* Link status changed */ -#define INTSTAT_AN_LP_ACK 0x08 /* Autoneg. LP Acknoledge */ -#define INTSTAT_PD_FAULT 0x04 /* Parallel Detection Fault */ -#define INTSTAT_AN_PAGE 0x04 /* Autoneg. Page Received */ -#define INTSTAT_RE_CNT_FULL 0x01 /* Receive Error Counter Full */ - -#define INTMASK_THUNDERLAN 0x8000 /* Enable interrupts */ +#define RXCON_DEFAULT (RXCON_EARLY | \ + RXCON_RECEIVE_MULTICAST_FRAMES | \ + RXCON_RECEIVE_BROADCAST_FRAMES) /* * Structures definition and Functions prototypes @@ -323,25 +257,32 @@ struct epic_tx_buffer { * epic_rx_desc, epic_tx_desc, epic_frag_list - must be aligned on dword */ -/* Driver status structure */ +/* + * Driver status structure + * There are macros to handle the access of Free|Open specific fields. + */ + typedef struct { #if defined(__OpenBSD__) - struct device sc_dev; + struct device dev; + + struct arpcom arpcom; + + mii_data_t miibus; +#else /* __FreeBSD__ */ + struct resource *res; + struct resource *irq; + + device_t miibus; + device_t dev; + struct callout_handle stat_ch; + + u_int32_t unit; +#endif void *sc_ih; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; -#else /* __FreeBSD__ */ -#if defined(EPIC_USEIOSPACE) - u_int32_t iobase; -#else - caddr_t csr; -#endif -#endif -#if !defined(EPIC_NOIFMEDIA) - struct ifmedia ifmedia; -#endif - struct arpcom arpcom; - u_int32_t unit; + struct epic_rx_buffer rx_buffer[RX_RING_SIZE]; struct epic_tx_buffer tx_buffer[TX_RING_SIZE]; @@ -361,43 +302,31 @@ typedef struct { void *pool; } epic_softc_t; +struct epic_type { + u_int16_t ven_id; + u_int16_t dev_id; + char *name; +}; + +#if defined(EPIC_DEBUG) +#define dprintf(a) printf a +#else +#define dprintf(a) +#endif + #if defined(__FreeBSD__) #define EPIC_FORMAT "tx%d" #define EPIC_ARGS(sc) (sc->unit) -#define sc_if arpcom.ac_if -#define sc_macaddr arpcom.ac_enaddr -#if defined(EPIC_USEIOSPACE) -#define CSR_WRITE_4(sc,reg,val) \ - outl( (sc)->iobase + (u_int32_t)(reg), (val) ) -#define CSR_WRITE_2(sc,reg,val) \ - outw( (sc)->iobase + (u_int32_t)(reg), (val) ) -#define CSR_WRITE_1(sc,reg,val) \ - outb( (sc)->iobase + (u_int32_t)(reg), (val) ) -#define CSR_READ_4(sc,reg) \ - inl( (sc)->iobase + (u_int32_t)(reg) ) -#define CSR_READ_2(sc,reg) \ - inw( (sc)->iobase + (u_int32_t)(reg) ) -#define CSR_READ_1(sc,reg) \ - inb( (sc)->iobase + (u_int32_t)(reg) ) -#else -#define CSR_WRITE_1(sc,reg,val) \ - ((*(volatile u_int8_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int8_t)(val)) -#define CSR_WRITE_2(sc,reg,val) \ - ((*(volatile u_int16_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int16_t)(val)) -#define CSR_WRITE_4(sc,reg,val) \ - ((*(volatile u_int32_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int32_t)(val)) -#define CSR_READ_1(sc,reg) \ - (*(volatile u_int8_t*)((sc)->csr + (u_int32_t)(reg))) -#define CSR_READ_2(sc,reg) \ - (*(volatile u_int16_t*)((sc)->csr + (u_int32_t)(reg))) -#define CSR_READ_4(sc,reg) \ - (*(volatile u_int32_t*)((sc)->csr + (u_int32_t)(reg))) -#endif +#define EPIC_BPFTAP_ARG(ifp) ifp #else /* __OpenBSD__ */ #define EPIC_FORMAT "%s" -#define EPIC_ARGS(sc) (sc->sc_dev.dv_xname) -#define sc_if arpcom.ac_if +#define EPIC_ARGS(sc) (sc->dev.dv_xname) +#define EPIC_BPFTAP_ARG(ifp) (ifp)->if_bpf +#endif + +#define sc_if arpcom.ac_if #define sc_macaddr arpcom.ac_enaddr + #define CSR_WRITE_4(sc,reg,val) \ bus_space_write_4( (sc)->sc_st, (sc)->sc_sh, (reg), (val) ) #define CSR_WRITE_2(sc,reg,val) \ @@ -410,8 +339,41 @@ typedef struct { bus_space_read_2( (sc)->sc_st, (sc)->sc_sh, (reg) ) #define CSR_READ_1(sc,reg) \ bus_space_read_1( (sc)->sc_st, (sc)->sc_sh, (reg) ) -#endif -#define PHY_READ_2(sc,reg) epic_read_phy_register(sc,reg) -#define PHY_WRITE_2(sc,reg,val) epic_write_phy_register(sc,reg,val) +#define PHY_READ_2(sc,phy,reg) \ + epic_read_phy_reg((sc),(phy),(reg)) +#define PHY_WRITE_2(sc,phy,reg,val) \ + epic_write_phy_reg((sc),(phy),(reg),(val)) + +/* Macro to get either mbuf cluster or nothing */ +#define EPIC_MGETCLUSTER(m) \ + { MGETHDR((m),M_DONTWAIT,MT_DATA); \ + if (m) { \ + MCLGET((m),M_DONTWAIT); \ + if( NULL == ((m)->m_flags & M_EXT) ) { \ + m_freem(m); \ + (m) = NULL; \ + } \ + } \ + } +/* + * Platform Independant Field Accessors + */ +#if defined(__OpenBSD__) + +#define epic_dev(sc) (*sc) +#define epic_dev_ptr(sc) (void*)(sc) + +#define epic_mii(sc) (sc->miibus) +#define epic_mii_ptr(sc) (&sc->miibus) + +#else + +#define epic_dev(dev) (*(device_get_softc(dev)) +#define epic_dev_ptr(dev) (device_get_softc(dev)) + +#define epic_mii(sc) (*(device_get_softc(sc->miibus)) +#define epic_mii_ptr(sc) (device_get_softc(sc->miibus)) + +#endif |