summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/files.pci4
-rw-r--r--sys/dev/pci/if_tx.c1550
-rw-r--r--sys/dev/pci/if_txvar.h250
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