root/dev/pci/if_san_obsd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wanpipe_generic_getcard
  2. wanpipe_generic_name
  3. wanpipe_generic_register
  4. wanpipe_generic_unregister
  5. wanpipe_generic_start
  6. wanpipe_generic_ioctl
  7. wanpipe_generic_watchdog
  8. wanpipe_generic_open
  9. wanpipe_generic_close
  10. wanpipe_generic_input
  11. wp_lite_set_proto
  12. wp_lite_set_te1_cfg

    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 }

/* [<][>][^][v][top][bottom][index][help] */