summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
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 */