[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     ! 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