root/dev/pci/if_art.c

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

DEFINITIONS

This source file includes following definitions.
  1. art_match
  2. art_softc_attach
  3. art_ioctl
  4. art_ifm_change
  5. art_ifm_status
  6. art_ifm_options
  7. art_onesec
  8. art_linkstate
  9. art_mask_tsmap

    1 /*      $OpenBSD: if_art.c,v 1.13 2006/01/26 16:51:00 claudio Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2004,2005  Internet Business Solutions AG, Zurich, Switzerland
    5  * Written by: Claudio Jeker <jeker@accoom.net>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 #include <sys/param.h>
   21 #include <sys/types.h>
   22 
   23 #include <sys/device.h>
   24 #include <sys/proc.h>
   25 #include <sys/socket.h>
   26 #include <sys/sockio.h>
   27 #include <sys/syslog.h>
   28 #include <sys/systm.h>
   29 
   30 #include <machine/bus.h>
   31 
   32 #include <net/if.h>
   33 #include <net/if_media.h>
   34 #include <net/if_sppp.h>
   35 
   36 #include <dev/pci/musyccvar.h>
   37 #include <dev/pci/if_art.h>
   38 
   39 #define ART_E1_MASK 0xffffffff
   40 #define ART_T1_MASK 0x01fffffe
   41 
   42 int     art_match(struct device *, void *, void *);
   43 void    art_softc_attach(struct device *, struct device *, void *);
   44 
   45 int     art_ioctl(struct ifnet *, u_long, caddr_t);
   46 int     art_ifm_change(struct ifnet *);
   47 void    art_ifm_status(struct ifnet *, struct ifmediareq *);
   48 int     art_ifm_options(struct ifnet *, struct channel_softc *, u_int);
   49 void    art_onesec(void *);
   50 void    art_linkstate(void *);
   51 u_int32_t art_mask_tsmap(u_int, u_int32_t);
   52 
   53 struct cfattach art_ca = {
   54         sizeof(struct art_softc), art_match, art_softc_attach
   55 };
   56 
   57 struct cfdriver art_cd = {
   58         NULL, "art", DV_DULL
   59 };
   60 
   61 int
   62 art_match(struct device *parent, void *match, void *aux)
   63 {
   64         struct musycc_attach_args       *ma = aux;
   65 
   66         if (ma->ma_type == MUSYCC_FRAMER_BT8370)
   67                 return (1);
   68         return (0);
   69 }
   70 
   71 /*
   72  * used for the one second timer
   73  */
   74 extern int hz;
   75 
   76 void
   77 art_softc_attach(struct device *parent, struct device *self, void *aux)
   78 {
   79         struct art_softc                *sc = (struct art_softc *)self;
   80         struct musycc_softc             *psc = (struct musycc_softc *)parent;
   81         struct musycc_attach_args       *ma = aux;
   82 
   83         printf(" \"%s\"", ma->ma_product);
   84 
   85         if (ebus_attach_device(&sc->art_ebus, psc, ma->ma_base,
   86             ma->ma_size) != 0) {
   87                 printf(": could not map framer\n");
   88                 return;
   89         }
   90 
   91         /* set basic values */
   92         sc->art_port = ma->ma_port;
   93         sc->art_slot = ma->ma_slot;
   94         sc->art_gnum = ma->ma_gnum;
   95         sc->art_type = ma->ma_flags & 0x03;
   96 
   97         sc->art_channel = musycc_channel_create(self->dv_xname, 1);
   98         if (sc->art_channel == NULL) {
   99                 printf(": could not alloc channel descriptor\n");
  100                 return;
  101         }
  102 
  103         if (musycc_channel_attach(psc, sc->art_channel, self, sc->art_gnum) ==
  104             -1) {
  105                 printf(": unable to attach to hdlc controller\n");
  106                 return;
  107         }
  108 
  109         ifmedia_init(&sc->art_ifm, 0, art_ifm_change, art_ifm_status);
  110         ifmedia_add(&sc->art_ifm,
  111             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, 0, 0), 0, NULL);
  112         ifmedia_add(&sc->art_ifm,
  113             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, 0, 0), 0, NULL);
  114         ifmedia_add(&sc->art_ifm,
  115             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, 0, 0), 0, NULL);
  116         ifmedia_add(&sc->art_ifm,
  117             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, 0, 0), 0, NULL);
  118         ifmedia_add(&sc->art_ifm,
  119             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, 0, 0), 0, NULL);
  120 
  121         ifmedia_add(&sc->art_ifm,
  122             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, IFM_TDM_MASTER, 0), 0, NULL);
  123         ifmedia_add(&sc->art_ifm,
  124             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, IFM_TDM_MASTER, 0), 0, NULL);
  125         ifmedia_add(&sc->art_ifm,
  126             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, IFM_TDM_MASTER, 0), 0, NULL);
  127         ifmedia_add(&sc->art_ifm,
  128             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, IFM_TDM_MASTER, 0), 0, NULL);
  129         ifmedia_add(&sc->art_ifm,
  130             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, IFM_TDM_MASTER, 0),
  131             0, NULL);
  132 
  133         ifmedia_add(&sc->art_ifm,
  134             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, IFM_TDM_PPP, 0), 0, NULL);
  135         ifmedia_add(&sc->art_ifm,
  136             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, IFM_TDM_PPP, 0), 0, NULL);
  137         ifmedia_add(&sc->art_ifm,
  138             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, IFM_TDM_PPP, 0), 0, NULL);
  139         ifmedia_add(&sc->art_ifm,
  140             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, IFM_TDM_PPP, 0), 0, NULL);
  141         ifmedia_add(&sc->art_ifm,
  142             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, IFM_TDM_PPP, 0), 0,
  143             NULL);
  144 
  145         ifmedia_add(&sc->art_ifm,
  146             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1, IFM_TDM_PPP | IFM_TDM_MASTER, 0),
  147             0, NULL);
  148         ifmedia_add(&sc->art_ifm,
  149             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1, IFM_TDM_PPP | IFM_TDM_MASTER, 0),
  150             0, NULL);
  151         ifmedia_add(&sc->art_ifm,
  152             IFM_MAKEWORD(IFM_TDM, IFM_TDM_T1_AMI, IFM_TDM_PPP | IFM_TDM_MASTER,
  153             0), 0, NULL);
  154         ifmedia_add(&sc->art_ifm,
  155             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704, IFM_TDM_PPP |
  156             IFM_TDM_MASTER, 0), 0, NULL);
  157         ifmedia_add(&sc->art_ifm,
  158             IFM_MAKEWORD(IFM_TDM, IFM_TDM_E1_G704_CRC4, IFM_TDM_PPP |
  159             IFM_TDM_MASTER, 0), 0, NULL);
  160 
  161         printf("\n");
  162 
  163         if (bt8370_reset(sc) != 0)
  164                 return;
  165 
  166         /* Initialize timeout for statistics update. */
  167         timeout_set(&sc->art_onesec, art_onesec, sc);
  168 
  169         ifmedia_set(&sc->art_ifm, IFM_TDM|IFM_TDM_E1_G704_CRC4);
  170         sc->art_media = sc->art_ifm.ifm_media;
  171 
  172         bt8370_set_frame_mode(sc, sc->art_type, IFM_TDM_E1_G704_CRC4, 0);
  173         musycc_attach_sppp(sc->art_channel, art_ioctl);
  174 
  175         /* Set linkstate hook to track link state changes done by sppp. */
  176         sc->art_linkstatehook = hook_establish(
  177             sc->art_channel->cc_ifp->if_linkstatehooks, 0, art_linkstate, sc);
  178 
  179         /* Schedule the timeout one second from now. */
  180         timeout_add(&sc->art_onesec, hz);
  181 }
  182 
  183 /* interface ioctl */
  184 int
  185 art_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
  186 {
  187         struct ifreq            *ifr = (struct ifreq*) data;
  188         struct channel_softc    *cc = ifp->if_softc;
  189         struct art_softc        *ac = (struct art_softc *)cc->cc_parent;
  190         u_int32_t                tsmap;
  191         int                      s, rv = 0;
  192 
  193         s = splnet();
  194         switch (command) {
  195         case SIOCSIFADDR:
  196                 if ((rv = musycc_init_channel(cc, ac->art_slot)))
  197                         break;
  198                 rv = sppp_ioctl(ifp, command, data);
  199                 break;
  200         case SIOCSIFTIMESLOT:
  201                 if ((rv = suser(curproc, 0)) != 0)
  202                         break;
  203                 rv = copyin(ifr->ifr_data, &tsmap, sizeof(tsmap));
  204                 if (rv)
  205                         break;
  206                 if (art_mask_tsmap(IFM_SUBTYPE(ac->art_media), tsmap) !=
  207                     tsmap) {
  208                         rv = EINVAL;
  209                         break;
  210                 }
  211                 if (ac->art_type == ART_SBI_SINGLE &&
  212                     (IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1 ||
  213                     IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1_AMI))
  214                         /*
  215                          * need to adjust timeslot mask for T1 on single port
  216                          * cards. There timeslot 0-23 are usable not 1-24
  217                          */
  218                         tsmap >>= 1;
  219 
  220                 cc->cc_tslots = tsmap;
  221                 rv = musycc_init_channel(cc, ac->art_slot);
  222                 break;
  223         case SIOCGIFTIMESLOT:
  224                 tsmap = cc->cc_tslots;
  225                 if (ac->art_type == ART_SBI_SINGLE &&
  226                     (IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1 ||
  227                     IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1_AMI))
  228                         tsmap <<= 1;
  229                 rv = copyout(&tsmap, ifr->ifr_data, sizeof(tsmap));
  230                 break;
  231         case SIOCSIFFLAGS:
  232                 /*
  233                  * If interface is marked up and not running, then start it.
  234                  * If it is marked down and running, stop it.
  235                  */
  236                 if (ifr->ifr_flags & IFF_UP && cc->cc_state != CHAN_RUNNING) {
  237                         if ((rv = musycc_init_channel(cc, ac->art_slot)))
  238                                 break;
  239                 } else if ((ifr->ifr_flags & IFF_UP) == 0 &&
  240                     cc->cc_state == CHAN_RUNNING)
  241                         musycc_stop_channel(cc);
  242                 rv = sppp_ioctl(ifp, command, data);
  243                 break;
  244         case SIOCSIFMEDIA:
  245         case SIOCGIFMEDIA:
  246                 if (ac != NULL)
  247                         rv = ifmedia_ioctl(ifp, ifr, &ac->art_ifm, command);
  248                 else
  249                         rv = EINVAL;
  250                 break;
  251         default:
  252                 rv = sppp_ioctl(ifp, command, data);
  253                 break;
  254         }
  255         splx(s);
  256         return (rv);
  257 }
  258 
  259 int
  260 art_ifm_change(struct ifnet *ifp)
  261 {
  262         struct channel_softc    *cc = ifp->if_softc;
  263         struct art_softc        *ac = (struct art_softc *)cc->cc_parent;
  264         struct ifmedia          *ifm = &ac->art_ifm;
  265         int                      rv, s, baudrate;
  266 
  267         ACCOOM_PRINTF(2, ("%s: art_ifm_change %08x\n", ifp->if_xname,
  268             ifm->ifm_media));
  269 
  270         if (IFM_TYPE(ifm->ifm_media) != IFM_TDM)
  271                 return (EINVAL);
  272 
  273         /* OPTIONS (controller mode hdlc, ppp, eoe) */
  274         if ((rv = art_ifm_options(ifp, cc, IFM_OPTIONS(ifm->ifm_media))) != 0)
  275                 return (rv);
  276 
  277         /* SUBTYPE (framing mode T1/E1) + MODE (clocking master/slave) */
  278         if (IFM_SUBTYPE(ifm->ifm_media) != IFM_SUBTYPE(ac->art_media) ||
  279             IFM_MODE(ifm->ifm_media) != IFM_MODE(ac->art_media)) {
  280                 ACCOOM_PRINTF(0, ("%s: art_ifm_change type %d mode %x\n",
  281                     ifp->if_xname, IFM_SUBTYPE(ifm->ifm_media),
  282                     IFM_MODE(ifm->ifm_media)));
  283 
  284                 bt8370_set_frame_mode(ac, ac->art_type,
  285                     IFM_SUBTYPE(ifm->ifm_media), IFM_MODE(ifm->ifm_media));
  286 
  287                 if (IFM_SUBTYPE(ifm->ifm_media) != IFM_SUBTYPE(ac->art_media)) {
  288                         /* adjust timeslot map on media change */
  289                         cc->cc_tslots = art_mask_tsmap(
  290                             IFM_SUBTYPE(ifm->ifm_media), cc->cc_tslots);
  291 
  292                         if (ac->art_type == ART_SBI_SINGLE &&
  293                             (IFM_SUBTYPE(ifm->ifm_media) == IFM_TDM_T1 ||
  294                              IFM_SUBTYPE(ifm->ifm_media) == IFM_TDM_T1_AMI) &&
  295                             (IFM_SUBTYPE(ac->art_media) != IFM_TDM_T1 &&
  296                              IFM_SUBTYPE(ac->art_media) != IFM_TDM_T1_AMI))
  297                                 /*
  298                                  * need to adjust timeslot mask for T1 on
  299                                  * single port cards. There timeslot 0-23 are
  300                                  * usable not 1-24
  301                                  */
  302                                 cc->cc_tslots >>= 1;
  303                         else if (ac->art_type == ART_SBI_SINGLE &&
  304                             (IFM_SUBTYPE(ifm->ifm_media) != IFM_TDM_T1 &&
  305                              IFM_SUBTYPE(ifm->ifm_media) != IFM_TDM_T1_AMI) &&
  306                             (IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1 ||
  307                              IFM_SUBTYPE(ac->art_media) == IFM_TDM_T1_AMI))
  308                                 /* undo the last adjustment */
  309                                 cc->cc_tslots <<= 1;
  310                 }
  311 
  312                 /* re-init the card */
  313                 if ((rv = musycc_init_channel(cc, ac->art_slot)))
  314                         return (rv);
  315         }
  316 
  317         baudrate = ifmedia_baudrate(ac->art_media);
  318         if (baudrate != ifp->if_baudrate) {
  319                 ifp->if_baudrate = baudrate;
  320                 s = splsoftnet();
  321                 if_link_state_change(ifp), baudrate;
  322                 splx(s);
  323         }
  324 
  325         ac->art_media = ifm->ifm_media;
  326 
  327         return (0);
  328 }
  329 
  330 void
  331 art_ifm_status(struct ifnet *ifp, struct ifmediareq *ifmreq)
  332 {
  333         struct art_softc        *ac;
  334 
  335         ac = (struct art_softc *)
  336             ((struct channel_softc *)ifp->if_softc)->cc_parent;
  337         ifmreq->ifm_status = IFM_AVALID;
  338         if (ifp->if_link_state == LINK_STATE_UP)
  339                 ifmreq->ifm_status |= IFM_ACTIVE;
  340         ifmreq->ifm_active = ac->art_media;
  341 
  342         return;
  343 }
  344 
  345 int
  346 art_ifm_options(struct ifnet *ifp, struct channel_softc *cc, u_int options)
  347 {
  348         struct art_softc        *ac = (struct art_softc *)cc->cc_parent;
  349         u_int                    flags = cc->cc_ppp.pp_flags;
  350         int                      rv;
  351 
  352         if (options == IFM_TDM_PPP) {
  353                 flags &= ~PP_CISCO;
  354                 flags |= PP_KEEPALIVE;
  355         } else if (options == 0) {
  356                 flags |= PP_CISCO;
  357                 flags |= PP_KEEPALIVE;
  358         } else {
  359                 ACCOOM_PRINTF(0, ("%s: Unsupported ifmedia options\n",
  360                     ifp->if_xname));
  361                 return (EINVAL);
  362         }
  363         if (flags != cc->cc_ppp.pp_flags) {
  364                 musycc_stop_channel(cc);
  365                 cc->cc_ppp.pp_flags = flags;
  366                 if ((rv = musycc_init_channel(cc, ac->art_slot)))
  367                         return (rv);
  368                 return (sppp_ioctl(ifp, SIOCSIFFLAGS, NULL));
  369         }
  370         return (0);
  371 }
  372 
  373 void
  374 art_onesec(void *arg)
  375 {
  376         struct art_softc        *ac = arg;
  377         struct ifnet            *ifp = ac->art_channel->cc_ifp;
  378         struct sppp             *ppp = &ac->art_channel->cc_ppp;
  379         int                      s, rv, link_state;
  380 
  381         rv = bt8370_link_status(ac);
  382         switch (rv) {
  383         case 1:
  384                 link_state = LINK_STATE_UP;
  385                 /* set green led */
  386                 ebus_set_led(ac->art_channel, 1, MUSYCC_LED_GREEN);
  387                 break;
  388         case 0:
  389                 link_state = LINK_STATE_DOWN;
  390                 /* set green led and red led as well */
  391                 ebus_set_led(ac->art_channel, 1,
  392                     MUSYCC_LED_GREEN | MUSYCC_LED_RED);
  393                 break;
  394         default:
  395                 link_state = LINK_STATE_DOWN;
  396                 /* turn green led off */
  397                 ebus_set_led(ac->art_channel, 0, MUSYCC_LED_GREEN);
  398                 break;
  399         }
  400 
  401         if (link_state != ifp->if_link_state) {
  402                 s = splsoftnet();
  403                 if (link_state == LINK_STATE_UP)
  404                         ppp->pp_up(ppp);
  405                 else
  406                         ppp->pp_down(ppp);
  407                 splx(s);
  408         }
  409 
  410         /*
  411          * run musycc onesec job
  412          */
  413         musycc_tick(ac->art_channel);
  414 
  415         /*
  416          * Schedule another timeout one second from now.
  417          */
  418         timeout_add(&ac->art_onesec, hz);
  419 }
  420 
  421 void
  422 art_linkstate(void *arg)
  423 {
  424         struct art_softc        *ac = arg;
  425         struct ifnet            *ifp = ac->art_channel->cc_ifp;
  426 
  427         if (ifp->if_link_state == LINK_STATE_UP)
  428                 /* turn red led off */
  429                 ebus_set_led(ac->art_channel, 0, MUSYCC_LED_RED);
  430         else
  431                 /* turn red led on */
  432                 ebus_set_led(ac->art_channel, 1, MUSYCC_LED_RED);
  433 }
  434 
  435 u_int32_t
  436 art_mask_tsmap(u_int mode, u_int32_t tsmap)
  437 {
  438         switch (mode) {
  439         case IFM_TDM_E1:
  440         case IFM_TDM_E1_G704:
  441         case IFM_TDM_E1_G704_CRC4:
  442                 return (tsmap & ART_E1_MASK);
  443         case IFM_TDM_T1_AMI:
  444         case IFM_TDM_T1:
  445                 return (tsmap & ART_T1_MASK);
  446         default:
  447                 return (tsmap);
  448         }
  449 }

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