Module Name: src
Committed By: dyoung
Date: Mon Jul 27 18:10:54 UTC 2009
Modified Files:
src/sys/dev/ic: gem.c gemvar.h
src/sys/dev/pci: if_gem_pci.c
src/sys/dev/sbus: if_gem_sbus.c
Log Message:
Do a complete device_t/softc split for the PCI attachment. I have
not finished the device_t/softc split for the SBus attachment
because I don't have an SBus gem(4) to test with.
Convert from legacy shutdownhooks to a PMF shutdown hook. Add PMF
suspend/resume handlers.
Factor a detachment hook out of gem_attach(). During device
attachment, track which resources are reserved in sc_attach_state,
and release only those resources during detachment.
Tested on gem0 and gem1 at pci1 on a Sun Fire V120.
To generate a diff of this commit:
cvs rdiff -u -r1.84 -r1.85 src/sys/dev/ic/gem.c
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/ic/gemvar.h
cvs rdiff -u -r1.35 -r1.36 src/sys/dev/pci/if_gem_pci.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/sbus/if_gem_sbus.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/gem.c
diff -u src/sys/dev/ic/gem.c:1.84 src/sys/dev/ic/gem.c:1.85
--- src/sys/dev/ic/gem.c:1.84 Tue May 12 14:25:17 2009
+++ src/sys/dev/ic/gem.c Mon Jul 27 18:10:53 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: gem.c,v 1.84 2009/05/12 14:25:17 cegger Exp $ */
+/* $NetBSD: gem.c,v 1.85 2009/07/27 18:10:53 dyoung Exp $ */
/*
*
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.84 2009/05/12 14:25:17 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.85 2009/07/27 18:10:53 dyoung Exp $");
#include "opt_inet.h"
#include "bpfilter.h"
@@ -88,12 +88,12 @@
#define TRIES 10000
+static void gem_inten(struct gem_softc *);
static void gem_start(struct ifnet *);
static void gem_stop(struct ifnet *, int);
int gem_ioctl(struct ifnet *, u_long, void *);
void gem_tick(void *);
void gem_watchdog(struct ifnet *);
-void gem_shutdown(void *);
void gem_pcs_start(struct gem_softc *sc);
void gem_pcs_stop(struct gem_softc *sc, int);
int gem_init(struct ifnet *);
@@ -126,6 +126,8 @@
int gem_ser_mediachange(struct ifnet *);
void gem_ser_mediastatus(struct ifnet *, struct ifmediareq *);
+static void gem_partial_detach(struct gem_softc *, enum gem_attach_stage);
+
struct mbuf *gem_get(struct gem_softc *, int, int);
int gem_put(struct gem_softc *, int, struct mbuf *);
void gem_read(struct gem_softc *, int, int);
@@ -145,6 +147,97 @@
#define ETHER_MIN_TX (ETHERMIN + sizeof(struct ether_header))
+int
+gem_detach(struct gem_softc *sc, int flags)
+{
+ char *nullbuf;
+ int i, rc;
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+
+ nullbuf =
+ (char *)sc->sc_control_data + sizeof(struct gem_control_data);
+
+ /*
+ * Free any resources we've allocated during the attach.
+ * Do this in reverse order and fall through.
+ */
+ switch (sc->sc_att_stage) {
+ case GEM_ATT_BACKEND_2:
+ case GEM_ATT_BACKEND_1:
+ case GEM_ATT_FINISHED:
+ gem_stop(&sc->sc_ethercom.ec_if, 1);
+
+#ifdef GEM_COUNTERS
+ for (i = __arraycount(sc->sc_ev_rxhist); --i >= 0; )
+ evcnt_detach(&sc->sc_ev_rxhist[i]);
+ evcnt_detach(&sc->sc_ev_rxnobuf);
+ evcnt_detach(&sc->sc_ev_rxfull);
+ evcnt_detach(&sc->sc_ev_rxint);
+ evcnt_detach(&sc->sc_ev_txint);
+#endif
+ evcnt_detach(&sc->sc_ev_intr);
+
+ callout_destroy(&sc->sc_tick_ch);
+#if NRND > 0
+ rnd_detach_source(&sc->rnd_source);
+#endif
+ ether_ifdetach(ifp);
+ if_detach(ifp);
+ ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
+ /*FALLTHROUGH*/
+ case GEM_ATT_MII:
+ sc->sc_att_stage = GEM_ATT_MII;
+ if ((rc = config_detach_children(sc->sc_dev, flags)) != 0)
+ return rc;
+ /*FALLTHROUGH*/
+ case GEM_ATT_7:
+ for (i = 0; i < GEM_NRXDESC; i++) {
+ if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
+ bus_dmamap_destroy(sc->sc_dmatag,
+ sc->sc_rxsoft[i].rxs_dmamap);
+ }
+ /*FALLTHROUGH*/
+ case GEM_ATT_6:
+ for (i = 0; i < GEM_TXQUEUELEN; i++) {
+ if (sc->sc_txsoft[i].txs_dmamap != NULL)
+ bus_dmamap_destroy(sc->sc_dmatag,
+ sc->sc_txsoft[i].txs_dmamap);
+ }
+ bus_dmamap_unload(sc->sc_dmatag, sc->sc_cddmamap);
+ /*FALLTHROUGH*/
+ case GEM_ATT_5:
+ bus_dmamap_destroy(sc->sc_dmatag, sc->sc_nulldmamap);
+ /*FALLTHROUGH*/
+ case GEM_ATT_4:
+ bus_dmamem_unmap(sc->sc_dmatag, nullbuf, ETHER_MIN_TX);
+ /*FALLTHROUGH*/
+ case GEM_ATT_3:
+ bus_dmamap_destroy(sc->sc_dmatag, sc->sc_cddmamap);
+ /*FALLTHROUGH*/
+ case GEM_ATT_2:
+ bus_dmamem_unmap(sc->sc_dmatag, sc->sc_control_data,
+ sizeof(struct gem_control_data));
+ /*FALLTHROUGH*/
+ case GEM_ATT_1:
+ bus_dmamem_free(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg);
+ /*FALLTHROUGH*/
+ case GEM_ATT_0:
+ sc->sc_att_stage = GEM_ATT_0;
+ /*FALLTHROUGH*/
+ case GEM_ATT_BACKEND_0:
+ break;
+ }
+ return 0;
+}
+
+static void
+gem_partial_detach(struct gem_softc *sc, enum gem_attach_stage stage)
+{
+ cfattach_t ca = device_cfattach(sc->sc_dev);
+
+ sc->sc_att_stage = stage;
+ (*ca->ca_detach)(sc->sc_dev, 0);
+}
/*
* gem_attach:
@@ -175,19 +268,21 @@
if ((error = bus_dmamem_alloc(sc->sc_dmatag,
sizeof(struct gem_control_data) + ETHER_MIN_TX, PAGE_SIZE,
0, &sc->sc_cdseg, 1, &sc->sc_cdnseg, 0)) != 0) {
- aprint_error_dev(&sc->sc_dev,
+ aprint_error_dev(sc->sc_dev,
"unable to allocate control data, error = %d\n",
error);
- goto fail_0;
+ gem_partial_detach(sc, GEM_ATT_0);
+ return;
}
/* XXX should map this in with correct endianness */
if ((error = bus_dmamem_map(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg,
sizeof(struct gem_control_data), (void **)&sc->sc_control_data,
BUS_DMA_COHERENT)) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to map control data, error = %d\n",
- error);
- goto fail_1;
+ aprint_error_dev(sc->sc_dev,
+ "unable to map control data, error = %d\n", error);
+ gem_partial_detach(sc, GEM_ATT_1);
+ return;
}
nullbuf =
@@ -196,34 +291,38 @@
if ((error = bus_dmamap_create(sc->sc_dmatag,
sizeof(struct gem_control_data), 1,
sizeof(struct gem_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to create control data DMA map, "
- "error = %d\n", error);
- goto fail_2;
+ aprint_error_dev(sc->sc_dev,
+ "unable to create control data DMA map, error = %d\n",
+ error);
+ gem_partial_detach(sc, GEM_ATT_2);
+ return;
}
if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_cddmamap,
sc->sc_control_data, sizeof(struct gem_control_data), NULL,
0)) != 0) {
- aprint_error_dev(&sc->sc_dev,
+ aprint_error_dev(sc->sc_dev,
"unable to load control data DMA map, error = %d\n",
error);
- goto fail_3;
+ gem_partial_detach(sc, GEM_ATT_3);
+ return;
}
memset(nullbuf, 0, ETHER_MIN_TX);
if ((error = bus_dmamap_create(sc->sc_dmatag,
ETHER_MIN_TX, 1, ETHER_MIN_TX, 0, 0, &sc->sc_nulldmamap)) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to create padding DMA map, "
- "error = %d\n", error);
- goto fail_4;
+ aprint_error_dev(sc->sc_dev,
+ "unable to create padding DMA map, error = %d\n", error);
+ gem_partial_detach(sc, GEM_ATT_4);
+ return;
}
if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_nulldmamap,
nullbuf, ETHER_MIN_TX, NULL, 0)) != 0) {
- aprint_error_dev(&sc->sc_dev,
- "unable to load padding DMA map, error = %d\n",
- error);
- goto fail_5;
+ aprint_error_dev(sc->sc_dev,
+ "unable to load padding DMA map, error = %d\n", error);
+ gem_partial_detach(sc, GEM_ATT_5);
+ return;
}
bus_dmamap_sync(sc->sc_dmatag, sc->sc_nulldmamap, 0, ETHER_MIN_TX,
@@ -247,9 +346,11 @@
ETHER_MAX_LEN_JUMBO, GEM_NTXSEGS,
ETHER_MAX_LEN_JUMBO, 0, 0,
&txs->txs_dmamap)) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to create tx DMA map %d, "
- "error = %d\n", i, error);
- goto fail_6;
+ aprint_error_dev(sc->sc_dev,
+ "unable to create tx DMA map %d, error = %d\n",
+ i, error);
+ gem_partial_detach(sc, GEM_ATT_6);
+ return;
}
SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
}
@@ -260,9 +361,11 @@
for (i = 0; i < GEM_NRXDESC; i++) {
if ((error = bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1,
MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to create rx DMA map %d, "
- "error = %d\n", i, error);
- goto fail_7;
+ aprint_error_dev(sc->sc_dev,
+ "unable to create rx DMA map %d, error = %d\n",
+ i, error);
+ gem_partial_detach(sc, GEM_ATT_7);
+ return;
}
sc->sc_rxsoft[i].rxs_mbuf = NULL;
}
@@ -290,12 +393,14 @@
if ((sc->sc_flags & (GEM_SERDES | GEM_SERIAL)) == 0) {
ifmedia_init(&mii->mii_media, IFM_IMASK, ether_mediachange,
ether_mediastatus);
- mii_attach(&sc->sc_dev, mii, 0xffffffff,
+ mii_attach(sc->sc_dev, mii, 0xffffffff,
MII_PHY_ANY, MII_OFFSET_ANY, MIIF_FORCEANEG);
if (LIST_EMPTY(&mii->mii_phys)) {
/* No PHY attached */
- aprint_error_dev(&sc->sc_dev, "PHY probe failed\n");
- goto fail_7;
+ aprint_error_dev(sc->sc_dev,
+ "PHY probe failed\n");
+ gem_partial_detach(sc, GEM_ATT_MII);
+ return;
} else {
struct mii_softc *child;
@@ -311,7 +416,7 @@
* by the GEM_MIF_CONFIG register.
*/
if (child->mii_phy > 1 || child->mii_inst > 0) {
- aprint_error_dev(&sc->sc_dev,
+ aprint_error_dev(sc->sc_dev,
"cannot accommodate MII device"
" %s at PHY %d, instance %d\n",
device_xname(child->mii_dev),
@@ -329,12 +434,14 @@
*/
if (sc->sc_phys[1]) {
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "using external PHY\n");
+ aprint_debug_dev(sc->sc_dev,
+ "using external PHY\n");
#endif
sc->sc_mif_config |= GEM_MIF_CONFIG_PHY_SEL;
} else {
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "using internal PHY\n");
+ aprint_debug_dev(sc->sc_dev,
+ "using internal PHY\n");
sc->sc_mif_config &= ~GEM_MIF_CONFIG_PHY_SEL;
#endif
}
@@ -363,7 +470,7 @@
GEM_MII_DATAPATH_SERIAL);
}
- aprint_normal_dev(&sc->sc_dev, "using external PCS %s: ",
+ aprint_normal_dev(sc->sc_dev, "using external PCS %s: ",
sc->sc_flags & GEM_SERDES ? "SERDES" : "Serialink");
ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO, 0, NULL);
@@ -393,7 +500,7 @@
*/
/* Announce ourselves. */
- aprint_normal_dev(&sc->sc_dev, "Ethernet address %s",
+ aprint_normal_dev(sc->sc_dev, "Ethernet address %s",
ether_sprintf(enaddr));
/* Get RX FIFO size */
@@ -406,20 +513,22 @@
aprint_normal(", %uKB TX fifo\n", v / 16);
/* Initialize ifnet structure. */
- strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ);
+ strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
ifp->if_softc = sc;
ifp->if_flags =
IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
sc->sc_if_flags = ifp->if_flags;
+#if 0
/*
* The GEM hardware supports basic TCP checksum offloading only.
* Several (all?) revisions (Sun rev. 01 and Apple rev. 00 and 80)
* have bugs in the receive checksum, so don't enable it for now.
+ */
if ((GEM_IS_SUN(sc) && sc->sc_chiprev != 1) ||
(GEM_IS_APPLE(sc) &&
(sc->sc_chiprev != 0 && sc->sc_chiprev != 0x80)))
ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Rx;
- */
+#endif
ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Tx;
ifp->if_start = gem_start;
ifp->if_ioctl = gem_ioctl;
@@ -453,93 +562,49 @@
ether_ifattach(ifp, enaddr);
ether_set_ifflags_cb(&sc->sc_ethercom, gem_ifflags_cb);
- sc->sc_sh = shutdownhook_establish(gem_shutdown, sc);
- if (sc->sc_sh == NULL)
- panic("gem_config: can't establish shutdownhook");
-
#if NRND > 0
- rnd_attach_source(&sc->rnd_source, device_xname(&sc->sc_dev),
+ rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
RND_TYPE_NET, 0);
#endif
evcnt_attach_dynamic(&sc->sc_ev_intr, EVCNT_TYPE_INTR,
- NULL, device_xname(&sc->sc_dev), "interrupts");
+ NULL, device_xname(sc->sc_dev), "interrupts");
#ifdef GEM_COUNTERS
evcnt_attach_dynamic(&sc->sc_ev_txint, EVCNT_TYPE_INTR,
- &sc->sc_ev_intr, device_xname(&sc->sc_dev), "tx interrupts");
+ &sc->sc_ev_intr, device_xname(sc->sc_dev), "tx interrupts");
evcnt_attach_dynamic(&sc->sc_ev_rxint, EVCNT_TYPE_INTR,
- &sc->sc_ev_intr, device_xname(&sc->sc_dev), "rx interrupts");
+ &sc->sc_ev_intr, device_xname(sc->sc_dev), "rx interrupts");
evcnt_attach_dynamic(&sc->sc_ev_rxfull, EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx ring full");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx ring full");
evcnt_attach_dynamic(&sc->sc_ev_rxnobuf, EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx malloc failure");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx malloc failure");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[0], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx 0desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx 0desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[1], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx 1desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx 1desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[2], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx 2desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx 2desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[3], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx 3desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx 3desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[4], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx >3desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx >3desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[5], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx >7desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx >7desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[6], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx >15desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx >15desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[7], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx >31desc");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx >31desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[8], EVCNT_TYPE_INTR,
- &sc->sc_ev_rxint, device_xname(&sc->sc_dev), "rx >63desc");
-#endif
-
-#if notyet
- /*
- * Add a suspend hook to make sure we come back up after a
- * resume.
- */
- sc->sc_powerhook = powerhook_establish(device_xname(&sc->sc_dev),
- gem_power, sc);
- if (sc->sc_powerhook == NULL)
- aprint_error_dev(&sc->sc_dev, "WARNING: unable to establish power hook\n");
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx >63desc");
#endif
callout_init(&sc->sc_tick_ch, 0);
- return;
- /*
- * Free any resources we've allocated during the failed attach
- * attempt. Do this in reverse order and fall through.
- */
- fail_7:
- for (i = 0; i < GEM_NRXDESC; i++) {
- if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
- bus_dmamap_destroy(sc->sc_dmatag,
- sc->sc_rxsoft[i].rxs_dmamap);
- }
- fail_6:
- for (i = 0; i < GEM_TXQUEUELEN; i++) {
- if (sc->sc_txsoft[i].txs_dmamap != NULL)
- bus_dmamap_destroy(sc->sc_dmatag,
- sc->sc_txsoft[i].txs_dmamap);
- }
- bus_dmamap_unload(sc->sc_dmatag, sc->sc_cddmamap);
- fail_5:
- bus_dmamap_destroy(sc->sc_dmatag, sc->sc_nulldmamap);
- fail_4:
- bus_dmamem_unmap(sc->sc_dmatag, (void *)nullbuf, ETHER_MIN_TX);
- fail_3:
- bus_dmamap_destroy(sc->sc_dmatag, sc->sc_cddmamap);
- fail_2:
- bus_dmamem_unmap(sc->sc_dmatag, (void *)sc->sc_control_data,
- sizeof(struct gem_control_data));
- fail_1:
- bus_dmamem_free(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg);
- fail_0:
+ sc->sc_att_stage = GEM_ATT_FINISHED;
+
return;
}
-
void
gem_tick(void *arg)
{
@@ -583,14 +648,14 @@
int s;
s = splnet();
- DPRINTF(sc, ("%s: gem_reset\n", device_xname(&sc->sc_dev)));
+ DPRINTF(sc, ("%s: gem_reset\n", device_xname(sc->sc_dev)));
gem_reset_rx(sc);
gem_reset_tx(sc);
/* Do a full reset */
bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX|GEM_RESET_TX);
if (!gem_bitwait(sc, h, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0))
- aprint_error_dev(&sc->sc_dev, "cannot reset device\n");
+ aprint_error_dev(sc->sc_dev, "cannot reset device\n");
splx(s);
}
@@ -624,10 +689,10 @@
static void
gem_stop(struct ifnet *ifp, int disable)
{
- struct gem_softc *sc = (struct gem_softc *)ifp->if_softc;
+ struct gem_softc *sc = ifp->if_softc;
struct gem_txsoft *txs;
- DPRINTF(sc, ("%s: gem_stop\n", device_xname(&sc->sc_dev)));
+ DPRINTF(sc, ("%s: gem_stop\n", device_xname(sc->sc_dev)));
callout_stop(&sc->sc_tick_ch);
if ((sc->sc_flags & (GEM_SERDES | GEM_SERIAL)) != 0)
@@ -684,14 +749,14 @@
bus_space_barrier(t, h, GEM_RX_CONFIG, 4, BUS_SPACE_BARRIER_WRITE);
/* Wait till it finishes */
if (!gem_bitwait(sc, h, GEM_RX_CONFIG, 1, 0))
- aprint_error_dev(&sc->sc_dev, "cannot disable read dma\n");
+ aprint_error_dev(sc->sc_dev, "cannot disable read dma\n");
/* Finally, reset the ERX */
bus_space_write_4(t, h2, GEM_RESET, GEM_RESET_RX);
bus_space_barrier(t, h, GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE);
/* Wait till it finishes */
if (!gem_bitwait(sc, h2, GEM_RESET, GEM_RESET_RX, 0)) {
- aprint_error_dev(&sc->sc_dev, "cannot reset receiver\n");
+ aprint_error_dev(sc->sc_dev, "cannot reset receiver\n");
return (1);
}
return (0);
@@ -790,7 +855,7 @@
bus_space_barrier(t, h, GEM_TX_CONFIG, 4, BUS_SPACE_BARRIER_WRITE);
/* Wait till it finishes */
if (!gem_bitwait(sc, h, GEM_TX_CONFIG, 1, 0))
- aprint_error_dev(&sc->sc_dev, "cannot disable read dma\n");
+ aprint_error_dev(sc->sc_dev, "cannot disable read dma\n");
/* Wait 5ms extra. */
delay(5000);
@@ -799,7 +864,7 @@
bus_space_barrier(t, h, GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE);
/* Wait till it finishes */
if (!gem_bitwait(sc, h2, GEM_RESET, GEM_RESET_TX, 0)) {
- aprint_error_dev(&sc->sc_dev, "cannot reset receiver\n");
+ aprint_error_dev(sc->sc_dev, "cannot reset receiver\n");
return (1);
}
return (0);
@@ -855,7 +920,7 @@
/*
* Initialize the transmit descriptor ring.
*/
- memset((void *)sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
+ memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
for (i = 0; i < GEM_NTXDESC; i++) {
sc->sc_txdescs[i].gd_flags = 0;
sc->sc_txdescs[i].gd_addr = 0;
@@ -874,7 +939,8 @@
rxs = &sc->sc_rxsoft[i];
if (rxs->rxs_mbuf == NULL) {
if ((error = gem_add_rxbuf(sc, i)) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to allocate or map rx "
+ aprint_error_dev(sc->sc_dev,
+ "unable to allocate or map rx "
"buffer %d, error = %d\n",
i, error);
/*
@@ -935,7 +1001,7 @@
uint32_t v;
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "gem_pcs_start()\n");
+ aprint_debug_dev(sc->sc_dev, "gem_pcs_start()\n");
#endif
/*
@@ -986,7 +1052,7 @@
bus_space_handle_t h = sc->sc_h1;
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "gem_pcs_stop()\n");
+ aprint_debug_dev(sc->sc_dev, "gem_pcs_stop()\n");
#endif
/* Tell link partner that we're going away */
@@ -1026,7 +1092,7 @@
int
gem_init(struct ifnet *ifp)
{
- struct gem_softc *sc = (struct gem_softc *)ifp->if_softc;
+ struct gem_softc *sc = ifp->if_softc;
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t h = sc->sc_h1;
int rc = 0, s;
@@ -1035,7 +1101,7 @@
s = splnet();
- DPRINTF(sc, ("%s: gem_init: calling stop\n", device_xname(&sc->sc_dev)));
+ DPRINTF(sc, ("%s: gem_init: calling stop\n", device_xname(sc->sc_dev)));
/*
* Initialization sequence. The numbered steps below correspond
* to the sequence outlined in section 6.3.5.1 in the Ethernet
@@ -1046,7 +1112,7 @@
/* step 1 & 2. Reset the Ethernet Channel */
gem_stop(ifp, 0);
gem_reset(sc);
- DPRINTF(sc, ("%s: gem_init: restarting\n", device_xname(&sc->sc_dev)));
+ DPRINTF(sc, ("%s: gem_init: restarting\n", device_xname(sc->sc_dev)));
/* Re-initialize the MIF */
gem_mifinit(sc);
@@ -1086,17 +1152,7 @@
bus_space_write_4(t, h, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0));
/* step 8. Global Configuration & Interrupt Mask */
- if ((sc->sc_flags & (GEM_SERDES | GEM_SERIAL)) != 0)
- v = GEM_INTR_PCS;
- else
- v = GEM_INTR_MIF;
- bus_space_write_4(t, h, GEM_INTMASK,
- ~(GEM_INTR_TX_INTME |
- GEM_INTR_TX_EMPTY |
- GEM_INTR_TX_MAC |
- GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF|
- GEM_INTR_RX_TAG_ERR | GEM_INTR_MAC_CONTROL|
- GEM_INTR_BERR | v));
+ gem_inten(sc);
bus_space_write_4(t, h, GEM_MAC_RX_MASK,
GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT);
bus_space_write_4(t, h, GEM_MAC_TX_MASK, 0xffff); /* XXX */
@@ -1277,7 +1333,7 @@
static void
gem_start(struct ifnet *ifp)
{
- struct gem_softc *sc = (struct gem_softc *)ifp->if_softc;
+ struct gem_softc *sc = ifp->if_softc;
struct mbuf *m0, *m;
struct gem_txsoft *txs;
bus_dmamap_t dmamap;
@@ -1295,7 +1351,7 @@
firsttx = sc->sc_txnext;
DPRINTF(sc, ("%s: gem_start: txfree %d, txnext %d\n",
- device_xname(&sc->sc_dev), ofree, firsttx));
+ device_xname(sc->sc_dev), ofree, firsttx));
/*
* Loop through the send queue, setting up transmit descriptors
@@ -1325,23 +1381,24 @@
(m0->m_pkthdr.len < ETHER_MIN_TX &&
dmamap->dm_nsegs == GEM_NTXSEGS)) {
if (m0->m_pkthdr.len > MCLBYTES) {
- aprint_error_dev(&sc->sc_dev, "unable to allocate jumbo Tx "
- "cluster\n");
+ aprint_error_dev(sc->sc_dev,
+ "unable to allocate jumbo Tx cluster\n");
IFQ_DEQUEUE(&ifp->if_snd, m0);
m_freem(m0);
continue;
}
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
- aprint_error_dev(&sc->sc_dev, "unable to allocate Tx mbuf\n");
+ aprint_error_dev(sc->sc_dev,
+ "unable to allocate Tx mbuf\n");
break;
}
MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner);
if (m0->m_pkthdr.len > MHLEN) {
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
- aprint_error_dev(&sc->sc_dev, "unable to allocate Tx "
- "cluster\n");
+ aprint_error_dev(sc->sc_dev,
+ "unable to allocate Tx cluster\n");
m_freem(m);
break;
}
@@ -1351,8 +1408,9 @@
error = bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap,
m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
if (error) {
- aprint_error_dev(&sc->sc_dev, "unable to load Tx buffer, "
- "error = %d\n", error);
+ aprint_error_dev(sc->sc_dev,
+ "unable to load Tx buffer, error = %d\n",
+ error);
break;
}
}
@@ -1523,20 +1581,20 @@
if (sc->sc_txfree != ofree) {
DPRINTF(sc, ("%s: packets enqueued, IC on %d, OWN on %d\n",
- device_xname(&sc->sc_dev), lasttx, firsttx));
+ device_xname(sc->sc_dev), lasttx, firsttx));
/*
* The entire packet chain is set up.
* Kick the transmitter.
*/
DPRINTF(sc, ("%s: gem_start: kicking tx %d\n",
- device_xname(&sc->sc_dev), nexttx));
+ device_xname(sc->sc_dev), nexttx));
bus_space_write_4(sc->sc_bustag, sc->sc_h1, GEM_TX_KICK,
sc->sc_txnext);
/* Set a watchdog timer in case the chip flakes out. */
ifp->if_timer = 5;
DPRINTF(sc, ("%s: gem_start: watchdog %d\n",
- device_xname(&sc->sc_dev), ifp->if_timer));
+ device_xname(sc->sc_dev), ifp->if_timer));
}
}
@@ -1554,7 +1612,7 @@
int progress = 0;
u_int32_t v;
- DPRINTF(sc, ("%s: gem_tint\n", device_xname(&sc->sc_dev)));
+ DPRINTF(sc, ("%s: gem_tint\n", device_xname(sc->sc_dev)));
/* Unload collision counters ... */
v = bus_space_read_4(t, mac, GEM_MAC_EXCESS_COLL_CNT) +
@@ -1658,7 +1716,7 @@
gem_start(ifp);
}
DPRINTF(sc, ("%s: gem_tint: watchdog %d\n",
- device_xname(&sc->sc_dev), ifp->if_timer));
+ device_xname(sc->sc_dev), ifp->if_timer));
return (1);
}
@@ -1678,7 +1736,7 @@
u_int32_t rxcomp;
int i, len, progress = 0;
- DPRINTF(sc, ("%s: gem_rint\n", device_xname(&sc->sc_dev)));
+ DPRINTF(sc, ("%s: gem_rint\n", device_xname(sc->sc_dev)));
/*
* Ignore spurious interrupt that sometimes occurs before
@@ -1724,7 +1782,8 @@
if (rxstat & GEM_RD_BAD_CRC) {
ifp->if_ierrors++;
- aprint_error_dev(&sc->sc_dev, "receive error: CRC error\n");
+ aprint_error_dev(sc->sc_dev,
+ "receive error: CRC error\n");
GEM_INIT_RXDESC(sc, i);
continue;
}
@@ -1871,7 +1930,7 @@
#ifdef GEM_DEBUG
if (ifp->if_flags & IFF_DEBUG)
printf("%s: rint: ring wrap\n",
- device_xname(&sc->sc_dev));
+ device_xname(sc->sc_dev));
#endif
}
sc->sc_rxptr = i;
@@ -1951,8 +2010,8 @@
m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
BUS_DMA_READ|BUS_DMA_NOWAIT);
if (error) {
- aprint_error_dev(&sc->sc_dev, "can't load rx DMA map %d, error = %d\n",
- idx, error);
+ aprint_error_dev(sc->sc_dev,
+ "can't load rx DMA map %d, error = %d\n", idx, error);
panic("gem_add_rxbuf"); /* XXX */
}
@@ -1972,7 +2031,7 @@
u_int32_t r, v;
if ((status & GEM_INTR_MIF) != 0) {
- printf("%s: XXXlink status changed\n", device_xname(&sc->sc_dev));
+ printf("%s: XXXlink status changed\n", device_xname(sc->sc_dev));
return (1);
}
@@ -1988,12 +2047,12 @@
r = GEM_SBUS_ERROR_STATUS;
bus_space_read_4(sc->sc_bustag, sc->sc_h2, r);
v = bus_space_read_4(sc->sc_bustag, sc->sc_h2, r);
- aprint_error_dev(&sc->sc_dev, "bus error interrupt: 0x%02x\n",
+ aprint_error_dev(sc->sc_dev, "bus error interrupt: 0x%02x\n",
v);
return (1);
}
snprintb(bits, sizeof(bits), GEM_INTR_BITS, status);
- printf("%s: status=%s\n", device_xname(&sc->sc_dev), bits);
+ printf("%s: status=%s\n", device_xname(sc->sc_dev), bits);
return (1);
}
@@ -2051,16 +2110,16 @@
if (v & GEM_MII_ANEG_FUL_DUPLX) {
sc->sc_mii.mii_media_active |= IFM_FDX;
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "link up: full duplex\n");
+ aprint_debug_dev(sc->sc_dev, "link up: full duplex\n");
#endif
} else if (v & GEM_MII_ANEG_HLF_DUPLX) {
sc->sc_mii.mii_media_active |= IFM_HDX;
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "link up: half duplex\n");
+ aprint_debug_dev(sc->sc_dev, "link up: half duplex\n");
#endif
} else {
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "duplex mismatch\n");
+ aprint_debug_dev(sc->sc_dev, "duplex mismatch\n");
#endif
}
gem_statuschange(sc);
@@ -2071,7 +2130,7 @@
sc->sc_mii.mii_media_active = IFM_ETHER | IFM_NONE;
sc->sc_mii.mii_media_status = IFM_AVALID;
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "link down\n");
+ aprint_debug_dev(sc->sc_dev, "link down\n");
#endif
gem_statuschange(sc);
@@ -2086,7 +2145,7 @@
int
gem_intr(void *v)
{
- struct gem_softc *sc = (struct gem_softc *)v;
+ struct gem_softc *sc = v;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t h = sc->sc_h1;
@@ -2105,7 +2164,7 @@
snprintb(bits, sizeof(bits), GEM_INTR_BITS, status);
#endif
DPRINTF(sc, ("%s: gem_intr: cplt 0x%x status %s\n",
- device_xname(&sc->sc_dev), (status >> 19), bits));
+ device_xname(sc->sc_dev), (status >> 19), bits));
if ((status & (GEM_INTR_RX_TAG_ERR | GEM_INTR_BERR)) != 0)
@@ -2127,7 +2186,7 @@
int txstat = bus_space_read_4(t, h, GEM_MAC_TX_STATUS);
if (txstat & ~GEM_MAC_TX_XMIT_DONE)
printf("%s: MAC tx fault, status %x\n",
- device_xname(&sc->sc_dev), txstat);
+ device_xname(sc->sc_dev), txstat);
if (txstat & (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG))
gem_init(ifp);
}
@@ -2144,7 +2203,7 @@
gem_reset_rxdma(sc);
} else if (rxstat & ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT))
printf("%s: MAC rx fault, status 0x%02x\n",
- device_xname(&sc->sc_dev), rxstat);
+ device_xname(sc->sc_dev), rxstat);
}
if (status & GEM_INTR_PCS) {
r |= gem_pint(sc);
@@ -2154,15 +2213,15 @@
if ((status & GEM_MAC_CONTROL_STATUS) != 0) {
status2 = bus_read_4(sc->sc_res[0], GEM_MAC_CONTROL_STATUS);
if ((status2 & GEM_MAC_PAUSED) != 0)
- aprintf_debug_dev(&sc->sc_dev, "PAUSE received (%d slots)\n",
+ aprintf_debug_dev(sc->sc_dev, "PAUSE received (%d slots)\n",
GEM_MAC_PAUSE_TIME(status2));
if ((status2 & GEM_MAC_PAUSE) != 0)
- aprintf_debug_dev(&sc->sc_dev, "transited to PAUSE state\n");
+ aprintf_debug_dev(sc->sc_dev, "transited to PAUSE state\n");
if ((status2 & GEM_MAC_RESUME) != 0)
- aprintf_debug_dev(&sc->sc_dev, "transited to non-PAUSE state\n");
+ aprintf_debug_dev(sc->sc_dev, "transited to non-PAUSE state\n");
}
if ((status & GEM_INTR_MIF) != 0)
- aprintf_debug_dev(&sc->sc_dev, "MIF interrupt\n");
+ aprintf_debug_dev(sc->sc_dev, "MIF interrupt\n");
*/
#if NRND > 0
rnd_add_uint32(&sc->rnd_source, status);
@@ -2182,7 +2241,7 @@
bus_space_read_4(sc->sc_bustag, sc->sc_h1, GEM_MAC_RX_STATUS),
bus_space_read_4(sc->sc_bustag, sc->sc_h1, GEM_MAC_RX_CONFIG)));
- log(LOG_ERR, "%s: device timeout\n", device_xname(&sc->sc_dev));
+ log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
++ifp->if_oerrors;
/* Try to get more packets going. */
@@ -2221,7 +2280,7 @@
static int
gem_mii_readreg(device_t self, int phy, int reg)
{
- struct gem_softc *sc = (void *)self;
+ struct gem_softc *sc = device_private(self);
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t mif = sc->sc_h1;
int n;
@@ -2244,14 +2303,14 @@
return (v & GEM_MIF_FRAME_DATA);
}
- printf("%s: mii_read timeout\n", device_xname(&sc->sc_dev));
+ printf("%s: mii_read timeout\n", device_xname(sc->sc_dev));
return (0);
}
static void
gem_mii_writereg(device_t self, int phy, int reg, int val)
{
- struct gem_softc *sc = (void *)self;
+ struct gem_softc *sc = device_private(self);
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t mif = sc->sc_h1;
int n;
@@ -2277,13 +2336,13 @@
return;
}
- printf("%s: mii_write timeout\n", device_xname(&sc->sc_dev));
+ printf("%s: mii_write timeout\n", device_xname(sc->sc_dev));
}
static void
-gem_mii_statchg(device_t dev)
+gem_mii_statchg(device_t self)
{
- struct gem_softc *sc = (void *)dev;
+ struct gem_softc *sc = device_private(self);
#ifdef GEM_DEBUG
int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
#endif
@@ -2339,13 +2398,13 @@
bus_space_barrier(t, mac, GEM_MAC_TX_CONFIG, 4,
BUS_SPACE_BARRIER_WRITE);
if (!gem_bitwait(sc, mac, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
- aprint_normal_dev(&sc->sc_dev, "cannot disable TX MAC\n");
+ aprint_normal_dev(sc->sc_dev, "cannot disable TX MAC\n");
bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, txcfg);
bus_space_write_4(t, mac, GEM_MAC_RX_CONFIG, 0);
bus_space_barrier(t, mac, GEM_MAC_RX_CONFIG, 4,
BUS_SPACE_BARRIER_WRITE);
if (!gem_bitwait(sc, mac, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
- aprint_normal_dev(&sc->sc_dev, "cannot disable RX MAC\n");
+ aprint_normal_dev(sc->sc_dev, "cannot disable RX MAC\n");
bus_space_write_4(t, mac, GEM_MAC_RX_CONFIG, rxcfg);
v = bus_space_read_4(t, mac, GEM_MAC_CONTROL_CONFIG) &
@@ -2415,7 +2474,7 @@
if (s == IFM_AUTO) {
if (sc->sc_mii_media != s) {
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev, "setting media to auto\n");
+ aprint_debug_dev(sc->sc_dev, "setting media to auto\n");
#endif
sc->sc_mii_media = s;
if (ifp->if_flags & IFF_UP) {
@@ -2431,7 +2490,7 @@
if (sc->sc_mii_media != t) {
sc->sc_mii_media = t;
#ifdef GEM_DEBUG
- aprint_debug_dev(&sc->sc_dev,
+ aprint_debug_dev(sc->sc_dev,
"setting media to 1000baseSX-%s\n",
t == IFM_FDX ? "FDX" : "HDX");
#endif
@@ -2502,14 +2561,57 @@
return (error);
}
+static void
+gem_inten(struct gem_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_bustag;
+ bus_space_handle_t h = sc->sc_h1;
+ uint32_t v;
-void
-gem_shutdown(void *arg)
+ if ((sc->sc_flags & (GEM_SERDES | GEM_SERIAL)) != 0)
+ v = GEM_INTR_PCS;
+ else
+ v = GEM_INTR_MIF;
+ bus_space_write_4(t, h, GEM_INTMASK,
+ ~(GEM_INTR_TX_INTME |
+ GEM_INTR_TX_EMPTY |
+ GEM_INTR_TX_MAC |
+ GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF|
+ GEM_INTR_RX_TAG_ERR | GEM_INTR_MAC_CONTROL|
+ GEM_INTR_BERR | v));
+}
+
+bool
+gem_resume(device_t self PMF_FN_ARGS)
+{
+ struct gem_softc *sc = device_private(self);
+
+ gem_inten(sc);
+
+ return true;
+}
+
+bool
+gem_suspend(device_t self PMF_FN_ARGS)
+{
+ struct gem_softc *sc = device_private(self);
+ bus_space_tag_t t = sc->sc_bustag;
+ bus_space_handle_t h = sc->sc_h1;
+
+ bus_space_write_4(t, h, GEM_INTMASK, ~(uint32_t)0);
+
+ return true;
+}
+
+bool
+gem_shutdown(device_t self, int howto)
{
- struct gem_softc *sc = (struct gem_softc *)arg;
+ struct gem_softc *sc = device_private(self);
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
gem_stop(ifp, 1);
+
+ return true;
}
/*
@@ -2601,41 +2703,3 @@
sc->sc_if_flags = ifp->if_flags;
bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v);
}
-
-#if notyet
-
-/*
- * gem_power:
- *
- * Power management (suspend/resume) hook.
- */
-void
-gem_power(int why, void *arg)
-{
- struct gem_softc *sc = arg;
- struct ifnet *ifp = &sc->sc_ethercom.ec_if;
- int s;
-
- s = splnet();
- switch (why) {
- case PWR_SUSPEND:
- case PWR_STANDBY:
- gem_stop(ifp, 1);
- if (sc->sc_power != NULL)
- (*sc->sc_power)(sc, why);
- break;
- case PWR_RESUME:
- if (ifp->if_flags & IFF_UP) {
- if (sc->sc_power != NULL)
- (*sc->sc_power)(sc, why);
- gem_init(ifp);
- }
- break;
- case PWR_SOFTSUSPEND:
- case PWR_SOFTSTANDBY:
- case PWR_SOFTRESUME:
- break;
- }
- splx(s);
-}
-#endif
Index: src/sys/dev/ic/gemvar.h
diff -u src/sys/dev/ic/gemvar.h:1.18 src/sys/dev/ic/gemvar.h:1.19
--- src/sys/dev/ic/gemvar.h:1.18 Fri Feb 1 10:53:25 2008
+++ src/sys/dev/ic/gemvar.h Mon Jul 27 18:10:53 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: gemvar.h,v 1.18 2008/02/01 10:53:25 jdc Exp $ */
+/* $NetBSD: gemvar.h,v 1.19 2009/07/27 18:10:53 dyoung Exp $ */
/*
*
@@ -110,11 +110,27 @@
bus_dmamap_t rxs_dmamap; /* our DMA map */
};
+enum gem_attach_stage {
+ GEM_ATT_BACKEND_2 = 0
+ , GEM_ATT_BACKEND_1
+ , GEM_ATT_FINISHED
+ , GEM_ATT_MII
+ , GEM_ATT_7
+ , GEM_ATT_6
+ , GEM_ATT_5
+ , GEM_ATT_4
+ , GEM_ATT_3
+ , GEM_ATT_2
+ , GEM_ATT_1
+ , GEM_ATT_0
+ , GEM_ATT_BACKEND_0
+};
+
/*
* Software state per device.
*/
struct gem_softc {
- struct device sc_dev; /* generic device information */
+ device_t sc_dev; /* generic device information */
struct ethercom sc_ethercom; /* ethernet common data */
struct mii_data sc_mii; /* MII media control */
struct callout sc_tick_ch; /* tick callout */
@@ -125,6 +141,7 @@
bus_dmamap_t sc_dmamap; /* bus dma handle */
bus_space_handle_t sc_h1; /* bus space handle for bank 1 regs */
bus_space_handle_t sc_h2; /* bus space handle for bank 2 regs */
+ bus_size_t sc_size; /* bank 1 size */
int sc_phys[2]; /* MII instance -> PHY map */
@@ -156,9 +173,6 @@
#define GEM_SERDES 0x0008 /* use the SERDES */
#define GEM_SERIAL 0x0010 /* use the serial link */
- void *sc_sdhook; /* shutdown hook */
- void *sc_powerhook; /* power management hook */
-
/*
* Ring buffer DMA stuff.
*/
@@ -214,6 +228,8 @@
struct evcnt sc_ev_rxfull;
struct evcnt sc_ev_rxhist[9];
#endif
+
+ enum gem_attach_stage sc_att_stage;
};
#ifdef GEM_COUNTERS
@@ -291,8 +307,12 @@
} while (0)
#ifdef _KERNEL
+bool gem_shutdown(device_t, int);
+bool gem_suspend(device_t PMF_FN_PROTO);
+bool gem_resume(device_t PMF_FN_PROTO);
void gem_attach(struct gem_softc *, const uint8_t *);
int gem_intr(void *);
+int gem_detach(struct gem_softc *, int);
void gem_reset(struct gem_softc *);
#endif /* _KERNEL */
Index: src/sys/dev/pci/if_gem_pci.c
diff -u src/sys/dev/pci/if_gem_pci.c:1.35 src/sys/dev/pci/if_gem_pci.c:1.36
--- src/sys/dev/pci/if_gem_pci.c:1.35 Tue May 12 08:23:00 2009
+++ src/sys/dev/pci/if_gem_pci.c Mon Jul 27 18:10:53 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gem_pci.c,v 1.35 2009/05/12 08:23:00 cegger Exp $ */
+/* $NetBSD: if_gem_pci.c,v 1.36 2009/07/27 18:10:53 dyoung Exp $ */
/*
*
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gem_pci.c,v 1.35 2009/05/12 08:23:00 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gem_pci.c,v 1.36 2009/07/27 18:10:53 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -91,20 +91,28 @@
struct gem_pci_softc {
struct gem_softc gsc_gem; /* GEM device */
void *gsc_ih;
+ pci_chipset_tag_t gsc_pc;
+ pci_intr_handle_t gsc_handle;
};
-int gem_match_pci(device_t, cfdata_t, void *);
-void gem_attach_pci(device_t, device_t, void *);
-
-CFATTACH_DECL(gem_pci, sizeof(struct gem_pci_softc),
- gem_match_pci, gem_attach_pci, NULL, NULL);
+static bool gem_pci_estintr(struct gem_pci_softc *);
+static bool gem_pci_suspend(device_t PMF_FN_PROTO);
+static bool gem_pci_resume(device_t PMF_FN_PROTO);
+static int gem_pci_detach(device_t, int);
+
+int gem_pci_match(device_t, cfdata_t, void *);
+void gem_pci_attach(device_t, device_t, void *);
+
+CFATTACH_DECL3_NEW(gem_pci, sizeof(struct gem_pci_softc),
+ gem_pci_match, gem_pci_attach, gem_pci_detach, NULL, NULL, NULL,
+ DVF_DETACH_SHUTDOWN);
/*
* Attach routines need to be split out to different bus-specific files.
*/
int
-gem_match_pci(device_t parent, cfdata_t cf, void *aux)
+gem_pci_match(device_t parent, cfdata_t cf, void *aux)
{
struct pci_attach_args *pa = aux;
@@ -157,13 +165,11 @@
}
void
-gem_attach_pci(device_t parent, device_t self, void *aux)
+gem_pci_attach(device_t parent, device_t self, void *aux)
{
struct pci_attach_args *pa = aux;
struct gem_pci_softc *gsc = device_private(self);
struct gem_softc *sc = &gsc->gsc_gem;
- pci_intr_handle_t ih;
- const char *intrstr;
char devinfo[256];
uint8_t enaddr[ETHER_ADDR_LEN];
#if GEM_USE_LOCAL_MAC_ADDRESS
@@ -192,6 +198,7 @@
aprint_naive(": Ethernet controller\n");
+ sc->sc_dev = self;
pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
sc->sc_chiprev = PCI_REVISION(pa->pa_class);
aprint_normal(": %s (rev. 0x%02x)\n", devinfo, sc->sc_chiprev);
@@ -226,7 +233,7 @@
}
if (sc->sc_variant == GEM_UNKNOWN) {
- aprint_error_dev(&sc->sc_dev, "unknown adaptor\n");
+ aprint_error_dev(sc->sc_dev, "unknown adaptor\n");
return;
}
@@ -235,14 +242,14 @@
/* XXX Need to check for a 64-bit mem BAR? */
if (pci_mapreg_map(pa, PCI_GEM_BASEADDR,
PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
- &sc->sc_bustag, &sc->sc_h1, NULL, NULL) != 0)
+ &sc->sc_bustag, &sc->sc_h1, NULL, &sc->sc_size) != 0)
{
- aprint_error_dev(&sc->sc_dev, "unable to map device registers\n");
+ aprint_error_dev(sc->sc_dev, "unable to map device registers\n");
return;
}
if (bus_space_subregion(sc->sc_bustag, sc->sc_h1,
GEM_PCI_BANK2_OFFSET, GEM_PCI_BANK2_SIZE, &sc->sc_h2)) {
- aprint_error_dev(&sc->sc_dev, "unable to create bank 2 subregion\n");
+ aprint_error_dev(sc->sc_dev, "unable to create bank 2 subregion\n");
return;
}
@@ -285,7 +292,7 @@
}
#ifdef GEM_DEBUG
/* PROM dump */
- printf("%s: PROM dump (0x0000 to %04lx)\n", device_xname(&sc->sc_dev),
+ printf("%s: PROM dump (0x0000 to %04lx)\n", device_xname(sc->sc_dev),
(sizeof buf) - 1);
i = 0;
j = 0;
@@ -368,7 +375,7 @@
node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag);
if (node == 0) {
- aprint_error_dev(&sc->sc_dev, "unable to locate OpenFirmware node\n");
+ aprint_error_dev(sc->sc_dev, "unable to locate OpenFirmware node\n");
return;
}
@@ -378,25 +385,94 @@
OF_getprop(node, "local-mac-address", enaddr, sizeof(enaddr));
}
#else
- printf("%s: no Ethernet address found\n", device_xname(&sc->sc_dev));
+ printf("%s: no Ethernet address found\n", device_xname(sc->sc_dev));
#endif /* macppc */
#endif /* __sparc__ */
- if (pci_intr_map(pa, &ih) != 0) {
- aprint_error_dev(&sc->sc_dev, "unable to map interrupt\n");
+ if (pci_intr_map(pa, &gsc->gsc_handle) != 0) {
+ aprint_error_dev(sc->sc_dev, "unable to map interrupt\n");
return;
}
- intrstr = pci_intr_string(pa->pa_pc, ih);
- gsc->gsc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, gem_intr, sc);
+ gsc->gsc_pc = pa->pa_pc;
+ gem_pci_estintr(gsc);
+
+ /* Finish off the attach. */
+ gem_attach(sc, enaddr);
+
+ if (!pmf_device_register1(sc->sc_dev, gem_pci_suspend, gem_pci_resume,
+ gem_shutdown)) {
+ aprint_error_dev(sc->sc_dev,
+ "could not establish power handlers\n");
+ } else
+ pmf_class_network_register(sc->sc_dev, &sc->sc_ethercom.ec_if);
+}
+
+static bool
+gem_pci_suspend(device_t self PMF_FN_ARGS)
+{
+ struct gem_pci_softc *gsc = device_private(self);
+
+ if (gsc->gsc_ih != NULL) {
+ pci_intr_disestablish(gsc->gsc_pc, gsc->gsc_ih);
+ gsc->gsc_ih = NULL;
+ }
+
+ return true;
+}
+
+static bool
+gem_pci_estintr(struct gem_pci_softc *gsc)
+{
+ struct gem_softc *sc = &gsc->gsc_gem;
+ const char *intrstr;
+
+ intrstr = pci_intr_string(gsc->gsc_pc, gsc->gsc_handle);
+ gsc->gsc_ih = pci_intr_establish(gsc->gsc_pc, gsc->gsc_handle, IPL_NET,
+ gem_intr, sc);
if (gsc->gsc_ih == NULL) {
- aprint_error_dev(&sc->sc_dev, "unable to establish interrupt");
+ aprint_error_dev(sc->sc_dev, "unable to establish interrupt");
if (intrstr != NULL)
aprint_normal(" at %s", intrstr);
aprint_normal("\n");
- return;
+ return false;
}
- aprint_normal_dev(&sc->sc_dev, "interrupting at %s\n", intrstr);
+ aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
+ return true;
+}
- /* Finish off the attach. */
- gem_attach(sc, enaddr);
+static bool
+gem_pci_resume(device_t self PMF_FN_ARGS)
+{
+ struct gem_pci_softc *gsc = device_private(self);
+
+ return gem_pci_estintr(gsc);
+}
+
+static int
+gem_pci_detach(device_t self, int flags)
+{
+ int rc;
+ struct gem_pci_softc *gsc = device_private(self);
+ struct gem_softc *sc = &gsc->gsc_gem;
+
+ switch (sc->sc_att_stage) {
+ case GEM_ATT_BACKEND_2:
+ pmf_device_deregister(self);
+ sc->sc_att_stage = GEM_ATT_FINISHED;
+ /*FALLTHROUGH*/
+ default:
+ if ((rc = gem_detach(sc, flags)) != 0)
+ return rc;
+ /*FALLTHROUGH*/
+ case GEM_ATT_BACKEND_1:
+ if (gsc->gsc_ih != NULL)
+ pci_intr_disestablish(gsc->gsc_pc, gsc->gsc_ih);
+
+ bus_space_unmap(sc->sc_bustag, sc->sc_h1, sc->sc_size);
+ /*FALLTHROUGH*/
+ case GEM_ATT_BACKEND_0:
+ sc->sc_att_stage = GEM_ATT_BACKEND_0;
+ break;
+ }
+ return 0;
}
Index: src/sys/dev/sbus/if_gem_sbus.c
diff -u src/sys/dev/sbus/if_gem_sbus.c:1.10 src/sys/dev/sbus/if_gem_sbus.c:1.11
--- src/sys/dev/sbus/if_gem_sbus.c:1.10 Tue May 12 14:43:59 2009
+++ src/sys/dev/sbus/if_gem_sbus.c Mon Jul 27 18:10:54 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gem_sbus.c,v 1.10 2009/05/12 14:43:59 cegger Exp $ */
+/* $NetBSD: if_gem_sbus.c,v 1.11 2009/07/27 18:10:54 dyoung Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gem_sbus.c,v 1.10 2009/05/12 14:43:59 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gem_sbus.c,v 1.11 2009/07/27 18:10:54 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -85,10 +85,12 @@
gemattach_sbus(device_t parent, device_t self, void *aux)
{
struct sbus_attach_args *sa = aux;
- struct gem_sbus_softc *gsc = (void *)self;
+ struct gem_sbus_softc *gsc = device_private(self);
struct gem_softc *sc = &gsc->gsc_gem;
uint8_t enaddr[ETHER_ADDR_LEN];
+ sc->sc_dev = self;
+
/* Pass on the bus tags */
sc->sc_bustag = sa->sa_bustag;
sc->sc_dmatag = sa->sa_dmatag;