summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2001-02-23 22:59:10 +0000
committerJason Wright <jason@cvs.openbsd.org>2001-02-23 22:59:10 +0000
commitf11ead6113a58fdcdc76d818fe3474daca24a643 (patch)
tree4cf9b7d670aa2751796bfec0e9beb6fa1009d8b6 /sys/dev
parent932d1d55cda1f371a6e1a03522c02ae0560e785b (diff)
Merge with FreeBSD:
more portable between fbsd and obsd real mii support prefer memory mapped registers (if configuration supports it)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_tx.c481
-rw-r--r--sys/dev/pci/if_txvar.h40
2 files changed, 294 insertions, 227 deletions
diff --git a/sys/dev/pci/if_tx.c b/sys/dev/pci/if_tx.c
index 13873d386b6..e0dd9eeb05e 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.12 2001/02/20 19:39:43 mickey Exp $ */
-/* $FreeBSD: src/sys/pci/if_tx.c,v 1.40 2000/07/13 22:54:34 archie Exp $ */
+/* $OpenBSD: if_tx.c,v 1.13 2001/02/23 22:59:09 jason Exp $ */
+/* $FreeBSD: src/sys/pci/if_tx.c,v 1.45 2001/02/07 20:11:02 semenu Exp $ */
/*-
* Copyright (c) 1997 Semen Ustimenko (semen@iclub.nsu.ru)
@@ -35,8 +35,6 @@
*
* todo:
* Implement FULL IFF_MULTICAST support.
- * Refactor out Free/Open compat cruft
- * Modularize, Modularize, and Modularize some more
*
*/
@@ -78,6 +76,9 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+
+#include <dev/mii/lxtphyreg.h>
#include "miibus_if.h"
@@ -119,6 +120,8 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+#include <dev/mii/lxtphyreg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -133,19 +136,11 @@ MODULE_DEPEND(tx, miibus, 1, 1, 1);
#if defined(__FreeBSD__)
#define EPIC_INTR_RET_TYPE void
-#else /* __OpenBSD__ */
-#define EPIC_INTR_RET_TYPE int
-#endif
-
-#if defined(__FreeBSD__)
#define EPIC_MIIBUS_WRITEREG_RET_TYPE int
-#else /* __OpenBSD__ */
-#define EPIC_MIIBUS_WRITEREG_RET_TYPE void
-#endif
-
-#if defined(__FreeBSD__)
#define EPIC_STATIC static
#else /* __OpenBSD__ */
+#define EPIC_INTR_RET_TYPE int
+#define EPIC_MIIBUS_WRITEREG_RET_TYPE void
#define EPIC_STATIC
#endif
@@ -155,7 +150,6 @@ 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 *));
@@ -177,12 +171,14 @@ 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 EPIC_MIIBUS_WRITEREG_RET_TYPE epic_miibus_writereg __P((struct device*, int, int, int));
EPIC_STATIC void epic_miibus_statchg __P((struct device *));
+EPIC_STATIC void epic_miibus_mediainit __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 *));
+EPIC_STATIC void epic_tick __P((void *));
/* -------------------------------------------------------------------------
OS-specific part
@@ -191,9 +187,9 @@ EPIC_STATIC void epic_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
#if defined(__OpenBSD__)
/* -----------------------------OpenBSD------------------------------------- */
-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 *));
+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
@@ -203,7 +199,7 @@ struct cfdriver tx_cd = {
};
/* Synopsis: Check if device id corresponds with SMC83C170 id. */
-EPIC_STATIC int
+int
epic_openbsd_probe(
struct device *parent,
void *match,
@@ -219,7 +215,7 @@ epic_openbsd_probe(
return 0;
}
-EPIC_STATIC void
+void
epic_openbsd_attach(
struct device *parent,
struct device *self,
@@ -231,66 +227,50 @@ epic_openbsd_attach(
pci_intr_handle_t ih;
const char *intrstr = NULL;
struct ifnet *ifp;
- bus_addr_t iobase;
bus_size_t iosize;
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);
-#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(pa->pa_iot, iobase, iosize, 0, &sc->sc_sh)) {
- printf(": can't map i/o space\n");
- return;
- }
- 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");
+ if ((command & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) == 0) {
+ printf(": neither i/o nor mem enabled\n");
return;
}
- if( bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->sc_sh)) {
- printf(": can't map i/o space\n");
- return;
+
+ if (command & PCI_COMMAND_MEM_ENABLE) {
+ if (pci_mapreg_map(pa, PCI_BASEMEM, PCI_MAPREG_TYPE_MEM, 0,
+ &sc->sc_st, &sc->sc_sh, NULL, &iosize)) {
+ printf(": can't map mem space\n");
+ return;
+ }
+ } else {
+ if (pci_mapreg_map(pa, PCI_BASEIO, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_st, &sc->sc_sh, NULL, &iosize)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
}
- sc->sc_st = pa->pa_memt;
-#endif
- /*
- * Set up if
- */
ifp = &sc->sc_if;
- bcopy(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
- */
+ /* Fetch card id */
+ sc->cardvend = pci_conf_read(pc, pa->pa_tag, PCI_SUBVEND_0);
+ sc->cardid = pci_conf_read(pc, pa->pa_tag, PCI_SUBDEV_0);
+
+ /* 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");
@@ -306,34 +286,25 @@ epic_openbsd_attach(
printf("\n");
return;
}
- printf(": %s",intrstr);
/* Display some info */
- printf(" address %s\n",ether_sprintf(sc->sc_macaddr));
-
- /*
- * ifmedia setup
- */
- ifmedia_init(&sc->miibus.mii_media, 0, epic_ifmedia_upd, epic_ifmedia_sts);
+ printf(": %s address %s\n", intrstr, ether_sprintf(sc->sc_macaddr));
- /*
- * mii setup
- */
+ /* Init ifmedia interface */
+ ifmedia_init(&sc->miibus.mii_media, 0,
+ epic_ifmedia_upd, epic_ifmedia_sts);
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);
-
+ mii_phy_probe(self, &sc->miibus, 0xffffffff);
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 {
+ } else
ifmedia_set(&sc->miibus.mii_media, IFM_ETHER|IFM_AUTO);
- }
+ timeout_set(&sc->sc_tmo, epic_tick, sc);
/* Attach os interface and bpf */
if_attach(ifp);
@@ -343,10 +314,8 @@ epic_openbsd_attach(
shutdownhook_establish(epic_openbsd_shutdown, sc);
}
-/*
- * Simply call epic_stop()
- */
-EPIC_STATIC void
+/* Simple call epic_stop() */
+void
epic_openbsd_shutdown(
void *sc)
{
@@ -356,14 +325,13 @@ epic_openbsd_shutdown(
#else /* __FreeBSD__ */
/* -----------------------------FreeBSD------------------------------------- */
-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*));
+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));
-EPIC_STATIC device_method_t epic_methods[] = {
+static device_method_t epic_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, epic_freebsd_probe),
DEVMETHOD(device_attach, epic_freebsd_attach),
@@ -383,26 +351,26 @@ EPIC_STATIC device_method_t epic_methods[] = {
{ 0, 0 }
};
-EPIC_STATIC driver_t epic_driver = {
+static driver_t epic_driver = {
"tx",
epic_methods,
sizeof(epic_softc_t)
};
-EPIC_STATIC devclass_t epic_devclass;
+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);
-EPIC_STATIC struct epic_type epic_devs[] = {
+static struct epic_type epic_devs[] = {
{ SMC_VENDORID, SMC_DEVICEID_83C170,
"SMC EtherPower II 10/100" },
{ 0, 0, NULL }
};
-EPIC_STATIC int
+static int
epic_freebsd_probe(dev)
- struct device* dev;
+ device_t dev;
{
struct epic_type *t;
@@ -416,9 +384,9 @@ epic_freebsd_probe(dev)
return(ENXIO);
}
-EPIC_STATIC struct epic_type *
+static struct epic_type *
epic_devtype(dev)
- struct device* dev;
+ device_t dev;
{
struct epic_type *t;
@@ -446,9 +414,9 @@ epic_devtype(dev)
* Do FreeBSD-specific attach routine, like map registers, alloc softc
* structure and etc.
*/
-EPIC_STATIC int
+static int
epic_freebsd_attach(dev)
- struct device* dev;
+ device_t dev;
{
struct ifnet *ifp;
epic_softc_t *sc;
@@ -536,6 +504,13 @@ epic_freebsd_attach(dev)
goto fail;
}
+ /* 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.
*/
@@ -559,6 +534,11 @@ epic_freebsd_attach(dev)
goto fail;
}
+ /* Fetch card id */
+ sc->cardvend = pci_read_config(sc->dev, PCIR_SUBVEND_0, 2);
+ sc->cardid = pci_read_config(sc->dev, PCIR_SUBDEV_0, 2);
+ printf("vend/id(%x/%x) ", sc->cardvend, sc->cardid);
+
/* Display ethernet address ,... */
device_printf(dev, "address %6D,", sc->sc_macaddr, ":");
@@ -572,7 +552,7 @@ epic_freebsd_attach(dev)
if( ' ' == (u_int8_t)tmp ) break;
printf("%c",(u_int8_t)tmp);
}
- printf ("\n");
+ printf("\n");
/* Attach to OS's managers */
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
@@ -587,9 +567,9 @@ fail:
/*
* Detach driver and free resources
*/
-EPIC_STATIC int
+static int
epic_freebsd_detach(dev)
- struct device* dev;
+ device_t dev;
{
struct ifnet *ifp;
epic_softc_t *sc;
@@ -622,35 +602,12 @@ epic_freebsd_detach(dev)
#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;
-}
-/*
* 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;
+ device_t dev;
{
epic_softc_t *sc;
@@ -663,12 +620,11 @@ epic_freebsd_shutdown(dev)
#endif /* __OpenBSD__ */
/* ------------------------------------------------------------------------
- OS-independent part
+ OS-independing part
------------------------------------------------------------------------ */
/*
* This is if_ioctl handler.
- * This is a mess
*/
EPIC_STATIC int
epic_ifioctl(ifp, command, data)
@@ -677,9 +633,9 @@ epic_ifioctl(ifp, command, data)
caddr_t data;
{
epic_softc_t *sc = ifp->if_softc;
- int x, error = 0;
struct mii_data *mii;
struct ifreq *ifr = (struct ifreq *) data;
+ int x, error = 0;
x = splimp();
@@ -784,7 +740,7 @@ epic_ifioctl(ifp, command, data)
/*
* OS-independed part of attach process. allocate memory for descriptors
- * and frag lists, wake up chip, and read MAC address.
+ * and frag lists, wake up chip, read MAC address and PHY identyfier.
* Return -1 on failure.
*/
EPIC_STATIC int
@@ -794,9 +750,6 @@ epic_common_attach(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;
@@ -808,45 +761,45 @@ epic_common_attach(sc)
}
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;
- /*
- * reset the chip
- */
- epic_reset( sc );
+ /* Bring the chip out of low-power mode. */
+ CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET);
+ DELAY(500);
- /*
- * Read mac address from EEPROM
- */
+ /* Workaround for Application Note 7-15 */
+ for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST);
+
+ /* 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);
- /*
- * Set defaults
- */
+ /* Set defaults */
sc->tx_threshold = TRANSMIT_THRESHOLD;
sc->txcon = TXCON_DEFAULT;
+ sc->miicfg = MIICFG_SMI_ENABLE;
+ sc->phyid = EPIC_UNKN_PHY;
+ sc->serinst = -1;
+
+ if (sc->cardvend != SMC_VENDORID)
+ printf(EPIC_FORMAT ": unknown card vendor 0x%04x\n", EPIC_ARGS(sc), sc->cardvend);
return 0;
}
/*
* This is if_start handler. It takes mbufs from if_snd queue
- * and quque them for transmit, one by one, until TX ring become full
- * or quque become empty.
+ * and queue them for transmit, one by one, until TX ring become full
+ * or queue become empty.
*/
EPIC_STATIC void
epic_ifstart(ifp)
@@ -1047,7 +1000,6 @@ epic_tx_done(sc)
/*
* Interrupt function
- * This is a mess
*/
EPIC_STATIC EPIC_INTR_RET_TYPE
epic_intr(arg)
@@ -1188,41 +1140,126 @@ epic_ifmedia_upd(ifp)
epic_softc_t *sc;
struct mii_data *mii;
struct ifmedia *ifm;
+ struct mii_softc *miisc;
+ int cfg, media;
sc = ifp->if_softc;
mii = epic_mii_ptr(sc);
ifm = &mii->mii_media;
+ media = ifm->ifm_cur->ifm_media;
/* Do not do anything if interface is not up */
if(!(ifp->if_flags & IFF_UP))
return (0);
- 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);
+ /*
+ * Lookup current selected PHY
+ */
+ if (IFM_INST(media) == sc->serinst) {
+ sc->phyid = EPIC_SERIAL;
+ sc->physc = NULL;
+ } else {
+ /* If we're not selecting serial interface, select MII mode */
+ sc->miicfg &= ~MIICFG_SERIAL_ENABLE;
+ CSR_WRITE_4(sc, MIICFG, sc->miicfg);
- /* Select BNC */
- CSR_WRITE_4(sc, MIICFG, MIICFG_SERIAL_ENABLE |
- MIICFG_694_ENABLE | MIICFG_SMI_ENABLE);
+ dprintf((EPIC_FORMAT ": MII selected\n", EPIC_ARGS(sc)));
- /* Update txcon register */
- epic_miibus_statchg(&sc->dev);
+ /* Default to unknown PHY */
+ sc->phyid = EPIC_UNKN_PHY;
- return (0);
- } else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) {
- /* Select MII */
- CSR_WRITE_4(sc, MIICFG, MIICFG_SMI_ENABLE);
+ /* Lookup selected PHY */
+ for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
+ miisc = LIST_NEXT(miisc, mii_list)) {
+ if (IFM_INST(media) == miisc->mii_inst) {
+ sc->physc = miisc;
+ break;
+ }
+ }
- /* Give it to miibus... */
- mii_mediachg(mii);
+ /* Identify selected PHY */
+ if (sc->physc) {
+ int id1, id2, model, oui;
- return (0);
+ id1 = PHY_READ(sc->physc, MII_PHYIDR1);
+ id2 = PHY_READ(sc->physc, MII_PHYIDR2);
+
+ oui = MII_OUI(id1, id2);
+ model = MII_MODEL(id2);
+ switch (oui) {
+ case MII_OUI_QUALSEMI:
+ if (model == MII_MODEL_QUALSEMI_QS6612)
+ sc->phyid = EPIC_QS6612_PHY;
+ break;
+ case MII_OUI_xxALTIMA:
+ if (model == MII_MODEL_xxALTIMA_AC101)
+ sc->phyid = EPIC_AC101_PHY;
+ break;
+ case MII_OUI_xxLEVEL1:
+ if (model == MII_MODEL_xxLEVEL1_LXT970)
+ sc->phyid = EPIC_LXT970_PHY;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Do PHY specific card setup
+ */
+
+ /* Call this, to isolate all not selected PHYs and
+ * set up selected
+ */
+ mii_mediachg(mii);
+
+ /* Do our own setup */
+ switch (sc->phyid) {
+ case EPIC_QS6612_PHY:
+ break;
+ case EPIC_AC101_PHY:
+ /* We have to powerup fiber tranceivers */
+ if (IFM_SUBTYPE(media) == IFM_100_FX)
+ sc->miicfg |= MIICFG_694_ENABLE;
+ else
+ sc->miicfg &= ~MIICFG_694_ENABLE;
+ CSR_WRITE_4(sc, MIICFG, sc->miicfg);
+
+ break;
+ case EPIC_LXT970_PHY:
+ /* We have to powerup fiber tranceivers */
+ cfg = PHY_READ(sc->physc, MII_LXTPHY_CONFIG);
+ if (IFM_SUBTYPE(media) == IFM_100_FX)
+ cfg |= CONFIG_LEDC1 | CONFIG_LEDC0;
+ else
+ cfg &= ~(CONFIG_LEDC1 | CONFIG_LEDC0);
+ PHY_WRITE(sc->physc, MII_LXTPHY_CONFIG, cfg);
+
+ break;
+ case EPIC_SERIAL:
+ /* Select serial PHY, (10base2/BNC usually) */
+ sc->miicfg |= MIICFG_694_ENABLE | MIICFG_SERIAL_ENABLE;
+ CSR_WRITE_4(sc, MIICFG, sc->miicfg);
+
+ /* There is no driver to fill this */
+ mii->mii_media_active = media;
+ mii->mii_media_status = 0;
+
+ /* We need to call this manualy as i wasn't called
+ * in mii_mediachg()
+ */
+ epic_miibus_statchg(&sc->dev);
+
+ dprintf((EPIC_FORMAT ": SERIAL selected\n", EPIC_ARGS(sc)));
+
+ break;
+ default:
+ printf(EPIC_FORMAT ": ERROR! Unknown PHY selected\n", EPIC_ARGS(sc));
+ return (EINVAL);
}
- return(EINVAL);
+ return(0);
}
/*
@@ -1241,6 +1278,7 @@ epic_ifmedia_sts(ifp, ifmr)
mii = epic_mii_ptr(sc);
ifm = &mii->mii_media;
+ /* Nothing should be selected if interface is down */
if(!(ifp->if_flags & IFF_UP)) {
ifmr->ifm_active = IFM_NONE;
ifmr->ifm_status = 0;
@@ -1248,18 +1286,13 @@ epic_ifmedia_sts(ifp, ifmr)
return;
}
- 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) {
+ /* Call underlying pollstat, if not serial PHY */
+ if (sc->phyid != EPIC_SERIAL)
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;
- }
+
+ /* Simply copy media info */
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
return;
}
@@ -1273,20 +1306,34 @@ epic_miibus_statchg(dev)
{
epic_softc_t *sc;
struct mii_data *mii;
+ int media;
sc = epic_dev_ptr(dev);
mii = epic_mii_ptr(sc);
+ media = mii->mii_media_active;
sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX);
- /*
- * If we are in full-duplex mode or loopback operation,
+ /* 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))
+ if (IFM_OPTIONS(media) & (IFM_FDX | IFM_LOOP))
sc->txcon |= TXCON_FULL_DUPLEX;
- if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX)
+ /* On some cards we need manualy set fullduplex led */
+ if (sc->cardid == SMC9432FTX ||
+ sc->cardid == SMC9432FTX_SC) {
+ if (IFM_OPTIONS(media) & IFM_FDX)
+ sc->miicfg |= MIICFG_694_ENABLE;
+ else
+ sc->miicfg &= ~MIICFG_694_ENABLE;
+
+ CSR_WRITE_4(sc, MIICFG, sc->miicfg);
+ }
+
+ /* Update baudrate */
+ if (IFM_SUBTYPE(media) == IFM_100_TX ||
+ IFM_SUBTYPE(media) == IFM_100_FX)
sc->sc_if.if_baudrate = 100000000;
else
sc->sc_if.if_baudrate = 10000000;
@@ -1296,7 +1343,6 @@ epic_miibus_statchg(dev)
return;
}
-#if defined(__FreeBSD__)
EPIC_STATIC void epic_miibus_mediainit(dev)
struct device* dev;
{
@@ -1304,20 +1350,29 @@ EPIC_STATIC void epic_miibus_mediainit(dev)
struct mii_data *mii;
struct ifmedia *ifm;
int media;
-
+
sc = epic_dev_ptr(dev);
mii = epic_mii_ptr(sc);
ifm = &mii->mii_media;
+ /* Add Serial Media Interface if present, this applies to
+ * SMC9432BTX serie
+ */
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));
+ /* Store its instance */
+ sc->serinst = mii->mii_instance++;
+
+ /* Add as 10base2/BNC media */
+ media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc->serinst);
ifmedia_add(ifm, media, 0, NULL);
+
+ /* Report to user */
+ printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc));
}
return;
}
-#endif
+
/*
* Reset chip, allocate rings, and update media.
@@ -1328,7 +1383,7 @@ epic_init(sc)
{
struct ifnet *ifp = &sc->sc_if;
struct mii_data *mii;
- int s;
+ int s,i;
s = splimp();
@@ -1337,7 +1392,7 @@ epic_init(sc)
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 );
@@ -1353,8 +1408,6 @@ epic_init(sc)
/* 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 ) ) {
@@ -1383,10 +1436,13 @@ epic_init(sc)
/* Enable interrupts by setting the interrupt mask. */
CSR_WRITE_4( sc, INTMASK,
- INTSTAT_RCC | INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE |
- INTSTAT_TXC | INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
+ INTSTAT_RCC | /* INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE | */
+ /* INTSTAT_TXC | */ INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
INTSTAT_FATAL);
+ /* Acknowledge all pending interrupts */
+ CSR_WRITE_4(sc, INTSTAT, CSR_READ_4(sc, INTSTAT));
+
/* Enable interrupts, set for PCI read multiple and etc */
CSR_WRITE_4( sc, GENCTL,
GENCTL_ENABLE_INTERRUPT | GENCTL_MEMORY_READ_MULTIPLE |
@@ -1406,8 +1462,7 @@ epic_init(sc)
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))
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
mii_phy_reset(miisc);
}
@@ -1416,34 +1471,12 @@ epic_init(sc)
splx(s);
+ timeout_add(&sc->sc_tmo, hz);
+
return 0;
}
/*
- * Reset the epic chip
- */
-EPIC_STATIC void epic_reset(sc)
- epic_softc_t *sc;
-{
- int i;
-
- /* 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 );
-
- /*
- * 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);
-
- /* Wake up */
- CSR_WRITE_4( sc, GENCTL, 0 );
-
- /* Workaround for Application Note 7-15 */
- for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST);
-}
-/*
* Synopsis: calculate and set Rx mode. Chip must be in idle state to
* access RXCON.
*/
@@ -1619,6 +1652,8 @@ epic_stop(sc)
{
int s;
+ timeout_del(&sc->sc_tmo);
+
s = splimp();
sc->sc_if.if_timer = 0;
@@ -1890,3 +1925,15 @@ epic_miibus_writereg(dev, phy, reg, data)
return (0);
#endif
}
+
+EPIC_STATIC void
+epic_tick(vsc)
+ void *vsc;
+{
+ epic_softc_t *sc = vsc;
+ struct mii_data *mii;
+
+ mii = epic_mii_ptr(sc);
+ if (sc->phyid != EPIC_SERIAL)
+ mii_tick(mii);
+}
diff --git a/sys/dev/pci/if_txvar.h b/sys/dev/pci/if_txvar.h
index 286a6467cd5..cbd9e28a797 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.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 $ */
+/* $OpenBSD: if_txvar.h,v 1.9 2001/02/23 22:59:09 jason Exp $ */
+/* $FreeBSD: src/sys/pci/if_txvar.h,v 1.8 2001/02/07 20:11:02 semenu Exp $ */
/*-
* Copyright (c) 1997 Semen Ustimenko
@@ -257,18 +257,33 @@ struct epic_tx_buffer {
* epic_rx_desc, epic_tx_desc, epic_frag_list - must be aligned on dword
*/
-/*
- * Driver status structure
- * There are macros to handle the access of Free|Open specific fields.
- */
-
+/* PHY, known by tx driver */
+#define EPIC_UNKN_PHY 0x0000
+#define EPIC_QS6612_PHY 0x0001
+#define EPIC_AC101_PHY 0x0002
+#define EPIC_LXT970_PHY 0x0003
+#define EPIC_SERIAL 0x0004
+
+#define SMC9432DMT 0xA010
+#define SMC9432TX 0xA011
+#define SMC9032TXM 0xA012
+#define SMC9032TX 0xA013
+#define SMC9432TXPWR 0xA014
+#define SMC9432BTX 0xA015
+#define SMC9432FTX 0xA016
+#define SMC9432FTX_SC 0xA017
+#define SMC9432TX_XG_ADHOC 0xA020
+#define SMC9434TX_XG_ADHOC 0xA021
+#define SMC9432FTX_ADHOC 0xA022
+#define SMC9432BTX1 0xA024
+
+/* Driver status structure */
typedef struct {
#if defined(__OpenBSD__)
struct device dev;
-
struct arpcom arpcom;
-
mii_data_t miibus;
+ struct timeout sc_tmo;
#else /* __FreeBSD__ */
struct resource *res;
struct resource *irq;
@@ -294,11 +309,16 @@ typedef struct {
u_int32_t flags;
u_int32_t tx_threshold;
u_int32_t txcon;
- u_int32_t phyid;
+ u_int32_t miicfg;
u_int32_t cur_tx;
u_int32_t cur_rx;
u_int32_t dirty_tx;
u_int32_t pending_txs;
+ u_int16_t cardvend;
+ u_int16_t cardid;
+ struct mii_softc *physc;
+ u_int32_t phyid;
+ int serinst;
void *pool;
} epic_softc_t;