Annotation of 42BSD/sys/vaxif/if_un.c, revision 1.1.1.1

1.1       root        1: /*     if_un.c 6.1     83/07/29        */
                      2: 
                      3: #include "un.h"
                      4: #if NUN > 0
                      5: /*
                      6:  * Ungermann-Bass network/DR11-W interface driver
                      7:  */
                      8: #include "../machine/pte.h"
                      9: 
                     10: #include "../h/param.h"
                     11: #include "../h/systm.h"
                     12: #include "../h/mbuf.h"
                     13: #include "../h/buf.h"
                     14: #include "../h/protosw.h"
                     15: #include "../h/socket.h"
                     16: #include "../h/vmmac.h"
                     17: #include "../h/errno.h"
                     18: #include "../h/time.h"
                     19: #include "../h/kernel.h"
                     20: #include "../h/ioctl.h"
                     21: 
                     22: #include "../net/if.h"
                     23: #include "../net/netisr.h"
                     24: #include "../net/route.h"
                     25: #include "../netinet/in.h"
                     26: #include "../netinet/in_systm.h"
                     27: #include "../netinet/ip.h"
                     28: #include "../netinet/ip_var.h"
                     29: 
                     30: #include "../vax/cpu.h"
                     31: #include "../vax/mtpr.h"
                     32: #include "../vaxif/if_un.h"
                     33: #include "../vaxif/if_unreg.h"
                     34: #include "../vaxif/if_uba.h"
                     35: #include "../vaxuba/ubareg.h"
                     36: #include "../vaxuba/ubavar.h"
                     37: 
                     38: #define        UNMTU           (600-sizeof (struct un_header))
                     39: 
                     40: #define        US_NULL         0       /* not doing anything state */
                     41: #define        US_IDLE         1       /* waiting to transfer state */
                     42: #define        US_READ         2       /* reading state */
                     43: #define        US_WRITE        3       /* writing state */
                     44: #define        US_RESET        4       /* waiting for reset state */
                     45: 
                     46: int    unprobe(), unattach(), unintr();
                     47: struct uba_device *uninfo[NUN];
                     48: u_short        unstd[] = { 0 };
                     49: struct uba_driver undriver =
                     50:        { unprobe, 0, unattach, 0, unstd, "un", uninfo };
                     51: #define        UNUNIT(dev)     (minor(dev))
                     52: 
                     53: int    uninit(), unioctl(), unoutput(), unreset();
                     54: int    unrestart();
                     55: 
                     56: /*
                     57:  * Ungermann-Bass software status per interface.
                     58:  *
                     59:  * Each interface is referenced by a network interface structure,
                     60:  * us_if, which the routing code uses to locate the interface.
                     61:  * This structure contains the output queue for the interface, its address,
                     62:  * etc.  We also have, for each interface, a UBA interface structure, which
                     63:  * contains information about the UNIBUS resources held by the interface:
                     64:  * map registers, buffered data paths, etc.  Information is cached in this
                     65:  * structure for use by the if_uba.c routines in running the interface
                     66:  * efficiently.
                     67:  */
                     68: struct un_softc {
                     69:        struct  ifnet us_if;            /* network-visible interface */
                     70:        struct  ifuba us_ifuba;         /* UNIBUS resources */
                     71:        short   us_state;               /* device state */
                     72:        short   us_errcnt;              /* number of errors since time set */
                     73:        short   us_restart;             /* restart interval */
                     74:        u_char  us_maxtime;             /* interval for error counting */
                     75:        u_char  us_maxerr;              /* errors allowed in interval */
                     76:        time_t  us_errtime;             /* time for error counting */
                     77: } un_softc[NUN];
                     78: 
                     79: /*
                     80:  * Cause an interrupt to determine interface presence and
                     81:  * interrupt vector.
                     82:  */
                     83: unprobe(reg)
                     84:        caddr_t reg;
                     85: {
                     86:        register int br, cvec;          /* r11, r10 value-result */
                     87:        register struct undevice *addr = (struct undevice *)reg;
                     88: 
                     89: #ifdef lint
                     90:        br = 0; cvec = br; br = cvec;
                     91:        unintr(0);
                     92: #endif
                     93:        addr->csr = IE|UNRESET;
                     94:        addr->csr = IE|UNRESET|GO;
                     95:        DELAY(100000);
                     96:        addr->csr = 0;
                     97:        return (1);
                     98: }
                     99: 
                    100: /*
                    101:  * Interface exists: make available by filling in network interface
                    102:  * record.  System will initialize the interface when it is ready
                    103:  * to accept packets.
                    104:  */
                    105: unattach(ui)
                    106:        struct uba_device *ui;
                    107: {
                    108:        register struct un_softc *us = &un_softc[ui->ui_unit];
                    109: 
                    110:        us->us_if.if_unit = ui->ui_unit;
                    111:        us->us_if.if_name = "un";
                    112:        us->us_if.if_mtu = UNMTU;
                    113:        us->us_if.if_init = uninit;
                    114:        us->us_if.if_ioctl = unioctl;
                    115:        us->us_if.if_output = unoutput;
                    116:        us->us_if.if_reset = unreset;
                    117:        us->us_if.if_watchdog = unrestart;
                    118:        us->us_maxtime = 3;
                    119:        us->us_maxerr = 10;
                    120:        us->us_restart = 5 * 60;
                    121:        us->us_ifuba.ifu_flags = UBA_CANTWAIT;
                    122: #ifdef notdef
                    123:        us->us_ifuba.ifu_flags |= UBA_NEEDBDP;
                    124: #endif
                    125:        if_attach(&us->us_if);
                    126: }
                    127: 
                    128: /*
                    129:  * Reset of interface after UNIBUS reset.
                    130:  * If interface is on specified uba, reset its state.
                    131:  */
                    132: unreset(unit, uban)
                    133:        int unit, uban;
                    134: {
                    135:        register struct uba_device *ui;
                    136: 
                    137:        if (unit >= NUN || (ui = uninfo[unit]) == 0 || ui->ui_alive == 0 ||
                    138:            ui->ui_ubanum != uban)
                    139:                return;
                    140:        printf(" un%d", unit);
                    141:        uninit(unit);
                    142: }
                    143: 
                    144: /*
                    145:  * Initialization of interface; clear recorded pending
                    146:  * operations, and reinitialize UNIBUS usage.
                    147:  */
                    148: uninit(unit)
                    149:        int unit;
                    150: {
                    151:        register struct un_softc *us = &un_softc[unit];
                    152:        register struct uba_device *ui = uninfo[unit];
                    153:        register struct undevice *addr;
                    154:        struct sockaddr_in *sin;
                    155:        int s;
                    156: 
                    157:        sin = (struct sockaddr_in *)&us->us_if.if_addr;
                    158:        if (in_netof(sin->sin_addr) == 0)
                    159:                return;
                    160:        if (if_ubainit(&us->us_ifuba, ui->ui_ubanum,
                    161:            sizeof (struct un_header), (int)btoc(UNMTU)) == 0) {
                    162:                printf("un%d: can't initialize\n", unit);
                    163:                us->us_if.if_flags &= ~IFF_UP;
                    164:                return;
                    165:        }
                    166:        us->us_if.if_flags |= IFF_RUNNING;
                    167:        us->us_errcnt = 0;
                    168:        us->us_errtime = time.tv_sec;
                    169:        unwhoami(unit);
                    170: 
                    171:        /*
                    172:         * Reset U-B interface, thus causing an interrupt which
                    173:         * will start things going.
                    174:         */
                    175:        addr = (struct undevice *)ui->ui_addr;
                    176:        s = splimp();
                    177:        addr->csr = IE|UNRESET;
                    178:        addr->csr = IE|UNRESET|GO;
                    179:        us->us_state = US_RESET;
                    180:        splx(s);
                    181: }
                    182: 
                    183: /*
                    184:  * Try to start a write operation.
                    185:  * If interface is busy, it must be in idle state, so issue a reset.
                    186:  * Otherwise, get the datagram from the output queue, map it onto
                    187:  * the UNIBUS, and start the write.  This routine should not be
                    188:  * called if the output queue is empty.
                    189:  */
                    190: unstart(dev)
                    191:        dev_t dev;
                    192: {
                    193:        int unit = UNUNIT(dev);
                    194:        struct uba_device *ui = uninfo[unit];
                    195:        register struct un_softc *us = &un_softc[unit];
                    196:        register struct undevice *addr = (struct undevice *)ui->ui_addr;
                    197:        struct mbuf *m;
                    198:        int dataaddr, datalen;
                    199:        register short cmdcsr;
                    200: 
                    201:        if (us->us_state != US_NULL) {
                    202:                addr->csr = IE|UNRESET;
                    203:                addr->csr = IE|UNRESET|GO;
                    204:                us->us_state = US_RESET;
                    205:        } else {
                    206:                IF_DEQUEUE(&us->us_if.if_snd, m);
                    207:                if (m == 0)
                    208:                        return;
                    209:                us->us_state = US_WRITE;
                    210:                datalen = if_wubaput(&us->us_ifuba, m);
                    211:                if (us->us_ifuba.ifu_flags & UBA_NEEDBDP)
                    212:                        UBAPURGE(us->us_ifuba.ifu_uba,
                    213:                                us->us_ifuba.ifu_w.ifrw_bdp);
                    214:                dataaddr = us->us_ifuba.ifu_w.ifrw_info;
                    215:                addr->bar = dataaddr & 0xffff;
                    216:                addr->wcr = -(((datalen + 1) >> 1) + 1);
                    217:                cmdcsr = ((dataaddr >> 12) & 0x30) | IE | UNOUT;
                    218:                addr->csr = cmdcsr;
                    219:                addr->csr = cmdcsr | GO;
                    220:        }
                    221: }
                    222: 
                    223: /*
                    224:  * Ungermann-Bass interface interrupt handler.
                    225:  * Determines reason for interrupt and acts accordingly.
                    226:  */
                    227: unintr(unit)
                    228:        int unit;
                    229: {
                    230:        register struct un_softc *us = &un_softc[unit];
                    231:        struct undevice *addr = (struct undevice *)uninfo[unit]->ui_addr;
                    232:        register struct un_header *un;
                    233:        struct mbuf *m;
                    234:        int len;
                    235:        register struct ifqueue *inq;
                    236:        int cmdcsr;
                    237: 
                    238:        if ((addr->dar & RESETACK) && us->us_state != US_RESET) {
                    239:                if ((us->us_if.if_flags & IFF_UP) == 0)
                    240:                        return;
                    241:                printf("un%d: unexpected reset\n", unit);
                    242:                unerror(unit);
                    243:        }
                    244:                
                    245:        switch (us->us_state) {
                    246: 
                    247:        case US_NULL:
                    248:                printf("un%d: stray interrupt\n", unit);
                    249:                break;
                    250: 
                    251:        case US_RESET:
                    252:                if (!(addr->dar & RESETACK)) {
                    253:                        addr->csr = IE|UNRESET;
                    254:                        addr->csr = IE|UNRESET|GO;
                    255:                        return;
                    256:                }
                    257:                break;
                    258: 
                    259:        case US_IDLE:
                    260:                break;
                    261: 
                    262:        case US_READ:
                    263:                us->us_if.if_ipackets++;
                    264:                if (us->us_ifuba.ifu_flags & UBA_NEEDBDP)
                    265:                        UBAPURGE(us->us_ifuba.ifu_uba,
                    266:                                us->us_ifuba.ifu_r.ifrw_bdp);
                    267:                if (addr->csr & STATA) {
                    268:                        if ((us->us_if.if_flags & IFF_UP) == 0)
                    269:                                return;
                    270:                        printf("un%d: input error csr=%b\n", unit,
                    271:                                addr->csr&0xffff, UNBITS);
                    272:                        us->us_if.if_ierrors++;
                    273:                        unerror(unit);
                    274:                        break;
                    275:                }
                    276:                un = (struct un_header *)(us->us_ifuba.ifu_r.ifrw_addr);
                    277:                switch (un->un_ptype) {
                    278: #ifdef INET
                    279:                case UNTYPE_IP:
                    280:                        len = htons((u_short)((struct ip *) (un+1))->ip_len);
                    281:                        schednetisr(NETISR_IP);
                    282:                        inq = &ipintrq;
                    283:                        break;
                    284: #endif
                    285:                case UNTYPE_INQUIRE: {
                    286:                        struct sockaddr_in *sin;
                    287: 
                    288:                        us->us_if.if_host[0] =
                    289:                            un->un_dport << 16 | htons(un->un_dniu);
                    290:                        sin = (struct sockaddr_in *)&us->us_if.if_addr;
                    291:                        sin->sin_addr = if_makeaddr(us->us_if.if_net,
                    292:                                us->us_if.if_host[0]);
                    293:                        us->us_if.if_flags |= IFF_UP;
                    294:                        if_rtinit(&us->us_if, RTF_UP);
                    295:                        goto setup;
                    296:                }
                    297: 
                    298:                default:
                    299:                        printf("un%d: bad packet type %d\n", un->un_ptype);
                    300:                        goto setup;
                    301:                }
                    302: 
                    303:                m = if_rubaget(&us->us_ifuba, len, 0);
                    304:                if (m != 0)
                    305:                        if (IF_QFULL(inq)) {
                    306:                                IF_DROP(inq);
                    307:                                m_freem(m);
                    308:                        } else
                    309:                                IF_ENQUEUE(inq, m);
                    310:                break;
                    311: 
                    312:        case US_WRITE:
                    313:                us->us_if.if_opackets++;
                    314:                if (addr->csr & STATA) {
                    315:                        if ((us->us_if.if_flags & IFF_UP) == 0)
                    316:                                return;
                    317:                        printf("un%d: output error csr=%b\n",
                    318:                            unit, addr->csr, UNBITS);
                    319:                        us->us_if.if_oerrors++;
                    320:                        unerror(unit);
                    321:                }
                    322:                if (us->us_ifuba.ifu_xtofree) {
                    323:                        m_freem(us->us_ifuba.ifu_xtofree);
                    324:                        us->us_ifuba.ifu_xtofree = 0;
                    325:                }
                    326:                break;
                    327: 
                    328:        default:
                    329:                printf("un%d: invalid state %d csr=%b\n",
                    330:                    us->us_state, addr->csr, UNBITS);
                    331:        }
                    332: 
                    333: setup:
                    334:        us->us_state = US_NULL;
                    335:        if (addr->csr & STATB) {
                    336:                us->us_state = US_READ;
                    337:                addr->wcr = -((sizeof (struct un_header) + UNMTU + 1)/2+1);
                    338:                addr->bar = us->us_ifuba.ifu_r.ifrw_info & 0xffff;
                    339:                cmdcsr = ((us->us_ifuba.ifu_r.ifrw_info >> 12) & 0x30);
                    340:                cmdcsr |= IE|UNRDDG;
                    341:                addr->csr = cmdcsr;
                    342:                addr->csr = cmdcsr | GO;
                    343:        } else if (us->us_if.if_snd.ifq_head != 0 && (addr->csr & STATC))
                    344:                unstart(unit);
                    345:        
                    346:        if (us->us_state == US_NULL) {
                    347:                us->us_state = US_IDLE;
                    348:                addr->csr = IE|UNIDLE;
                    349:                addr->csr = IE|UNIDLE|GO;
                    350:        }
                    351: }
                    352: 
                    353: /*
                    354:  * Ungermann-Bass output routine.
                    355:  * Encapsulate a packet destined for dst for the local net.
                    356:  */
                    357: unoutput(ifp, m0, dst)
                    358:        struct ifnet *ifp;
                    359:        struct mbuf *m0;
                    360:        struct sockaddr *dst;
                    361: {
                    362:        int type, destniu, destport, len;
                    363:        register struct mbuf *m = m0;
                    364:        register struct un_header *un;
                    365:        register struct un_softc *us = &un_softc[ifp->if_unit];
                    366:        int s;
                    367: 
                    368:        if ((us->us_if.if_flags & IFF_UP) == 0)
                    369:                return (ENETDOWN);
                    370:        switch (dst->sa_family) {
                    371: 
                    372: #ifdef INET
                    373:        case AF_INET: {
                    374:                struct sockaddr_in *sin = (struct sockaddr_in *)dst;
                    375:                struct ip *ip = mtod(m, struct ip *);
                    376: 
                    377:                if (sin->sin_addr.s_addr & 0xffffff00) {
                    378:                        destniu = sin->sin_addr.s_addr >> 24;
                    379:                        destport = (sin->sin_addr.s_addr >> 8) & 0xff;
                    380:                } else {
                    381:                        destniu = 0xffff;
                    382:                        destport = 0xff;
                    383:                }
                    384:                len = htons((u_short) ip->ip_len);
                    385:                type = UNTYPE_IP;
                    386:                break;
                    387:        }
                    388: #endif
                    389:        default:
                    390:                printf("un%d: can't handle af%d\n", ifp->if_unit,
                    391:                        dst->sa_family);
                    392:                m_freem(m0);
                    393:                return (EAFNOSUPPORT);
                    394:        }
                    395:        
                    396:        /*
                    397:         * Add local net header.  If no space in first mbuf,
                    398:         * allocate another.
                    399:         */
                    400:        if (m->m_off > MMAXOFF ||
                    401:            MMINOFF + sizeof (struct un_header) > m->m_off) {
                    402:                m = m_get(M_DONTWAIT, MT_HEADER);
                    403:                if (m == 0) {
                    404:                        m_freem(m0);
                    405:                        return (ENOBUFS);
                    406:                }
                    407:                m->m_next = m0;
                    408:                m->m_off = MMINOFF;
                    409:                m->m_len = sizeof (struct un_header);
                    410:        } else {
                    411:                m->m_off -= sizeof (struct un_header);
                    412:                m->m_len += sizeof (struct un_header);
                    413:        }
                    414:        un = mtod(m, struct un_header *);
                    415:        bzero((caddr_t)un, sizeof (struct un_header));
                    416:        un->un_length = htons((u_short)(len + sizeof (struct un_header)));
                    417:        un->un_dniu = htons((u_short)destniu);
                    418:        un->un_dport = destport;
                    419:        un->un_dtype = 5;
                    420:        un->un_sniu = htons((u_short)(ifp->if_host[0] >> 24));
                    421:        un->un_sport = (ifp->if_host[0] >> 8) & 0xff;
                    422:        un->un_stype = 5;
                    423:        un->un_ptype = type;
                    424: 
                    425:        /*
                    426:         * Queue message on interface, and start output if interface
                    427:         * not yet active.
                    428:         */
                    429:        s = splimp();
                    430:        if (IF_QFULL(&ifp->if_snd)) {
                    431:                IF_DROP(&ifp->if_snd);
                    432:                m_freem(m);
                    433:                splx(s);
                    434:                return (ENOBUFS);
                    435:        }
                    436:        IF_ENQUEUE(&ifp->if_snd, m);
                    437:        if (us->us_state == US_IDLE)
                    438:                unstart(ifp->if_unit);
                    439:        splx(s);
                    440:        return (0);
                    441: }
                    442: 
                    443: /*
                    444:  * U-B error handler, if maxerr errors have occured
                    445:  * in maxtime seconds, disable the interface.
                    446:  */
                    447: unerror(unit)
                    448:        int unit;
                    449: {
                    450:        register struct un_softc *us = &un_softc[unit];
                    451:        struct undevice *addr = (struct undevice *)uninfo[unit]->ui_addr;
                    452: 
                    453:        if (time.tv_sec - us->us_errtime > us->us_maxtime) {
                    454:                us->us_errtime = time.tv_sec;
                    455:                us->us_errcnt = 1;
                    456:        } else if (++us->us_errcnt >= us->us_maxerr) {
                    457:                printf("un%d: error limit exceeded\n", unit);
                    458:                us->us_if.if_flags &= ~IFF_UP;
                    459:                addr->csr = 0;
                    460:                us->us_if.if_timer = us->us_restart;
                    461:        }
                    462: }
                    463: 
                    464: unrestart(unit)
                    465:        int unit;
                    466: {
                    467:        register struct un_softc *us = &un_softc[unit];
                    468:        struct undevice *addr = (struct undevice *)uninfo[unit]->ui_addr;
                    469:        int s;
                    470: 
                    471:        us->us_if.if_flags |= IFF_UP;
                    472:        printf("un%d: restarting\n", unit);
                    473:        unwhoami(unit);
                    474:        s = splimp();
                    475:        addr->csr = IE|UNRESET;
                    476:        addr->csr = IE|UNRESET|GO;
                    477:        us->us_state = US_RESET;
                    478:        splx(s);
                    479: }
                    480: 
                    481: /*
                    482:  * Send a "Who am I?" message to the interface. 
                    483:  * Interface should respond with an copy of the
                    484:  * packet with its real address filled in.  The
                    485:  * message is placed at the head of the output queue.
                    486:  * An interface reset should be done next to start
                    487:  * things rolling.
                    488:  */
                    489: unwhoami(unit)             
                    490:        int unit;
                    491: {
                    492:        register struct mbuf *m;
                    493:        register struct un_softc *us = &un_softc[unit];
                    494:        register struct un_header *un;
                    495:        int s;
                    496: 
                    497:        if ((m = m_get(M_DONTWAIT, MT_HEADER)) == 0) 
                    498:                return;
                    499:        m->m_off = MMINOFF;
                    500:        m->m_len = sizeof(struct un_header);
                    501:        un = mtod(m, struct un_header *);
                    502:        bzero((caddr_t)un, sizeof (struct un_header));
                    503:        un->un_length = htons(sizeof (struct un_header));
                    504:        un->un_dtype = un->un_stype = 5;
                    505:        un->un_ptype = UNTYPE_INQUIRE;
                    506:        s = splimp();
                    507:        IF_PREPEND(&us->us_if.if_snd, m);
                    508:        splx(s);
                    509: }
                    510: 
                    511: /*
                    512:  * Process an ioctl request.
                    513:  */
                    514: unioctl(ifp, cmd, data)
                    515:        register struct ifnet *ifp;
                    516:        int cmd;
                    517:        caddr_t data;
                    518: {
                    519:        struct ifreq *ifr = (struct ifreq *)data;
                    520:        int s = splimp(), error = 0;
                    521: 
                    522:        switch (cmd) {
                    523: 
                    524:        case SIOCSIFADDR:
                    525:                if (ifp->if_flags & IFF_RUNNING)
                    526:                        if_rtinit(ifp, -1);     /* delete previous route */
                    527:                unsetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
                    528:                if (ifp->if_flags & IFF_RUNNING)
                    529:                        if_rtinit(ifp, RTF_UP);
                    530:                else
                    531:                        uninit(ifp->if_unit);
                    532:                break;
                    533: 
                    534:        default:
                    535:                error = EINVAL;
                    536:        }
                    537:        splx(s);
                    538:        return (error);
                    539: }
                    540: 
                    541: unsetaddr(ifp, sin)
                    542:        register struct ifnet *ifp;
                    543:        register struct sockaddr_in *sin;
                    544: {
                    545: 
                    546:        ifp->if_net = in_netof(sin->sin_addr);
                    547:        sin = (struct sockaddr_in *)&ifp->if_addr;
                    548:        sin->sin_family = AF_INET;
                    549:        /* host number filled in already, or filled in later */
                    550:        sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]);
                    551:        sin = (struct sockaddr_in *)&ifp->if_broadaddr;
                    552:        sin->sin_family = AF_INET;
                    553:        sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
                    554:        ifp->if_flags |= IFF_BROADCAST;
                    555: }
                    556: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.