Annotation of sys/dev/pci/if_san_obsd.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_san_obsd.c,v 1.12 2006/05/13 19:04:30 brad Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
! 5: * All rights reserved. www.sangoma.com
! 6: *
! 7: * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above
! 15: * copyright notice, this list of conditions and the following disclaimer
! 16: * in the documentation and/or other materials provided with the
! 17: * distribution.
! 18: * 3. Neither the name of Sangoma Technologies nor the names of its
! 19: * contributors may be used to endorse or promote products derived
! 20: * from this software without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
! 23: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 24: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 25: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 26: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 27: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 28: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 32: * THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #include <sys/types.h>
! 36: #include <sys/param.h>
! 37: #include <sys/systm.h>
! 38: #include <sys/proc.h>
! 39: #include <sys/syslog.h>
! 40: #include <sys/ioccom.h>
! 41: #include <sys/conf.h>
! 42: #include <sys/malloc.h>
! 43: #include <sys/errno.h>
! 44: #include <sys/exec.h>
! 45: #include <sys/mbuf.h>
! 46: #include <sys/sockio.h>
! 47: #include <sys/socket.h>
! 48: #include <sys/kernel.h>
! 49: #include <sys/device.h>
! 50: #include <sys/time.h>
! 51: #include <sys/timeout.h>
! 52:
! 53: #include "bpfilter.h"
! 54: #if NBPFILTER > 0
! 55: # include <net/bpf.h>
! 56: #endif
! 57: #include <net/if.h>
! 58: #include <net/if_media.h>
! 59: #include <net/netisr.h>
! 60: #include <net/if_sppp.h>
! 61: #include <netinet/in_systm.h>
! 62: #include <netinet/in.h>
! 63:
! 64: #include <netinet/udp.h>
! 65: #include <netinet/ip.h>
! 66:
! 67: #include <dev/pci/if_san_common.h>
! 68: #include <dev/pci/if_san_obsd.h>
! 69:
! 70:
! 71: #ifdef _DEBUG_
! 72: #define STATIC
! 73: #else
! 74: #define STATIC static
! 75: #endif
! 76:
! 77: #define PPP_HEADER_LEN 4 /* should be globaly defined by sppp */
! 78:
! 79:
! 80: static sdla_t *wanpipe_generic_getcard(struct ifnet *);
! 81: static int wanpipe_generic_ioctl(struct ifnet *, u_long, caddr_t);
! 82: static void wanpipe_generic_watchdog(struct ifnet*);
! 83: static void wanpipe_generic_start(struct ifnet *);
! 84:
! 85:
! 86: static char *san_ifname_format = "san%d";
! 87:
! 88:
! 89:
! 90: static sdla_t *
! 91: wanpipe_generic_getcard(struct ifnet *ifp)
! 92: {
! 93: sdla_t* card;
! 94:
! 95: if (ifp->if_softc == NULL) {
! 96: log(LOG_INFO, "%s: Invalid device private structure pointer\n",
! 97: ifp->if_xname);
! 98: return (NULL);
! 99: }
! 100: card = ((sdla_t*)((wanpipe_common_t*)ifp->if_softc)->card);
! 101: if (card == NULL) {
! 102: log(LOG_INFO, "%s: Invalid Sangoma device card\n",
! 103: ifp->if_xname);
! 104: return (NULL);
! 105: }
! 106: return (card);
! 107: }
! 108:
! 109: int
! 110: wanpipe_generic_name(sdla_t *card, char *ifname, int len)
! 111: {
! 112: static int ifunit = 0;
! 113:
! 114: snprintf(ifname, len, san_ifname_format, ifunit++);
! 115: return (0);
! 116: }
! 117:
! 118: int
! 119: wanpipe_generic_register(sdla_t *card, struct ifnet *ifp, char *ifname)
! 120: {
! 121: wanpipe_common_t* common = WAN_IFP_TO_COMMON(ifp);
! 122:
! 123: if (ifname == NULL || strlen(ifname) > IFNAMSIZ)
! 124: return (EINVAL);
! 125: else
! 126: bcopy(ifname, ifp->if_xname, strlen(ifname));
! 127:
! 128: IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
! 129: IFQ_SET_READY(&ifp->if_snd);
! 130: ifp->if_mtu = PP_MTU;
! 131: ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
! 132: common->protocol = IF_PROTO_CISCO;
! 133:
! 134: ((struct sppp *)ifp)->pp_flags |= PP_CISCO;
! 135: ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
! 136: ((struct sppp *)ifp)->pp_framebytes = 3;
! 137:
! 138: ifp->if_ioctl = wanpipe_generic_ioctl; /* Will set from new_if() */
! 139: ifp->if_start = wanpipe_generic_start;
! 140: ifp->if_watchdog = wanpipe_generic_watchdog;
! 141:
! 142: if_attach(ifp);
! 143: if_alloc_sadl(ifp);
! 144: sppp_attach(ifp);
! 145:
! 146: #if NBPFILTER > 0
! 147: bpfattach(&ifp->if_bpf, ifp, DLT_PPP, PPP_HEADER_LEN);
! 148: #endif /* NBPFILTER > 0 */
! 149:
! 150: return (0);
! 151: }
! 152:
! 153: void
! 154: wanpipe_generic_unregister(struct ifnet *ifp)
! 155: {
! 156: log(LOG_INFO, "%s: Unregister interface!\n", ifp->if_xname);
! 157:
! 158: sppp_detach(ifp);
! 159: if_free_sadl(ifp);
! 160: if_detach(ifp);
! 161: }
! 162:
! 163: static void
! 164: wanpipe_generic_start(struct ifnet *ifp)
! 165: {
! 166: sdla_t *card;
! 167: struct mbuf *opkt;
! 168: int err = 0;
! 169:
! 170: if ((card = wanpipe_generic_getcard(ifp)) == NULL)
! 171: return;
! 172:
! 173: while (1) {
! 174: if (sppp_isempty(ifp)) {
! 175: /* No more packets in send queue */
! 176: break;
! 177: }
! 178:
! 179: if ((opkt = sppp_dequeue(ifp)) == NULL) {
! 180: /* Should never happened, packet pointer is NULL */
! 181: break;
! 182: }
! 183: if (card->iface_send == NULL) {
! 184: m_freem(opkt);
! 185: break;
! 186: }
! 187: /* report the packet to BPF if present and attached */
! 188: #if NBPFILTER > 0
! 189: if (ifp->if_bpf)
! 190: bpf_mtap(ifp->if_bpf, opkt, BPF_DIRECTION_OUT);
! 191: #endif /* NBPFILTER > 0 */
! 192:
! 193: if (wan_mbuf_to_buffer(&opkt)) {
! 194: m_freem(opkt);
! 195: break;
! 196: }
! 197:
! 198: err = card->iface_send(opkt, ifp);
! 199: if (err)
! 200: break;
! 201: }
! 202: }
! 203:
! 204:
! 205: static int
! 206: wanpipe_generic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
! 207: {
! 208: struct proc *p = curproc;
! 209: struct ifreq *ifr = (struct ifreq*)data;
! 210: sdla_t *card;
! 211: wanpipe_common_t* common = WAN_IFP_TO_COMMON(ifp);
! 212: struct if_settings ifsettings;
! 213: unsigned long ts_map;
! 214: int err = 0, s;
! 215:
! 216: if ((card = wanpipe_generic_getcard(ifp)) == NULL)
! 217: return (EINVAL);
! 218:
! 219: s = splnet();
! 220:
! 221: switch (cmd) {
! 222: case SIOCSIFADDR:
! 223: // XXX because sppp does an implicit setflags
! 224: log(LOG_INFO, "%s: Bringing interface up.\n",
! 225: ifp->if_xname);
! 226: if (card->iface_up)
! 227: card->iface_up(ifp);
! 228: wanpipe_generic_start(ifp);
! 229: err = 1;
! 230: break;
! 231:
! 232: case SIOCSIFMEDIA:
! 233: /* You can't set new media type while card is running */
! 234: if (card->state != WAN_DISCONNECTED) {
! 235: log(LOG_INFO, "%s: Unable to change media type!\n",
! 236: ifp->if_xname);
! 237: err = EINVAL;
! 238: } else
! 239: err = ifmedia_ioctl(ifp, ifr, &common->ifm, cmd);
! 240: goto ioctl_out;
! 241:
! 242: case SIOCGIFMEDIA:
! 243: err = ifmedia_ioctl(ifp, ifr, &common->ifm, cmd);
! 244: goto ioctl_out;
! 245:
! 246: case SIOCSIFTIMESLOT:
! 247: if ((err = suser(p, p->p_acflag)) != 0)
! 248: goto ioctl_out;
! 249: if (card->state != WAN_DISCONNECTED) {
! 250: log(LOG_INFO, "%s: Unable to change timeslot map!\n",
! 251: ifp->if_xname);
! 252: err = EINVAL;
! 253: goto ioctl_out;
! 254: }
! 255:
! 256: err = copyin(ifr->ifr_data, &ts_map, sizeof(ts_map));
! 257: if (err == 0)
! 258: sdla_te_settimeslot(card, ts_map);
! 259:
! 260: goto ioctl_out;
! 261:
! 262: case SIOCGIFTIMESLOT:
! 263: ts_map = sdla_te_gettimeslot(card);
! 264: err = copyout(ifr->ifr_data, &ts_map, sizeof(ts_map));
! 265: goto ioctl_out;
! 266:
! 267: case SIOCSIFFLAGS:
! 268: /*
! 269: ** If the interface is marked up - enable communications.
! 270: ** If down - disable communications. IFF_UP is taken
! 271: ** care of before entering this function.
! 272: */
! 273: err = 1;
! 274: if ((ifp->if_flags & IFF_UP) == 0) {
! 275: if ((ifp->if_flags & IFF_RUNNING) == 0)
! 276: break;
! 277: /* bring it down */
! 278: log(LOG_INFO, "%s: Bringing interface down.\n",
! 279: ifp->if_xname);
! 280: if (card->iface_down)
! 281: card->iface_down(ifp);
! 282: } else { /* bring it up */
! 283: if (ifp->if_flags & IFF_RUNNING)
! 284: break;
! 285: log(LOG_INFO, "%s: Bringing interface up.\n",
! 286: ifp->if_xname);
! 287: if (card->iface_up)
! 288: card->iface_up(ifp);
! 289: wanpipe_generic_start(ifp);
! 290: }
! 291: break;
! 292:
! 293: case SIOC_WANPIPE_DEVICE:
! 294: err = copyin(ifr->ifr_data, &ifsettings,
! 295: sizeof(struct if_settings));
! 296:
! 297: if (err) {
! 298: log(LOG_INFO, "%s: Failed to copy from user space!\n",
! 299: card->devname);
! 300: goto ioctl_out;
! 301: }
! 302:
! 303: switch (ifsettings.type) {
! 304: case IF_GET_PROTO:
! 305: ifsettings.type = common->protocol;
! 306: err = copyout(&ifsettings, ifr->ifr_data,
! 307: sizeof(struct if_settings));
! 308: if (err)
! 309: log(LOG_INFO,
! 310: "%s: Failed to copy to uspace!\n",
! 311: card->devname);
! 312: break;
! 313:
! 314: case IF_PROTO_CISCO:
! 315: case IF_PROTO_PPP:
! 316: if ((err = suser(p, p->p_acflag)) != 0)
! 317: goto ioctl_out;
! 318: err = wp_lite_set_proto(ifp, (struct ifreq*)data);
! 319: break;
! 320:
! 321: case IF_IFACE_T1:
! 322: case IF_IFACE_E1:
! 323: if ((err = suser(p, p->p_acflag)) != 0)
! 324: goto ioctl_out;
! 325: err = wp_lite_set_te1_cfg(ifp, (struct ifreq*)data);
! 326: break;
! 327:
! 328: default:
! 329: if (card->iface_ioctl)
! 330: err = card->iface_ioctl(ifp, cmd,
! 331: (struct ifreq*)data);
! 332: break;
! 333: }
! 334: goto ioctl_out;
! 335:
! 336: default:
! 337: if (card->iface_ioctl) {
! 338: /* Argument seqeunce is change for Linux order */
! 339: err = card->iface_ioctl(ifp, cmd, (struct ifreq*)data);
! 340: }
! 341: break;
! 342: }
! 343:
! 344: if (err)
! 345: err = sppp_ioctl(ifp, cmd, data);
! 346:
! 347: ioctl_out:
! 348: splx(s);
! 349: return (err);
! 350: }
! 351:
! 352: static void
! 353: wanpipe_generic_watchdog(struct ifnet *ifp)
! 354: {
! 355: return;
! 356: }
! 357:
! 358: int
! 359: wanpipe_generic_open(struct ifnet *ifp)
! 360: {
! 361: return (0);
! 362: }
! 363:
! 364: int
! 365: wanpipe_generic_close(struct ifnet *ifp)
! 366: {
! 367: return (0);
! 368: }
! 369:
! 370: int
! 371: wanpipe_generic_input(struct ifnet *ifp, struct mbuf *m)
! 372: {
! 373: sdla_t *card;
! 374: #if NBPFILTER > 0
! 375: #endif /* NBPFILTER > 0 */
! 376:
! 377: if ((card = wanpipe_generic_getcard(ifp)) == NULL) {
! 378: return (-EINVAL);
! 379: }
! 380: m->m_pkthdr.rcvif = ifp;
! 381: #if NBPFILTER > 0
! 382: if (ifp->if_bpf)
! 383: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 384: #endif /* NBPFILTER > 0 */
! 385: ifp->if_ipackets ++;
! 386: sppp_input(ifp, m);
! 387: return (0);
! 388: }
! 389:
! 390: int
! 391: wp_lite_set_proto(struct ifnet *ifp, struct ifreq *ifr)
! 392: {
! 393: wanpipe_common_t *common;
! 394: struct if_settings *ifsettings;
! 395: int err = 0;
! 396:
! 397: if ((common = ifp->if_softc) == NULL) {
! 398: log(LOG_INFO, "%s: Private structure is null!\n",
! 399: ifp->if_xname);
! 400: return (EINVAL);
! 401: }
! 402:
! 403: ifsettings = (struct if_settings*) ifr->ifr_data;
! 404:
! 405: switch (ifsettings->type) {
! 406: case IF_PROTO_CISCO:
! 407: if (common->protocol == IF_PROTO_CISCO)
! 408: return 0;
! 409: ((struct sppp *)ifp)->pp_flags |= PP_CISCO;
! 410: ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
! 411: common->protocol = IF_PROTO_CISCO;
! 412: break;
! 413: case IF_PROTO_PPP:
! 414: if (common->protocol == IF_PROTO_PPP)
! 415: return 0;
! 416: ((struct sppp *)ifp)->pp_flags &= ~PP_CISCO;
! 417: ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
! 418: common->protocol = IF_PROTO_PPP;
! 419: break;
! 420: }
! 421:
! 422: err = sppp_ioctl(ifp, SIOCSIFFLAGS, ifr);
! 423: return (err);
! 424: }
! 425:
! 426: int
! 427: wp_lite_set_te1_cfg(struct ifnet *ifp, struct ifreq *ifr)
! 428: {
! 429: sdla_t *card;
! 430: struct if_settings *ifsettings;
! 431: sdla_te_cfg_t te_cfg;
! 432: int err = 0;
! 433:
! 434: if ((card = wanpipe_generic_getcard(ifp)) == NULL)
! 435: return (EINVAL);
! 436:
! 437: ifsettings = (struct if_settings*)ifr->ifr_data;
! 438: err = copyin(ifsettings->ifs_te1, &te_cfg, sizeof(sdla_te_cfg_t));
! 439:
! 440: if (ifsettings->flags & SANCFG_CLOCK_FLAG)
! 441: card->fe_te.te_cfg.te_clock = te_cfg.te_clock;
! 442:
! 443: switch (ifsettings->type) {
! 444: case IF_IFACE_T1:
! 445: if (ifsettings->flags & SANCFG_LBO_FLAG)
! 446: card->fe_te.te_cfg.lbo = te_cfg.lbo;
! 447: break;
! 448: }
! 449:
! 450: return (err);
! 451: }
CVSweb