Annotation of sys/dev/ic/pdq_ifsubr.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pdq_ifsubr.c,v 1.19 2006/05/30 21:33:59 fkr Exp $ */
! 2: /* $NetBSD: pdq_ifsubr.c,v 1.5 1996/05/20 00:26:21 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. The name of the author may not be used to endorse or promote products
! 14: * derived from this software without specific prior written permission
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 26: *
! 27: * Id: pdq_ifsubr.c,v 1.6 1996/05/16 14:25:26 thomas Exp
! 28: *
! 29: */
! 30:
! 31: /*
! 32: * DEC PDQ FDDI Controller; code for BSD derived operating systems
! 33: *
! 34: * This module provide bus independent BSD specific O/S functions.
! 35: * (ie. it provides an ifnet interface to the rest of the system)
! 36: */
! 37:
! 38:
! 39: #include <sys/param.h>
! 40: #include <sys/kernel.h>
! 41: #include <sys/mbuf.h>
! 42: #include <sys/protosw.h>
! 43: #include <sys/socket.h>
! 44: #include <sys/ioctl.h>
! 45: #include <sys/errno.h>
! 46: #include <sys/malloc.h>
! 47: #if defined(__FreeBSD__)
! 48: #include <sys/devconf.h>
! 49: #elif defined(__NetBSD__) || defined(__OpenBSD__)
! 50: #include <sys/device.h>
! 51: #endif
! 52:
! 53: #include <net/if.h>
! 54: #include <net/if_types.h>
! 55: #include <net/if_dl.h>
! 56: #include <net/route.h>
! 57:
! 58: #include "bpfilter.h"
! 59: #if NBPFILTER > 0
! 60: #include <net/bpf.h>
! 61: #endif
! 62:
! 63: #ifdef INET
! 64: #include <netinet/in.h>
! 65: #include <netinet/in_systm.h>
! 66: #include <netinet/in_var.h>
! 67: #include <netinet/ip.h>
! 68: #include <netinet/if_ether.h>
! 69: #endif
! 70: #if defined(__FreeBSD__)
! 71: #include <netinet/if_fddi.h>
! 72: #else
! 73: #include <net/if_fddi.h>
! 74: #endif
! 75:
! 76: #include <uvm/uvm_extern.h>
! 77:
! 78: #include "pdqvar.h"
! 79: #include "pdqreg.h"
! 80:
! 81: void
! 82: pdq_ifinit(
! 83: pdq_softc_t *sc)
! 84: {
! 85: if (sc->sc_if.if_flags & IFF_UP) {
! 86: sc->sc_if.if_flags |= IFF_RUNNING;
! 87: if (sc->sc_if.if_flags & IFF_PROMISC) {
! 88: sc->sc_pdq->pdq_flags |= PDQ_PROMISC;
! 89: } else {
! 90: sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC;
! 91: }
! 92: if (sc->sc_if.if_flags & IFF_ALLMULTI) {
! 93: sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI;
! 94: } else {
! 95: sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI;
! 96: }
! 97: if (sc->sc_if.if_flags & IFF_LINK1) {
! 98: sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT;
! 99: } else {
! 100: sc->sc_pdq->pdq_flags &= ~PDQ_PASS_SMT;
! 101: }
! 102: sc->sc_pdq->pdq_flags |= PDQ_RUNNING;
! 103: pdq_run(sc->sc_pdq);
! 104: } else {
! 105: sc->sc_if.if_flags &= ~IFF_RUNNING;
! 106: sc->sc_pdq->pdq_flags &= ~PDQ_RUNNING;
! 107: pdq_stop(sc->sc_pdq);
! 108: }
! 109: }
! 110:
! 111: void
! 112: pdq_ifwatchdog(
! 113: struct ifnet *ifp)
! 114: {
! 115: /*
! 116: * No progress was made on the transmit queue for PDQ_OS_TX_TRANSMIT
! 117: * seconds. Remove all queued packets.
! 118: */
! 119:
! 120: ifp->if_flags &= ~IFF_OACTIVE;
! 121: ifp->if_timer = 0;
! 122: IFQ_PURGE(&ifp->if_snd);
! 123: }
! 124:
! 125: ifnet_ret_t
! 126: pdq_ifstart(
! 127: struct ifnet *ifp)
! 128: {
! 129: pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_arpcom.ac_if));
! 130: struct mbuf *m;
! 131: int tx = 0;
! 132:
! 133: if ((ifp->if_flags & IFF_RUNNING) == 0)
! 134: return;
! 135:
! 136: if (sc->sc_if.if_timer == 0)
! 137: sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
! 138:
! 139: if ((sc->sc_pdq->pdq_flags & PDQ_TXOK) == 0) {
! 140: sc->sc_if.if_flags |= IFF_OACTIVE;
! 141: return;
! 142: }
! 143: for (;; tx = 1) {
! 144: IFQ_POLL(&ifp->if_snd, m);
! 145: if (m == NULL)
! 146: break;
! 147:
! 148: if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) {
! 149: ifp->if_flags |= IFF_OACTIVE;
! 150: break;
! 151: }
! 152:
! 153: IFQ_DEQUEUE(&ifp->if_snd, m);
! 154: }
! 155: if (tx)
! 156: PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
! 157: }
! 158:
! 159: void
! 160: pdq_os_receive_pdu(
! 161: pdq_t *pdq,
! 162: struct mbuf *m,
! 163: size_t pktlen)
! 164: {
! 165: pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
! 166: struct fddi_header *fh = mtod(m, struct fddi_header *);
! 167:
! 168: sc->sc_if.if_ipackets++;
! 169: #if NBPFILTER > 0
! 170: if (sc->sc_bpf != NULL)
! 171: PDQ_BPF_MTAP(sc, m, BPF_DIRECTION_IN);
! 172: if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
! 173: m_freem(m);
! 174: return;
! 175: }
! 176: #endif
! 177:
! 178: m->m_data += sizeof(struct fddi_header);
! 179: m->m_len -= sizeof(struct fddi_header);
! 180: m->m_pkthdr.len = pktlen - sizeof(struct fddi_header);
! 181: m->m_pkthdr.rcvif = &sc->sc_if;
! 182: fddi_input(&sc->sc_if, fh, m);
! 183: }
! 184:
! 185: void
! 186: pdq_os_restart_transmitter(
! 187: pdq_t *pdq)
! 188: {
! 189: pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
! 190: sc->sc_if.if_flags &= ~IFF_OACTIVE;
! 191: if (!IFQ_IS_EMPTY(&sc->sc_if.if_snd)) {
! 192: sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
! 193: pdq_ifstart(&sc->sc_if);
! 194: } else {
! 195: sc->sc_if.if_timer = 0;
! 196: }
! 197: }
! 198:
! 199: void
! 200: pdq_os_transmit_done(
! 201: pdq_t *pdq,
! 202: struct mbuf *m)
! 203: {
! 204: pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
! 205: #if NBPFILTER > 0
! 206: if (sc->sc_bpf != NULL)
! 207: PDQ_BPF_MTAP(sc, m, BPF_DIRECTION_OUT);
! 208: #endif
! 209: m_freem(m);
! 210: sc->sc_if.if_opackets++;
! 211: }
! 212:
! 213: void
! 214: pdq_os_addr_fill(
! 215: pdq_t *pdq,
! 216: pdq_lanaddr_t *addr,
! 217: size_t num_addrs)
! 218: {
! 219: pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
! 220: struct ether_multistep step;
! 221: struct ether_multi *enm;
! 222:
! 223: ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
! 224: while (enm != NULL && num_addrs > 0) {
! 225: ((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) enm->enm_addrlo)[0];
! 226: ((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) enm->enm_addrlo)[1];
! 227: ((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) enm->enm_addrlo)[2];
! 228: ETHER_NEXT_MULTI(step, enm);
! 229: addr++;
! 230: num_addrs--;
! 231: }
! 232: }
! 233:
! 234: int
! 235: pdq_ifioctl(
! 236: struct ifnet *ifp,
! 237: ioctl_cmd_t cmd,
! 238: caddr_t data)
! 239: {
! 240: pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_arpcom.ac_if));
! 241: int s, error = 0;
! 242:
! 243: s = splnet();
! 244:
! 245: switch (cmd) {
! 246: case SIOCSIFADDR: {
! 247: struct ifaddr *ifa = (struct ifaddr *)data;
! 248:
! 249: ifp->if_flags |= IFF_UP;
! 250: switch(ifa->ifa_addr->sa_family) {
! 251: #if defined(INET)
! 252: case AF_INET: {
! 253: pdq_ifinit(sc);
! 254: arp_ifinit(&sc->sc_arpcom, ifa);
! 255: break;
! 256: }
! 257: #endif /* INET */
! 258:
! 259: #if defined(NS)
! 260: /* This magic copied from if_is.c; I don't use XNS,
! 261: * so I have no way of telling if this actually
! 262: * works or not.
! 263: */
! 264: case AF_NS: {
! 265: struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
! 266: if (ns_nullhost(*ina)) {
! 267: ina->x_host = *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
! 268: } else {
! 269: ifp->if_flags &= ~IFF_RUNNING;
! 270: bcopy((caddr_t)ina->x_host.c_host,
! 271: (caddr_t)sc->sc_arpcom.ac_enaddr,
! 272: sizeof sc->sc_arpcom.ac_enaddr);
! 273: }
! 274:
! 275: pdq_ifinit(sc);
! 276: break;
! 277: }
! 278: #endif /* NS */
! 279:
! 280: default: {
! 281: pdq_ifinit(sc);
! 282: break;
! 283: }
! 284: }
! 285: break;
! 286: }
! 287:
! 288: case SIOCSIFFLAGS: {
! 289: pdq_ifinit(sc);
! 290: break;
! 291: }
! 292:
! 293: case SIOCADDMULTI:
! 294: case SIOCDELMULTI: {
! 295: /*
! 296: * Update multicast listeners
! 297: */
! 298: if (cmd == SIOCADDMULTI)
! 299: error = ether_addmulti((struct ifreq *)data, &sc->sc_arpcom);
! 300: else
! 301: error = ether_delmulti((struct ifreq *)data, &sc->sc_arpcom);
! 302:
! 303: if (error == ENETRESET) {
! 304: if (sc->sc_if.if_flags & IFF_RUNNING)
! 305: pdq_run(sc->sc_pdq);
! 306: error = 0;
! 307: }
! 308: break;
! 309: }
! 310:
! 311: default: {
! 312: error = EINVAL;
! 313: break;
! 314: }
! 315: }
! 316:
! 317: splx(s);
! 318: return error;
! 319: }
! 320:
! 321: #ifndef IFF_NOTRAILERS
! 322: #define IFF_NOTRAILERS 0
! 323: #endif
! 324:
! 325: void
! 326: pdq_ifattach(
! 327: pdq_softc_t *sc,
! 328: ifnet_ret_t (*ifwatchdog)(int unit))
! 329: {
! 330: struct ifnet *ifp = &sc->sc_if;
! 331:
! 332: ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
! 333:
! 334: #if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__) || \
! 335: defined(__OpenBSD__)
! 336: ifp->if_watchdog = pdq_ifwatchdog;
! 337: #else
! 338: ifp->if_watchdog = ifwatchdog;
! 339: #endif
! 340:
! 341: ifp->if_ioctl = pdq_ifioctl;
! 342: ifp->if_start = pdq_ifstart;
! 343: IFQ_SET_READY(&ifp->if_snd);
! 344:
! 345: if_attach(ifp);
! 346: fddi_ifattach(ifp);
! 347: #if NBPFILTER > 0
! 348: PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header));
! 349: #endif
! 350: }
CVSweb