[BACK]Return to if_art.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/if_art.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb