diff options
author | semenu <semenu@FreeBSD.org> | 2000-04-12 06:51:43 +0000 |
---|---|---|
committer | semenu <semenu@FreeBSD.org> | 2000-04-12 06:51:43 +0000 |
commit | fea3e0ecac004c02502dcdcbf96af20a3a4bc864 (patch) | |
tree | 1bc77cb304b695502e35eef83160c588aa165a4e /sys/dev/tx | |
parent | ba68a82065f9f9389d80893245d4b41bcd22a765 (diff) | |
download | FreeBSD-src-fea3e0ecac004c02502dcdcbf96af20a3a4bc864.zip FreeBSD-src-fea3e0ecac004c02502dcdcbf96af20a3a4bc864.tar.gz |
Driver is now using miibus, and newbus.
PR: kern/17601
Diffstat (limited to 'sys/dev/tx')
-rw-r--r-- | sys/dev/tx/if_tx.c | 1360 | ||||
-rw-r--r-- | sys/dev/tx/if_txreg.h | 211 | ||||
-rw-r--r-- | sys/dev/tx/if_txvar.h | 211 |
3 files changed, 678 insertions, 1104 deletions
diff --git a/sys/dev/tx/if_tx.c b/sys/dev/tx/if_tx.c index 288edbd..fa03716 100644 --- a/sys/dev/tx/if_tx.c +++ b/sys/dev/tx/if_tx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tx.c,v 1.3 1998/10/10 04:30:09 jason Exp $ */ +/* $OpenBSD: if_tx.c,v 1.9.2.1 2000/02/21 22:29:13 niklas Exp $ */ /* $FreeBSD$ */ /*- @@ -25,8 +25,6 @@ * 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. - * - * */ /* @@ -37,60 +35,72 @@ * * todo: * Implement FULL IFF_MULTICAST support. - * Test, test and test again:-( * */ /* 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 "bpf.h" -#include "opt_bdg.h" - #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__) +#include "opt_bdg.h" +#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> + +#ifdef BRIDGE +#include <net/bridge.h> +#endif + +#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 @@ -103,64 +113,38 @@ #include <netns/ns_if.h> #endif -#if NBPF > 0 +#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 <sys/eventhandler.h> -#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> - -#ifdef BRIDGE -#include <net/bridge.h> -#endif - #endif #if defined(__FreeBSD__) -#if __FreeBSD_version >= 300000 -#define EPIC_IFIOCTL_CMD_TYPE u_long -#else -#define EPIC_IFIOCTL_CMD_TYPE int -#endif #define EPIC_INTR_RET_TYPE void #else /* __OpenBSD__ */ -#define EPIC_IFIOCTL_CMD_TYPE u_long #define EPIC_INTR_RET_TYPE int #endif -static int epic_ifioctl __P((register struct ifnet *, EPIC_IFIOCTL_CMD_TYPE, caddr_t)); +static int epic_ifioctl __P((register struct ifnet *, u_long, caddr_t)); static EPIC_INTR_RET_TYPE epic_intr __P((void *)); static int epic_common_attach __P((epic_softc_t *)); -static void epic_ifstart __P((struct ifnet * const)); +static void epic_ifstart __P((struct ifnet *)); static void epic_ifwatchdog __P((struct ifnet *)); static int epic_init __P((epic_softc_t *)); static void epic_stop __P((epic_softc_t *)); -static __inline void epic_rx_done __P((epic_softc_t *)); -static __inline void epic_tx_done __P((epic_softc_t *)); +static void epic_rx_done __P((epic_softc_t *)); +static void epic_tx_done __P((epic_softc_t *)); static int epic_init_rings __P((epic_softc_t *)); static void epic_free_rings __P((epic_softc_t *)); static void epic_stop_activity __P((epic_softc_t *)); @@ -168,39 +152,22 @@ static void epic_start_activity __P((epic_softc_t *)); static void epic_set_rx_mode __P((epic_softc_t *)); static void epic_set_tx_mode __P((epic_softc_t *)); static void epic_set_mc_table __P((epic_softc_t *)); -static void epic_set_media_speed __P((epic_softc_t *)); -static void epic_init_phy __P((epic_softc_t *)); -static void epic_dump_state __P((epic_softc_t *)); -static int epic_autoneg __P((epic_softc_t *)); static int epic_read_eeprom __P((epic_softc_t *,u_int16_t)); static void epic_output_eepromw __P((epic_softc_t *, u_int16_t)); static u_int16_t epic_input_eepromw __P((epic_softc_t *)); static u_int8_t epic_eeprom_clock __P((epic_softc_t *,u_int8_t)); static void epic_write_eepromreg __P((epic_softc_t *,u_int8_t)); static u_int8_t epic_read_eepromreg __P((epic_softc_t *)); -static u_int16_t epic_read_phy_register __P((epic_softc_t *, u_int16_t)); -static void epic_write_phy_register __P((epic_softc_t *, u_int16_t, u_int16_t)); -#if !defined(EPIC_NOIFMEDIA) -static int epic_ifmedia_change __P((struct ifnet *)); -static void epic_ifmedia_status __P((struct ifnet *, struct ifmediareq *)); -#endif +static int epic_read_phy_reg __P((epic_softc_t *, int, int)); +static void epic_write_phy_reg __P((epic_softc_t *, int, int, int)); -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])) +static int epic_miibus_readreg __P((device_t, int, int)); +static int epic_miibus_writereg __P((device_t, int, int, int)); +static void epic_miibus_statchg __P((device_t)); +static int epic_ifmedia_upd __P((struct ifnet *)); +static void epic_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); /* ------------------------------------------------------------------------- OS-specific part @@ -209,9 +176,9 @@ int epic_mtypes [] = { #if defined(__OpenBSD__) /* -----------------------------OpenBSD------------------------------------- */ -static int epic_openbsd_probe __P((struct device *,void *,void *)); -static void epic_openbsd_attach __P((struct device *, struct device *, void *)); -static void epic_shutdown __P((void *)); +int epic_openbsd_probe __P((struct device *,void *,void *)); +void epic_openbsd_attach __P((struct device *, struct device *, void *)); +void epic_openbsd_shutdown __P((void *)); struct cfattach tx_ca = { sizeof(epic_softc_t), epic_openbsd_probe, epic_openbsd_attach @@ -221,7 +188,7 @@ struct cfdriver tx_cd = { }; /* Synopsis: Check if device id corresponds with SMC83C170 id. */ -static int +int epic_openbsd_probe( struct device *parent, void *match, @@ -231,13 +198,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; } -static void +void epic_openbsd_attach( struct device *parent, struct device *self, @@ -249,23 +216,46 @@ epic_openbsd_attach( pci_intr_handle_t ih; const char *intrstr = NULL; struct ifnet *ifp; - bus_space_tag_t iot = pa->pa_iot; bus_addr_t iobase; bus_size_t iosize; int i; -#if !defined(EPIC_NOIFMEDIA) - int tmp; -#endif + u_int32_t command; + + command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + 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); - if( pci_io_find(pc, pa->pa_tag, PCI_CBIO, &iobase, &iosize)) { +#ifdef EPIC_USEIOSPACE + if (!(command & PCI_COMMAND_IO_ENABLE)) { + printf(": failed to enable I/O ports\n"); + return; + } + if( pci_io_find(pc, pa->pa_tag, PCI_BASEIO, &iobase, &iosize)) { printf(": can't find i/o space\n"); return; } - if( bus_space_map(iot, iobase, iosize, 0, &sc->sc_sh)) { + if( bus_space_map(pa->pa_iot, iobase, iosize, 0, &sc->sc_sh)) { printf(": can't map i/o space\n"); return; } - sc->sc_st = iot; + sc->sc_st = pa->pa_iot; +#else + if (!(command & PCI_COMMAND_MEM_ENABLE)) { + printf(": failed to enable memory mapping\n"); + return; + } + if( pci_mem_find(pc, pa->pa_tag, PCI_BASEMEM, &iobase, &iosize, NULL)) { + printf(": can't find mem space\n"); + return; + } + if( bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->sc_sh)) { + printf(": can't map i/o space\n"); + return; + } + sc->sc_st = pa->pa_memt; +#endif ifp = &sc->sc_if; bcopy(sc->sc_dev.dv_xname, ifp->if_xname,IFNAMSIZ); @@ -298,75 +288,37 @@ epic_openbsd_attach( /* 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 - } - } /* Init ifmedia interface */ -#if !defined(EPIC_NOIFMEDIA) - ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status); - - for (i=0; i<EPIC_MTYPESNUM; i++) - ifmedia_add(&sc->ifmedia,epic_mtypes[i],0,NULL); - - ifmedia_set(&sc->ifmedia, tmp); -#endif + ifmedia_init(&sc->sc_mii.mii_media, 0, + epic_ifmedia_upd, epic_ifmedia_sts); + sc->sc_mii.mii_ifp = ifp; + sc->sc_mii.mii_readreg = epic_miibus_readreg; + sc->sc_mii.mii_writereg = epic_miibus_writereg; + sc->sc_mii.mii_statchg = epic_miibus_statchg; + mii_phy_probe(self, &sc->sc_mii, 0xffffffff); + if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { + ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE,0,NULL); + ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); + } else + ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); /* Attach os interface and bpf */ if_attach(ifp); ether_ifattach(ifp); -#if NBPF > 0 +#if NBPFILTER > 0 bpfattach(&sc->sc_if.if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif /* Set shutdown routine to stop DMA process */ - shutdownhook_establish(epic_shutdown, sc); + shutdownhook_establish(epic_openbsd_shutdown, sc); printf("\n"); } /* Simple call epic_stop() */ -static void -epic_shutdown( +void +epic_openbsd_shutdown( void *sc) { epic_stop(sc); @@ -375,62 +327,108 @@ epic_shutdown( #else /* __FreeBSD__ */ /* -----------------------------FreeBSD------------------------------------- */ -static const char* epic_freebsd_probe __P((pcici_t, pcidi_t)); -static void epic_freebsd_attach __P((pcici_t, int)); -static void epic_shutdown __P((void *, int)); - -/* Global variables */ -static u_long epic_pci_count; -static struct pci_device txdevice = { - "tx", - epic_freebsd_probe, - epic_freebsd_attach, - &epic_pci_count, - NULL +static int epic_freebsd_probe __P((device_t)); +static int epic_freebsd_attach __P((device_t)); +static void epic_freebsd_shutdown __P((device_t)); +static int epic_freebsd_detach __P((device_t)); +static struct epic_type *epic_devtype __P((device_t)); + +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), + + { 0, 0 } +}; + +static driver_t epic_driver = { + "tx", + epic_methods, + sizeof(epic_softc_t) }; -/* Append this driver to pci drivers list */ -COMPAT_PCI_DRIVER (tx, txdevice); +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); + +static struct epic_type epic_devs[] = { + { SMC_VENDORID, SMC_DEVICEID_83C170, + "SMC EtherPower II 10/100BaseTX" }, + { 0, 0, NULL } +}; -/* Synopsis: Check if device id corresponds with SMC83C170 id. */ -static const char* -epic_freebsd_probe( - pcici_t config_id, - pcidi_t device_id) +static int +epic_freebsd_probe(dev) + device_t dev; { - if( PCI_VENDORID(device_id) != SMC_VENDORID ) - return NULL; + struct epic_type *t; + + t = epic_devtype(dev); - if( PCI_CHIPID(device_id) == CHIPID_83C170 ) - return "SMC 83c170"; + if (t != NULL) { + device_set_desc(dev, t->name); + return(0); + } - return NULL; + return(ENXIO); } +static struct epic_type * +epic_devtype(dev) + device_t 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. */ -static void -epic_freebsd_attach( - pcici_t config_id, - int unit) +static int +epic_freebsd_attach(dev) + device_t 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)); @@ -443,62 +441,101 @@ 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; + /* Bring the chip out of low-power mode and reset it. */ + CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET ); + DELAY(500); + + /* Workaround for Application Note 7-15 */ + for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST); + + /* + * 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; + } - /* Enable BusMaster'ing */ - 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 "); @@ -510,96 +547,75 @@ 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 */ + if_attach(ifp); + ether_ifattach(ifp); + callout_handle_init(&sc->stat_ch); - /* Init ifmedia interface */ -#if !defined(EPIC_NOIFMEDIA) - ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status); + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); - for (i=0; i<EPIC_MTYPESNUM; i++) - ifmedia_add(&sc->ifmedia,epic_mtypes[i],0,NULL); +fail: + splx(s); - ifmedia_set(&sc->ifmedia, tmp); -#endif + return(error); +} + +/* + * Detach driver and free resources + */ +static int +epic_freebsd_detach(dev) + device_t 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 */ - EVENTHANDLER_REGISTER(shutdown_post_sync, epic_shutdown, sc, - SHUTDOWN_PRI_DEFAULT); + bpfdetach(ifp); + if_detach(ifp); - /* Attach to if manager */ - if_attach(ifp); - ether_ifattach(ifp); + epic_stop(sc); -#if NBPF > 0 - bpfattach(ifp,DLT_EN10MB, sizeof(struct ether_header)); -#endif + bus_generic_detach(dev); + device_delete_child(dev, sc->miibus); - splx(s); + 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); - printf("\n"); + free(sc->pool, M_DEVBUF); - return; + splx(s); + + return(0); } +#undef EPIC_RES +#undef EPIC_RID + +/* + * Stop all chip I/O so that the kernel's probe routines don't + * get confused by errant DMAs when rebooting. + */ static void -epic_shutdown( - void *sc, - int howto) +epic_freebsd_shutdown(dev) + device_t dev; { + epic_softc_t *sc; + + sc = device_get_softc(dev); + epic_stop(sc); -} + return; +} #endif /* __OpenBSD__ */ /* ------------------------------------------------------------------------ @@ -610,12 +626,14 @@ epic_shutdown( * This is if_ioctl handler. */ static int -epic_ifioctl __P(( - register struct ifnet * ifp, - EPIC_IFIOCTL_CMD_TYPE command, - caddr_t data)) +epic_ifioctl(ifp, command, data) + struct ifnet *ifp; + u_long command; + caddr_t data; { epic_softc_t *sc = ifp->if_softc; + struct mii_data *mii; + struct ifreq *ifr = (struct ifreq *) data; int x, error = 0; x = splimp(); @@ -639,7 +657,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; @@ -662,7 +680,7 @@ epic_ifioctl __P(( break; } } -#endif +#endif /* __FreeBSD__ */ case SIOCSIFFLAGS: /* @@ -681,15 +699,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; @@ -711,13 +723,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 = device_get_softc(sc->miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; -#endif default: error = EINVAL; @@ -733,8 +743,8 @@ epic_ifioctl __P(( * Return -1 on failure. */ static int -epic_common_attach( - epic_softc_t *sc) +epic_common_attach(sc) + epic_softc_t *sc; { int i; caddr_t pool; @@ -761,8 +771,8 @@ epic_common_attach( pool += sizeof(struct epic_rx_desc)*RX_RING_SIZE; sc->tx_desc = (void *)pool; - /* Bring the chip out of low-power mode and reset it. */ - CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET ); + /* 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); @@ -771,12 +781,7 @@ epic_common_attach( 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; @@ -789,7 +794,9 @@ epic_common_attach( * or quque become empty. */ static void -epic_ifstart(struct ifnet * const ifp){ +epic_ifstart(ifp) + struct ifnet * ifp; +{ epic_softc_t *sc = ifp->if_softc; struct epic_tx_buffer *buf; struct epic_tx_desc *desc; @@ -798,20 +805,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; @@ -823,17 +816,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); @@ -877,13 +859,9 @@ epic_ifstart(struct ifnet * const ifp){ /* Set watchdog timer */ ifp->if_timer = 8; -#if NBPF > 0 +#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 } @@ -894,12 +872,11 @@ epic_ifstart(struct ifnet * const ifp){ } /* - * - * splimp() invoked before epic_intr_normal() + * Synopsis: Finish all received frames. */ -static __inline void -epic_rx_done __P(( - epic_softc_t *sc )) +static void +epic_rx_done(sc) + epic_softc_t *sc; { u_int16_t len; struct epic_rx_buffer *buf; @@ -947,15 +924,11 @@ epic_rx_done __P(( m->m_pkthdr.rcvif = &(sc->sc_if); m->m_pkthdr.len = m->m_len = len; -#if NBPF > 0 - /* Give mbuf to BPF */ +#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__ */ -#endif /* NBPF */ + bpf_mtap( EPIC_BPFTAP_ARG(&sc->sc_if), m ); +#endif /* NBPFILTER > 0 */ #ifdef BRIDGE if (do_bridge) { @@ -978,8 +951,7 @@ epic_rx_done __P(( } #endif -#if NBPF > 0 -#ifdef BRIDGE +#if defined (__FreeBSD__) /* * This deserves explanation * If the bridge is _on_, then the following check @@ -989,11 +961,14 @@ epic_rx_done __P(( * * But if the bridge is off, then we have to drop * stuff that came in just via bpf. + * + * In OpenBSD such filter stands in ether_input. (?) */ - if (!do_bridge) -#endif /* Accept only our packets, broadcasts and multicasts */ - if( (eh->ether_dhost[0] & 1) == 0 && +#ifdef BRIDGE + if (do_bridge) +#endif + if ((eh->ether_dhost[0] & 1) == 0 && bcmp(eh->ether_dhost,sc->sc_macaddr,ETHER_ADDR_LEN)){ m_freem(m); continue; @@ -1020,9 +995,9 @@ epic_rx_done __P(( * packet, switch to next descriptor and repeat until no packets * are pending or descriptor is not transmitted yet. */ -static __inline void -epic_tx_done __P(( - register epic_softc_t *sc )) +static void +epic_tx_done(sc) + epic_softc_t *sc; { struct epic_tx_buffer *buf; struct epic_tx_desc *desc; @@ -1060,12 +1035,10 @@ epic_tx_done __P(( /* * Interrupt function - * - * splimp() assumed to be done */ static EPIC_INTR_RET_TYPE -epic_intr ( - void *arg) +epic_intr(arg) + void *arg; { epic_softc_t * sc = (epic_softc_t *) arg; int status,i=4; @@ -1073,7 +1046,6 @@ epic_intr ( int claimed = 0; #endif - while( i-- && ((status = CSR_READ_4(sc, INTSTAT)) & INTSTAT_INT_ACTV) ){ #if defined(__OpenBSD__) claimed = 1; @@ -1088,8 +1060,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 ); @@ -1104,46 +1074,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) ){ @@ -1157,8 +1087,6 @@ epic_intr ( (status&INTSTAT_DPE)?" DPE":"" ); - epic_dump_state(sc); - epic_stop(sc); epic_init(sc); @@ -1202,12 +1130,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 */ static void -epic_ifwatchdog __P(( - struct ifnet *ifp)) +epic_ifwatchdog(ifp) + struct ifnet *ifp; { epic_softc_t *sc = ifp->if_softc; int x; @@ -1222,9 +1148,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 */ @@ -1241,77 +1165,99 @@ epic_ifwatchdog __P(( splx(x); } -#if defined(SIOCSIFMEDIA) && !defined(EPIC_NOIFMEDIA) +/* + * Set media options. + */ static int -epic_ifmedia_change __P(( - struct ifnet * ifp)) +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; - if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER) - return (EINVAL); + sc = ifp->if_softc; + mii = device_get_softc(sc->miibus); + mii_mediachg(mii); - if (!(ifp->if_flags & IFF_UP)) - return (0); + return(0); +} - epic_stop_activity(sc); - epic_set_media_speed(sc); - epic_start_activity(sc); +/* + * Report current media status. + */ +static void +epic_ifmedia_sts(ifp, ifmr) + struct ifnet *ifp; + struct ifmediareq *ifmr; +{ + epic_softc_t *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = device_get_softc(sc->miibus); + if (ifp->if_flags & IFF_UP) { + 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; + } - return 0; + return; } +/* + * Callback routine, called on media change. + */ static void -epic_ifmedia_status __P(( - struct ifnet * ifp, - struct ifmediareq *ifmr)) +epic_miibus_statchg(dev) + device_t dev; { - epic_softc_t *sc = ifp->if_softc; - u_int32_t bmcr; - u_int32_t bmsr; - - if (!(ifp->if_flags & IFF_UP)) - return; + epic_softc_t *sc; + struct mii_data *mii; - bmcr = PHY_READ_2( sc, DP83840_BMCR ); + sc = device_get_softc(dev); + mii = device_get_softc(sc->miibus); - PHY_READ_2( sc, DP83840_BMSR ); - bmsr = PHY_READ_2( sc, DP83840_BMSR ); + sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX); - ifmr->ifm_active = IFM_ETHER; - ifmr->ifm_status = IFM_AVALID; + /* + * 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( !(bmsr & BMSR_LINK_STATUS) ) { - ifmr->ifm_active |= - (bmcr&BMCR_AUTONEGOTIATION)?IFM_AUTO:IFM_NONE; - return; - } + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) + sc->sc_if.if_baudrate = 100000000; + else + sc->sc_if.if_baudrate = 10000000; - 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; + epic_set_tx_mode(sc); + return; } -#endif /* - * Reset chip, PHY, allocate rings - * - * splimp() invoked here + * Reset chip, allocate rings, and call miibus mediachg. */ -static int -epic_init __P(( - epic_softc_t * sc)) +static int +epic_init(sc) + epic_softc_t *sc; { struct ifnet *ifp = &sc->sc_if; + struct mii_data *mii; int s,i; s = splimp(); + /* If interface is already running, then we need not do anything */ + if (ifp->if_flags & IFF_RUNNING) { + splx(s); + return 0; + } + /* 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 ); @@ -1357,17 +1303,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; @@ -1378,7 +1320,21 @@ epic_init __P(( /* Start Rx process */ epic_start_activity(sc); + /* Reset all PHYs */ + mii = device_get_softc(sc->miibus); + 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); + } + + /* Fetch info from MII */ + mii_mediachg(mii); + mii_pollstat(mii); + splx(s); + return 0; } @@ -1387,264 +1343,31 @@ epic_init __P(( * access RXCON. */ static void -epic_set_rx_mode( - epic_softc_t * sc) +epic_set_rx_mode(sc) + 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; + u_int32_t flags = sc->sc_if.if_flags; + u_int32_t rxcon = RXCON_DEFAULT; - rxcon |= (flags & IFF_PROMISC)?RXCON_PROMISCUOUS_MODE:0; + rxcon |= (flags & IFF_PROMISC) ? RXCON_PROMISCUOUS_MODE : 0; CSR_WRITE_4( sc, RXCON, rxcon ); return; } -#if 0 -void -dump_phy_regs(epic_softc_t *sc) -{ - - 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)); -} -#endif - /* - * Synopsis: Reset PHY and do PHY-special initialization: + * Synopsis: Set transmit control register. Chip must be in idle state to + * access TXCON. */ static void -epic_init_phy __P(( - epic_softc_t * sc)) -{ - u_int32_t 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); - - /* Mask interrupts sources */ - PHY_WRITE_2(sc, QS6612_INTMASK, - PHY_READ_2(sc, QS6612_INTSTAT) | - INTMASK_THUNDERLAN | INTSTAT_AN_COMPLETE | - INTSTAT_LINK_STATUS ); - - /* Enable QS6612 extended cable length capabilites */ - /* PHY_WRITE_2(sc, QS6612_MCTL, */ - /* PHY_READ_2(sc, QS6612_MCTL) | MCTL_BTEXT); */ - - break; - } - default: - break; - } -} - -/* - * Synopsis: Set PHY to media type specified by IFF_LINK* flags or - * ifmedia structure. Chip must be in idle state to access TXCON. - */ -static void -epic_set_media_speed __P(( - 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; - - 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 */ - } - - epic_set_tx_mode(sc); - - 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 - */ -static 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; - } - -} - -/* - */ -static void -epic_set_tx_mode ( - epic_softc_t *sc ) +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); } /* @@ -1656,8 +1379,8 @@ epic_set_tx_mode ( * epic_start_activity() should help to do this. */ static void -epic_set_mc_table ( - epic_softc_t * sc) +epic_set_mc_table(sc) + epic_softc_t *sc; { struct ifnet *ifp = &sc->sc_if; @@ -1676,14 +1399,14 @@ epic_set_mc_table ( * Synopsis: Start receive process and transmit one, if they need. */ static void -epic_start_activity __P(( - epic_softc_t * sc)) +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))); } /* @@ -1691,8 +1414,8 @@ epic_start_activity __P(( * packet needs to be queued to stop Tx DMA. */ static void -epic_stop_activity __P(( - epic_softc_t * sc)) +epic_stop_activity(sc) + epic_softc_t *sc; { int i; @@ -1784,12 +1507,10 @@ epic_stop_activity __P(( /* * Synopsis: Shut down board and deallocates rings. - * - * splimp() invoked here */ static void -epic_stop __P(( - epic_softc_t * sc)) +epic_stop(sc) + epic_softc_t *sc; { int s; @@ -1825,8 +1546,8 @@ epic_stop __P(( * Synopsis: This function should free all memory allocated for rings. */ static void -epic_free_rings __P(( - epic_softc_t * sc)) +epic_free_rings(sc) + epic_softc_t *sc; { int i; @@ -1861,7 +1582,9 @@ epic_free_rings __P(( * are bounded and aligned properly. */ static int -epic_init_rings(epic_softc_t * sc){ +epic_init_rings(sc) + epic_softc_t *sc; +{ int i; sc->cur_rx = sc->cur_tx = sc->dirty_tx = sc->pending_txs = 0; @@ -1910,9 +1633,10 @@ epic_init_rings(epic_softc_t * sc){ /* * EEPROM operation functions */ -static void epic_write_eepromreg __P(( - epic_softc_t *sc, - u_int8_t val)) +static void +epic_write_eepromreg(sc, val) + epic_softc_t *sc; + u_int8_t val; { u_int16_t i; @@ -1925,16 +1649,16 @@ static void epic_write_eepromreg __P(( } static u_int8_t -epic_read_eepromreg __P(( - epic_softc_t *sc)) +epic_read_eepromreg(sc) + epic_softc_t *sc; { - return CSR_READ_1( sc,EECTL ); + return CSR_READ_1(sc, EECTL); } static u_int8_t -epic_eeprom_clock __P(( - epic_softc_t *sc, - u_int8_t val)) +epic_eeprom_clock(sc, val) + epic_softc_t *sc; + u_int8_t val; { epic_write_eepromreg( sc, val ); epic_write_eepromreg( sc, (val | 0x4) ); @@ -1944,9 +1668,9 @@ epic_eeprom_clock __P(( } static void -epic_output_eepromw __P(( - epic_softc_t * sc, - u_int16_t val)) +epic_output_eepromw(sc, val) + epic_softc_t *sc; + u_int16_t val; { int i; for( i = 0xF; i >= 0; i--){ @@ -1956,8 +1680,8 @@ epic_output_eepromw __P(( } static u_int16_t -epic_input_eepromw __P(( - epic_softc_t *sc)) +epic_input_eepromw(sc) + epic_softc_t *sc; { int i; int tmp; @@ -1973,9 +1697,9 @@ epic_input_eepromw __P(( } static int -epic_read_eeprom __P(( - epic_softc_t *sc, - u_int16_t loc)) +epic_read_eeprom(sc, loc) + epic_softc_t *sc; + u_int16_t loc; { u_int16_t dataval; u_int16_t read_cmd; @@ -1996,74 +1720,66 @@ epic_read_eeprom __P(( return dataval; } -static u_int16_t -epic_read_phy_register __P(( - epic_softc_t *sc, - u_int16_t loc)) +/* + * Here goes MII read/write routines + */ +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)); } static void -epic_write_phy_register __P(( - epic_softc_t * sc, - u_int16_t loc, - u_int16_t val)) +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; } -static void -epic_dump_state __P(( - epic_softc_t * sc)) +static int +epic_miibus_readreg(dev, phy, reg) + device_t 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 = device_get_softc(dev); + + return (PHY_READ_2(sc, phy, reg)); +} + +static int +epic_miibus_writereg(dev, phy, reg, data) + device_t dev; + int phy, reg, data; +{ + epic_softc_t *sc; + + sc = device_get_softc(dev); + + PHY_WRITE_2(sc, phy, reg, data); + + return (0); } diff --git a/sys/dev/tx/if_txreg.h b/sys/dev/tx/if_txreg.h index 49a3941..35685af 100644 --- a/sys/dev/tx/if_txreg.h +++ b/sys/dev/tx/if_txreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_txvar.h,v 1.3 1998/10/10 04:30:09 jason Exp $ */ +/* $OpenBSD: if_txvar.h,v 1.7 1999/11/17 05:21:19 jason Exp $ */ /* $FreeBSD$ */ /*- @@ -25,13 +25,15 @@ * 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. - * - * */ /* * Configuration */ +/*#define EPIC_DEBUG 1*/ +/*#define EPIC_USEIOSPACE 1*/ +#define EARLY_RX 1 + #ifndef ETHER_MAX_LEN #define ETHER_MAX_LEN 1518 #endif @@ -46,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 Sapce 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 @@ -115,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 @@ -200,80 +186,22 @@ #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 @@ -330,20 +258,20 @@ typedef struct { struct arpcom arpcom; #if defined(__OpenBSD__) struct device sc_dev; + mii_data_t sc_mii; +#else /* __FreeBSD__ */ + struct resource *res; + struct resource *irq; + + device_t miibus; + 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 - u_int32_t unit; + struct epic_rx_buffer rx_buffer[RX_RING_SIZE]; struct epic_tx_buffer tx_buffer[TX_RING_SIZE]; @@ -363,43 +291,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_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) \ @@ -412,8 +328,21 @@ 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( 0 == ((m)->m_flags & M_EXT) ) { \ + m_freem(m); \ + (m) = NULL; \ + } \ + } \ + } diff --git a/sys/dev/tx/if_txvar.h b/sys/dev/tx/if_txvar.h index 49a3941..35685af 100644 --- a/sys/dev/tx/if_txvar.h +++ b/sys/dev/tx/if_txvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_txvar.h,v 1.3 1998/10/10 04:30:09 jason Exp $ */ +/* $OpenBSD: if_txvar.h,v 1.7 1999/11/17 05:21:19 jason Exp $ */ /* $FreeBSD$ */ /*- @@ -25,13 +25,15 @@ * 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. - * - * */ /* * Configuration */ +/*#define EPIC_DEBUG 1*/ +/*#define EPIC_USEIOSPACE 1*/ +#define EARLY_RX 1 + #ifndef ETHER_MAX_LEN #define ETHER_MAX_LEN 1518 #endif @@ -46,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 Sapce 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 @@ -115,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 @@ -200,80 +186,22 @@ #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 @@ -330,20 +258,20 @@ typedef struct { struct arpcom arpcom; #if defined(__OpenBSD__) struct device sc_dev; + mii_data_t sc_mii; +#else /* __FreeBSD__ */ + struct resource *res; + struct resource *irq; + + device_t miibus; + 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 - u_int32_t unit; + struct epic_rx_buffer rx_buffer[RX_RING_SIZE]; struct epic_tx_buffer tx_buffer[TX_RING_SIZE]; @@ -363,43 +291,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_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) \ @@ -412,8 +328,21 @@ 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( 0 == ((m)->m_flags & M_EXT) ) { \ + m_freem(m); \ + (m) = NULL; \ + } \ + } \ + } |