summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2007-04-20 13:46:41 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2007-04-20 13:46:41 +0000
commit5f54c56c238f7174ef82a202058cb52745d73b07 (patch)
treee43ad58fa8f3566228d498c99c2a011def99114d /sys/dev
parent4bdfd3fbeab33036af17ac4e5edbe0d998486d0c (diff)
this implements up and down routines for the interface. currently when
brought up they allocate all four fifos and set the interface flags. when theyre brought down they clear the flags, wait for the tx fifos to drain, and then free all the fifos. interrupts are not yet dealt with.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_tht.c92
1 files changed, 89 insertions, 3 deletions
diff --git a/sys/dev/pci/if_tht.c b/sys/dev/pci/if_tht.c
index 22c05a4bd58..286424ea608 100644
--- a/sys/dev/pci/if_tht.c
+++ b/sys/dev/pci/if_tht.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tht.c,v 1.33 2007/04/20 07:10:56 dlg Exp $ */
+/* $OpenBSD: if_tht.c,v 1.34 2007/04/20 13:46:40 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -405,6 +405,9 @@ int tht_ioctl(struct ifnet *, u_long, caddr_t);
void tht_start(struct ifnet *);
void tht_watchdog(struct ifnet *);
+void tht_up(struct tht_softc *);
+void tht_down(struct tht_softc *);
+
/* ifmedia operations */
int tht_media_change(struct ifnet *);
void tht_media_status(struct ifnet *, struct ifmediareq *);
@@ -606,9 +609,9 @@ tht_mountroot(void *arg)
printf("%s: firmware load %s\n", DEVNAME(sc),
(tht_fw_load(sc) == 0) ? "succeeded" : "failed");
- tht_fifo_free(sc, &sc->sc_txt);
-
tht_sw_reset(sc);
+
+ tht_fifo_free(sc, &sc->sc_txt);
}
int
@@ -622,6 +625,7 @@ tht_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
{
struct tht_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)addr;
+ struct ifaddr *ifa;
int error;
int s;
@@ -634,6 +638,28 @@ tht_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
}
switch (cmd) {
+ case SIOCSIFADDR:
+ ifa = (struct ifaddr *)addr;
+
+#ifdef INET
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ arp_ifinit(&sc->sc_ac, ifa);
+#endif
+
+ ifp->if_flags |= IFF_UP;
+ /* FALLTHROUGH */
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_flags & IFF_RUNNING)
+ /* multicast/promisc change */;
+ else
+ tht_up(sc);
+ } else {
+ if (ifp->if_flags & IFF_RUNNING)
+ tht_down(sc);
+ }
+ break;
+
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
@@ -649,6 +675,66 @@ tht_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
}
void
+tht_up(struct tht_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_ac.ac_if;
+
+ if (ISSET(ifp->if_flags, IFF_RUNNING)) {
+ printf("%s: interface is already up\n");
+ return;
+ }
+
+ if (tht_fifo_alloc(sc, &sc->sc_txt, &tht_txt_desc) != 0)
+ return;
+ if (tht_fifo_alloc(sc, &sc->sc_rxf, &tht_rxf_desc) != 0)
+ goto free_txt;
+ if (tht_fifo_alloc(sc, &sc->sc_rxd, &tht_rxd_desc) != 0)
+ goto free_rxf;
+ if (tht_fifo_alloc(sc, &sc->sc_txf, &tht_txf_desc) != 0)
+ goto free_rxd;
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ /* enable interrupts */
+
+ return;
+
+free_rxd:
+ tht_fifo_free(sc, &sc->sc_rxd);
+free_rxf:
+ tht_fifo_free(sc, &sc->sc_rxf);
+free_txt:
+ tht_fifo_free(sc, &sc->sc_txt);
+
+ tht_sw_reset(sc);
+}
+
+void
+tht_down(struct tht_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_ac.ac_if;
+
+ if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
+ printf("%s: interface is already down\n");
+ return;
+ }
+
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+
+ while (tht_fifo_ready(sc, &sc->sc_txt) < sc->sc_txt.tf_len &&
+ tht_fifo_ready(sc, &sc->sc_txf) < sc->sc_txf.tf_len)
+ tsleep(sc, 0, "thtdown", hz);
+
+ tht_sw_reset(sc);
+
+ tht_fifo_free(sc, &sc->sc_txf);
+ tht_fifo_free(sc, &sc->sc_rxd);
+ tht_fifo_free(sc, &sc->sc_rxf);
+ tht_fifo_free(sc, &sc->sc_txt);
+}
+
+void
tht_start(struct ifnet *ifp)
{
/* do nothing */