diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2007-04-20 13:46:41 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2007-04-20 13:46:41 +0000 |
commit | 5f54c56c238f7174ef82a202058cb52745d73b07 (patch) | |
tree | e43ad58fa8f3566228d498c99c2a011def99114d /sys/dev | |
parent | 4bdfd3fbeab33036af17ac4e5edbe0d998486d0c (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.c | 92 |
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 */ |