Annotation of 43BSDReno/sys/netiso/if_un.eg, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright IBM Corporation 1987,1990
                      3:  *
                      4:  * All Rights Reserved
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software and its
                      7:  * documentation for any purpose and without fee is hereby granted,
                      8:  * provided that the above copyright notice appear in all copies and that
                      9:  * both that copyright notice and this permission notice appear in
                     10:  * supporting documentation, and that the name of IBM not be
                     11:  * used in advertising or publicity pertaining to distribution of the
                     12:  * software without specific, written prior permission.
                     13:  *
                     14:  * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     15:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR USE.
                     16:  * IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
                     17:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     18:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
                     19:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
                     20:  * THIS SOFTWARE.
                     21:  *
                     22:  *     @(#)if_un.eg    7.1 (Berkeley) 10/29/90
                     23:  */
                     24: 
                     25: /*
                     26:  * Ungermann-Bass PC-NIC (Ethernet) Adapter  (4.3 driver)
                     27:  */
                     28: 
                     29: #include "un.h"
                     30: #if NUN > 0
                     31: 
                     32: #include "../machine/pte.h"
                     33: 
                     34: #include "param.h"
                     35: #include "systm.h"
                     36: #include "mbuf.h"
                     37: #include "buf.h"
                     38: #include "protosw.h"
                     39: #include "socket.h"
                     40: #include "vmmac.h"
                     41: #include "ioctl.h"
                     42: #include "errno.h"
                     43: 
                     44: #include "../net/if.h"
                     45: #include "../net/netisr.h"
                     46: #include "../net/route.h"
                     47: 
                     48: #ifdef INET
                     49: #include "../netinet/in.h"
                     50: #include "../netinet/in_systm.h"
                     51: #include "../netinet/in_var.h"
                     52: #include "../netinet/ip.h"
                     53: #include "../netinet/if_ether.h"
                     54: #endif INET
                     55: 
                     56: #ifdef NS
                     57: #include "../netns/ns.h"
                     58: #include "../netns/ns_if.h"
                     59: #endif NS
                     60: 
                     61: #ifdef ISO
                     62: #include "../netargo/if_clnp.h"
                     63: #include "../netargo/iso.h"
                     64: #include "../netargo/iso_var.h"
                     65: #include "../netargo/argo_debug.h"
                     66: #endif ISO
                     67: 
                     68: #include "../machine/io.h"
                     69: #include "if_unreg.h"
                     70: #ifdef IEEELLC
                     71: #include "if_llc.h"
                     72: #endif IEEELLC
                     73: #include "../machineio/ioccvar.h"
                     74: #include "../machine/debug.h"
                     75: 
                     76: int    unprobe(), unattach();
                     77: 
                     78: #ifdef AT
                     79: caddr_t unstd[] = { (caddr_t) 0xa0000, (caddr_t) 0xa8000,
                     80:        (caddr_t) 0xb0000, (caddr_t) 0xb8000, 0 };
                     81: #else
                     82: caddr_t unstd[] = { (caddr_t) 0xf4080000, (caddr_t) 0xf4088000,
                     83:        (caddr_t) 0xf4090000, (caddr_t) 0xf4098000, 0 };
                     84: #endif AT
                     85: 
                     86: struct iocc_device *uninfo[NUN];
                     87: 
                     88: int    unint(),  uninit(), unioctl(), unoutput(), unreset();
                     89: 
                     90: struct iocc_driver undriver =
                     91:        { unprobe, 0, unattach, 0, unstd, "un", uninfo,
                     92:                0, 0, unint, UN_EADDROFF };
                     93: 
                     94: struct mbuf *unget();
                     95: 
                     96: /*
                     97:  * Ethernet software status per adapter.
                     98:  */
                     99: struct un_softc {
                    100:        struct  arpcom us_ac;           /* generic network interface stuff */
                    101: #define        us_if   us_ac.ac_if             /* ifnet struct */
                    102: #define        us_addr us_ac.ac_enaddr         /* hardware (i.e. ethernet) address */
                    103:        short   us_oactive;             /* 1 => output active */
                    104:        short   us_nextpage;            /* next receive buffer page */
                    105:        short   us_xbuf;                /* in-use xmt buf (if output active) */
                    106:        short   us_xfull[2];            /* 1 => a full xmt buf */
                    107:        short   us_xstart[2];           /* start address used in unstart */
                    108: } un_softc[NUN];
                    109: 
                    110: #ifdef DEBUG
                    111: char undebug = 0;
                    112: #endif DEBUG
                    113: 
                    114: #ifdef ATR
                    115: #define move_window(window, addr)      {\
                    116:        int real_addr;\
                    117:        int new_window;\
                    118:        \
                    119:        window = get_128_window();\
                    120:        real_addr = 0xfffff & (int) addr;\
                    121:        new_window = real_addr & 0xe0000;\
                    122:        set_128_window(new_window);\
                    123:        addr = (struct undevice *) (real_addr - new_window);\
                    124: }
                    125: 
                    126: #define restore_window(window) set_128_window(window)
                    127: #define bcopyin(from,to,len) bcopy((from)+pcif_128_fw,to,len)
                    128: #define bcopyout(from,to,len) bcopy(from,(to)+pcif_128_fw,len)
                    129: #endif ATR
                    130: 
                    131: #ifdef IBMRTPC
                    132: #define bcopyin bcopy
                    133: #define bcopyout bcopy
                    134: #endif IBMRTPC
                    135: /*
                    136:  *  unprobe - try to generate an interrupt (to see if the board is there)
                    137:  */
                    138: unprobe(p)
                    139:        register caddr_t p;
                    140: {
                    141:        register struct undevice *addr = (struct undevice *) p;
                    142: #ifdef ATR
                    143:        register int old_window;
                    144:        move_window(old_window, addr);
                    145: #endif ATR
                    146:        (void) unzap(addr);
                    147:        UN_GLOBIENB(0);                 /* global interrrupt enable */
                    148:        MM_OUT(&addr->un_csr, UN_GSFTINT);  /* generate software interrupt */
                    149:        PROBE_DELAY(100000);
                    150:        MM_OUT(&addr->un_csr, 0);
                    151: #ifdef ATR
                    152:        restore_window(old_window);
                    153: #endif ATR
                    154:        return(PROBE_OK);
                    155: }
                    156: 
                    157: /*
                    158:  *  unattach - make the interface available to the network software
                    159:  *  (if the auto-configuration software determines that the interface
                    160:  *  exists).  The system will initialize the interface when it is
                    161:  *  ready to accept packets.
                    162:  */
                    163: unattach(iod)
                    164:        register struct iocc_device *iod;
                    165: {
                    166:        register struct un_softc *us = &un_softc[iod->iod_unit];
                    167:        register struct ifnet *ifp = &us->us_if;
                    168:        register struct undevice *addr = (struct undevice *) iod->iod_addr;
                    169:        register int i;
                    170: #ifdef ATR
                    171:        register int old_window;
                    172: 
                    173:        move_window(old_window, addr);
                    174: #endif ATR
                    175:        ifp->if_unit = iod->iod_unit;
                    176:        ifp->if_name = "un";
                    177: 
                    178: #ifdef IEEELLC
                    179:        ifp->if_mtu = ETHERMTU - 3;             /* 3 bytes for UI LLC frame */
                    180: #else
                    181:        ifp->if_mtu = ETHERMTU;
                    182: #endif IEEELCC
                    183: 
                    184:        /*
                    185:         * Read the ethernet address off the board.
                    186:         * Save it and also write it to the edlc chip.
                    187:         */
                    188:        for (i = 0; i < ETH_ADDR_SIZE; i++){
                    189:                us->us_addr[i] = MM_IN(&addr->un_eprom[UN_EADDROFF+i]);
                    190:                MM_OUT(&addr->un_edlc.nodeID[i], us->us_addr[i]);
                    191:        }
                    192:        printf("un%d: ethernet address ", ifp->if_unit);
                    193:        unprintethaddr(us->us_addr);
                    194:        printf("\n");
                    195:        ifp->if_init = uninit;
                    196:        ifp->if_ioctl = unioctl;
                    197:        ifp->if_output = unoutput;
                    198:        ifp->if_reset = unreset;
                    199:        ifp->if_flags = IFF_BROADCAST;
                    200: #ifdef ISO
                    201:        ifp->if_flags |= IFF_EAVESDROP;
                    202: #endif ISO
                    203:        if_attach(ifp);
                    204:        DEBUGF(undebug, printf("un%d: attached\n", iod->iod_unit);)
                    205: #ifdef ATR
                    206:        restore_window(old_window);
                    207: #endif ATR
                    208: }
                    209: 
                    210: /*
                    211:  *  unreset - reset interface
                    212:  */
                    213: unreset(unit)
                    214:        register unsigned int unit;
                    215: {
                    216:        register struct iocc_device *iod;
                    217: 
                    218:        if (unit < NUN && (iod = uninfo[unit]) != 0 && iod->iod_alive != 0){
                    219:                un_softc[unit].us_if.if_flags &= ~IFF_RUNNING;
                    220:                DEBUGF(undebug, printf("un%d: reset\n", unit);)
                    221:                uninit(unit);
                    222:        }
                    223: }
                    224: 
                    225: /*
                    226:  *  uninit - initialize interface, enable packet reception, start any
                    227:  *  pending writes
                    228:  */
                    229: uninit(unit)
                    230:        register int unit;
                    231: {
                    232:        register struct un_softc *us = &un_softc[unit];
                    233:        register struct ifnet *ifp = &us->us_if;
                    234:        register int s;
                    235:        register struct undevice *addr;
                    236:        register int i;
                    237: 
                    238:        if (ifp->if_addrlist == (struct ifaddr *) 0){
                    239:                /* no address */
                    240:                return;
                    241:        }
                    242:        if ((ifp->if_flags & IFF_RUNNING) == 0){
                    243:                int old_window;
                    244: 
                    245:                addr = (struct undevice *) (uninfo[unit]->iod_addr);
                    246: #ifdef ATR
                    247:                move_window(old_window, addr);
                    248: #endif ATR
                    249:                s = splimp();
                    250:                us->us_nextpage = unzap(addr);  /* initialize hardware */
                    251:                        /* unzap returns next receive page to be used */
                    252:                for (i = 0; i < ETH_ADDR_SIZE; i++){
                    253:                        MM_OUT(&addr->un_edlc.nodeID[i], us->us_addr[i]);
                    254:                }
                    255:                us->us_oactive = 0;     /* output not active */
                    256:                /*  turn adapter on */
                    257:                ifp->if_flags |= IFF_RUNNING;
                    258:                MM_OUT(&addr->un_csr, UN_PAVIENB);
                    259:                        /* Allow packet available interrupts */
                    260:                UN_GLOBIENB(us->us_nextpage);   /* global interrrupt enable */
                    261:                if (ifp->if_snd.ifq_head){      /* anything on send queue */
                    262:                        struct mbuf *m;
                    263: 
                    264:                        IF_DEQUEUE(&ifp->if_snd, m);
                    265:                        unput(us, addr, m, 0);
                    266:                        unstart(us, addr, 0);
                    267:                        if (ifp->if_snd.ifq_head){
                    268:                                IF_DEQUEUE(&ifp->if_snd, m);
                    269:                                unput(us, addr, m, 1);
                    270:                        }
                    271:                }
                    272:                splx(s);
                    273: #ifdef ATR
                    274:                restore_window(old_window);
                    275: #endif ATR
                    276:        }
                    277:        DEBUGF(undebug, printf("un%d: init'ed\n", unit);)
                    278: }
                    279: 
                    280: /*
                    281:  *  unstart - start output from one of the adapter's 2 transmit buffers
                    282:  */
                    283: unstart(us, addr, xbuf)
                    284:        register struct un_softc *us;
                    285:        register struct undevice *addr;
                    286:        register int xbuf;
                    287: {
                    288:        us->us_oactive = 1;
                    289:        us->us_xbuf = xbuf;
                    290:        UN_XMIT(addr, us->us_xstart[xbuf]);
                    291:        MM_OUT(&addr->un_csr, UN_IENABLE); /* enable transmit done interrupt */
                    292: }
                    293: 
                    294: /*
                    295:  *  unint - interrupt handler.  find the cause of the interrupt and
                    296:  *  dispatch an appropriate handler routine.
                    297:  */
                    298: unint(unit)
                    299:        register int unit;
                    300: {
                    301:        register struct un_softc *us = &un_softc[unit];
                    302:        register struct undevice *addr =
                    303:          (struct undevice *) uninfo[unit]->iod_addr;
                    304:        register char status;
                    305:        register int rc = 1;
                    306: #ifdef ATR
                    307:        register int old_window;
                    308: 
                    309:        move_window(old_window, addr);
                    310: #endif ATR
                    311: 
                    312:        UN_DISABLE(us->us_nextpage);
                    313:        while ((status = ~MM_IN(&addr->un_csr)) & UN_PAVINT){
                    314:                DEBUGF(undebug & 0x2, printf("unint: unit = %d, csr = %b",
                    315:                  unit, status & 0xff, UN_CSRBITS);)
                    316:                unrint(unit, us, addr);
                    317:                rc = 0;
                    318:        }
                    319:        if (status & UN_TXRINT){
                    320:                DEBUGF(undebug & 0x2, printf("unint: unit = %d, csr = %b",
                    321:                  unit, status & 0xff, UN_CSRBITS);)
                    322:                unxint(unit, us, addr);
                    323:                rc = 0;
                    324:        }
                    325:        UN_ENABLE(us->us_nextpage);
                    326: #ifdef ATR
                    327:        restore_window(old_window);
                    328: #endif ATR
                    329:        return(rc);
                    330: }
                    331: 
                    332: /*
                    333:  *  unrint - interrupt handler for packet reception.
                    334:  *
                    335:  *  log error if error bits are latched,  examine packet to determine
                    336:  *  type, if can't determine packet length from type, drop packet.
                    337:  *  otherwise decapsulate packet based on type and pass to an appropriate
                    338:  *  higher-level input routine.
                    339:  */
                    340: unrint(unit, us, addr)
                    341:        int unit;
                    342:        register struct un_softc *us;
                    343:        register struct undevice *addr;
                    344: {
                    345:        register struct ether_header *eh;
                    346:        register struct mbuf *m;
                    347:        register int len;
                    348:        register int off;
                    349:        int resid;
                    350:        struct ifqueue *inq;
                    351:        char status = MM_IN(&addr->un_edlc.rstat);
                    352:        u_short type;
                    353:        u_short ungetushortatoff();
                    354: #ifdef IEEELLC
                    355:        struct ether_header     ehbuf;
                    356: #endif IEEELLC
                    357: 
                    358:        MM_OUT(&addr->un_edlc.rstat, status);   /* clear status */
                    359:        /* (the hardware xor's in the value of status setting rstat to 0) */
                    360:        DEBUGF(undebug & 0x2, printf(" rstat = %b", status, RS_BITS);)
                    361:        /*
                    362:         *  Latch errors.  (Errors found correspond to packets
                    363:         *  that were received prior to the current packet
                    364:         *  since packet available interrupts are generated
                    365:         *  for good packets only.)
                    366:         */
                    367:        if (status & RS_ERR){
                    368:                DEBUGF(undebug, printf("unrint: input error\n");)
                    369:                us->us_if.if_ierrors++;
                    370:        }
                    371:        us->us_if.if_ipackets++;
                    372: 
                    373:        /*
                    374:         *  determine the length of the received packet.
                    375:         */
                    376:        len = 0;
                    377:        off = us->us_nextpage;
                    378: 
                    379: #define BUMP(page)     if (++(page) == UN_NUMRBUFS) page = 0
                    380:        while ((MM_IN(&addr->un_pram[us->us_nextpage]) & UN_LAST_PAGE) == 0){
                    381:                len += UN_RBUFSIZE;
                    382:                BUMP(us->us_nextpage);
                    383:        }
                    384:        len += (MM_IN(&addr->un_pram[us->us_nextpage]) &
                    385:                UN_PAGE_LENGTH_MASK) + 1;
                    386:        BUMP(us->us_nextpage);
                    387: #undef BUMP
                    388:        DEBUGF(undebug & 0x2, printf(" len = %d ", len);)
                    389:        if (len > UN_XBSIZE){
                    390:                printf("un%d: huge packet!\n",unit);
                    391:                goto chuckit;
                    392:        }
                    393:        /*
                    394:         * Process the packet
                    395:         */
                    396:        eh = (struct ether_header *) &addr->un_rcvbuf[off][0];
                    397:        DEBUGF(undebug & 0x2,
                    398:                {  char cbuf[6];
                    399:                printf(" from = ");
                    400:                bcopyin(eh->ether_shost, cbuf, sizeof(cbuf));
                    401:                unprintethaddr(cbuf);
                    402:                printf("  to = ");
                    403:                bcopyin(eh->ether_dhost, cbuf, sizeof(cbuf));
                    404:                unprintethaddr(cbuf);
                    405:                printf(" "); }
                    406:        )
                    407:        len -= sizeof(struct ether_header);
                    408:        type = ntohs((u_short) MM_INW(&eh->ether_type));
                    409:        /*
                    410:         *  The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL
                    411:         *  have (type - ETHERTYPE_TRAIL) * 512 bytes of data followed by
                    412:         *  a type field and then a (variable length) header
                    413:         */
                    414:        if (type >= ETHERTYPE_TRAIL &&
                    415:            type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER){
                    416:                off = (type - ETHERTYPE_TRAIL) * 512;
                    417:                if (off >= ETHERMTU){
                    418:                        goto chuckit;
                    419:                }
                    420:                type = ungetushortatoff(addr, eh, off);
                    421:                resid = ungetushortatoff(addr, eh, off + 2);
                    422:                if (off + resid > len){
                    423:                        goto chuckit;
                    424:                }
                    425:                len = off + resid;
                    426:        } else {
                    427:                off = 0;
                    428:        }
                    429:        if (len == 0){
                    430:                goto chuckit;
                    431:        }
                    432: 
                    433: #ifdef IEEELLC
                    434:        if (type <= ETHERMTU) {
                    435:                /* may need ether_header for XID, TEST LLC functions */
                    436:                ehbuf = *eh;
                    437:        }
                    438: #endif IEEELLC
                    439: 
                    440:        /*
                    441:         *  pull packet off interface.  if off is non-zero, the
                    442:         *  packet has a trailing "header".  unget will move this
                    443:         *  header to the front, but we still have to remove the
                    444:         *  type and length fields from the front of the data.
                    445:         */
                    446:        m = unget(addr, (char *) eh, len, off, &us->us_if);
                    447:        /*
                    448:         *  update the full page pointer and clear the packet available
                    449:         *  flag if necessary.  update the fpp here to free the on-board
                    450:         *  receive pages as soon as possible.
                    451:         */
                    452:        unupdatefpp(addr, us->us_nextpage);
                    453:        if (m != 0){
                    454:                if (off){
                    455: #ifdef ISO
                    456:                        /* 
                    457:                         *      Move snpa header over by 4 bytes to skip
                    458:                         *      the trailer Type and Header length fields.
                    459:                         */
                    460:                        struct snpa_hdr         sh;
                    461: 
                    462:                        bcopy(mtod(m, char *), (caddr_t)&sh, sizeof(struct snpa_hdr));
                    463:                        m->m_off += 2 * sizeof(u_short);
                    464:                        m->m_len -= 2 * sizeof(u_short);
                    465:                        bcopy((caddr_t)&sh, mtod(m, char *), sizeof(struct snpa_hdr));
                    466: #else  ISO
                    467:                        struct ifnet *ifp;
                    468:                        /*
                    469:                         * bcopy is used since word moves must be on 4 byte
                    470:                         * boundaries on the RT PC
                    471:                         */
                    472:                        bcopy(mtod(m, char *), (char *) &ifp, sizeof(ifp));
                    473:                        m->m_off += 2 * sizeof(u_short);
                    474:                        m->m_len -= 2 * sizeof(u_short);
                    475:                        bcopy((char *) &ifp, mtod(m, char *), sizeof(ifp));
                    476: #endif ISO
                    477:                }
                    478:                switch (type){
                    479: #ifdef INET
                    480:                case ETHERTYPE_IP:
                    481:                    {
                    482:                        int s;
                    483: 
                    484:                        DEBUGF(undebug & 0x2, printf("ip packet\n");)
                    485:                        schednetisr(NETISR_IP);
                    486:                        s = splimp();
                    487:                        inq = &ipintrq;
                    488:                        if (IF_QFULL(inq)){
                    489:                                DEBUGF(undebug & 0x2, printf(" qfull\n");)
                    490:                                IF_DROP(inq);
                    491:                                m_freem(m);
                    492:                        } else {
                    493:                                IF_ENQUEUE(inq, m);
                    494:                                DEBUGF(undebug & 0x2, printf(" queued\n");)
                    495:                        }
                    496:                        splx(s);
                    497:                        break;
                    498:                    }
                    499: 
                    500:                case ETHERTYPE_ARP:
                    501:                        DEBUGF(undebug & 0x2, printf("arp packet\n");)
                    502:                        arpinput(&us->us_ac, m);  /* arpinput frees m */
                    503:                        break;
                    504: #endif INET
                    505: #ifdef NS
                    506:                case ETHERTYPE_NS:
                    507:                        DEBUGF(undebug & 0x2, printf("ns packet\n");)
                    508:                        schednetisr(NETISR_NS);
                    509:                        inq = &nsintrq;
                    510:                        break;
                    511: #endif NS
                    512: #ifndef        IEEELLC
                    513: #ifdef ISO
                    514:                case ETHERTYPE_CLNP:    /* should be CLNL */
                    515:                        DEBUGF(undebug & 0x2, printf("clnl packet\n");)
                    516: 
                    517:                        /* IFF_EAVESDROP can not be turned off for Ethernet */
                    518: 
                    519:                        schednetisr(NETISR_CLNP);
                    520:                        inq = &clnlintrq;
                    521:                        if (IF_QFULL(inq)){
                    522:                                DEBUGF(undebug & 0x2, printf(" qfull\n");)
                    523:                                IF_DROP(inq);
                    524:                                m_freem(m);
                    525:                        } else {
                    526:                                IF_ENQUEUE(inq, m);
                    527:                                DEBUGF(undebug & 0x2, printf(" queued\n");)
                    528:                        }
                    529:                        break;
                    530: #endif ISO
                    531:                default:
                    532:                        DEBUGF(undebug & 0x2, printf("unknown packet\n");)
                    533:                        m_freem(m);
                    534:                        break;
                    535: #else
                    536:                default: {
                    537:                        struct llc *l;
                    538:                        caddr_t         pkt_start;
                    539: #ifdef ISO
                    540: #define        PREPENDED_SIZE  sizeof(struct snpa_hdr)
                    541: #else
                    542: #define        PREPENDED_SIZE  sizeof(struct ifnet *)
                    543: #endif ISO
                    544:                        if (type > ETHERMTU)
                    545:                                goto not802;
                    546: 
                    547:                        /*
                    548:                         *      This assumes that the snpa header is in the same mbuf
                    549:                         *      as the llc header. Currently this is ok, but if
                    550:                         *      unget allocates a cluster, this will not be the case
                    551:                         */
                    552:                        pkt_start = mtod(m, caddr_t);
                    553:                        l = (struct llc *) (pkt_start + PREPENDED_SIZE);
                    554: 
                    555:                        IFDEBUG(D_ETHER)
                    556:                                printf("unrint: llc: length %d, control x%x:\n", type,
                    557:                                        l->llc_control);        
                    558:                        ENDDEBUG
                    559: 
                    560:                        switch (l->llc_control) {
                    561:                        case LLC_UI:
                    562:                        /* LLC_UI_P forbidden in class 1 service */
                    563: #ifdef ISO
                    564:                                if (l->llc_dsap == LLC_ISO_LSAP) {
                    565:                                        if ((IS_MULTICAST(ehbuf.ether_dhost)) &&
                    566:                                                ((us->us_if.if_flags & IFF_EAVESDROP) == 0) &&
                    567:                                                (!snpac_ownmulti(ehbuf.ether_dhost, 6))) {
                    568:                                                m_freem(m);
                    569:                                                return;
                    570:                                        }
                    571: 
                    572:                                        /* move struct snpa_header over the llc header */
                    573:                                        clnp_ypocb(pkt_start, pkt_start + 3, 
                    574:                                                PREPENDED_SIZE);
                    575:                                        m->m_off += 3;
                    576:                                        m->m_len -= 3;
                    577: 
                    578:                                        DEBUGF(undebug & 0x2, printf("clnp packet\n");)
                    579:                                        schednetisr(NETISR_CLNP);
                    580:                                        inq = &clnlintrq;
                    581:                                        if (IF_QFULL(inq)){
                    582:                                                DEBUGF(undebug & 0x2, printf(" qfull\n");)
                    583:                                                IF_DROP(inq);
                    584:                                                m_freem(m);
                    585:                                        } else {
                    586:                                                IF_ENQUEUE(inq, m);
                    587:                                                DEBUGF(undebug & 0x2, printf(" queued\n");)
                    588:                                        }
                    589:                                        return;
                    590:                            } else {
                    591:                                        IFDEBUG(D_ETHER)
                    592:                                                printf("unrint: unknown llc sap\n");
                    593:                                        ENDDEBUG
                    594:                                        m_freem(m);
                    595:                                        return;
                    596:                                }
                    597: #endif ISO
                    598:                            break;
                    599: /* LLC_XID, LLC_XID_P, LLC_TEST, and LLC_TEST_P are untested */
                    600:                        case LLC_XID:
                    601:                        case LLC_XID_P: /* control field is untouched for resp */
                    602:                            if(m->m_len < 6)
                    603:                                        goto not802;
                    604:                            l->llc_fid = LLC_IEEE_basic_format;
                    605:                            l->llc_class = LLC_CLASS1;
                    606:                            l->llc_window = 0;
                    607:                            l->llc_dsap = l->llc_ssap = 0;
                    608:                            /* FALL THROUGH */
                    609:                        case LLC_TEST:
                    610:                        case LLC_TEST_P: {
                    611:                                struct ifnet *ifp = &us->us_if;
                    612:                            struct sockaddr_iso siso;
                    613:                            u_char c = l->llc_dsap;
                    614:                            l->llc_dsap = l->llc_ssap;
                    615:                            l->llc_ssap = c;
                    616: 
                    617:                            /* Do not TEST or XID to multicasts */
                    618:                            if (IS_MULTICAST(ehbuf.ether_dhost)) {
                    619:                                        m_freem(m);
                    620:                                        break;
                    621:                                }
                    622: 
                    623:                            siso.siso_family = AF_ISO;
                    624:                                bcopy(ehbuf.ether_shost, siso.siso_addr.sna_idi, 6);
                    625:                                siso.siso_addr.isoa_afi = AFI_SNA;
                    626:                                siso.siso_addr.isoa_len = 7;
                    627: 
                    628:                                /* trim off prepended snpa_hdr or ifp */
                    629:                                m->m_off += PREPENDED_SIZE;
                    630:                                m->m_len -= PREPENDED_SIZE;
                    631: 
                    632:                            unoutput(ifp, m, &siso);
                    633:                            return;
                    634:                        }
                    635:                        not802:
                    636:                        default:
                    637:                                DEBUGF(undebug & 0x2, printf("unknown packet\n");)
                    638:                                m_freem(m);
                    639:                                break;
                    640:                        }
                    641:                }
                    642: #endif IEEELLC
                    643:                }
                    644:        }
                    645:        return;
                    646: chuckit:
                    647:        DEBUGF(undebug, printf("unrint: packet dropped\n");)
                    648:        unupdatefpp(addr, us->us_nextpage);
                    649: }
                    650: 
                    651: /*
                    652:  *  unxint -  interrupt handler for transmit ready
                    653:  */
                    654: unxint(unit, us, addr)
                    655:        register int unit;
                    656:        register struct un_softc *us;
                    657:        register struct undevice *addr;
                    658: {
                    659:        register char status;
                    660:        register int next_buf;
                    661: 
                    662:        /*
                    663:         *  collect stats on last packet
                    664:         */
                    665:        status = MM_IN(&addr->un_edlc.xstat);
                    666:        MM_OUT(&addr->un_edlc.xstat, status);   /* clear status bits */
                    667:        DEBUGF(undebug & 0x2, printf(" unxint: xstat = %b\n",
                    668:          status & 0xff, XS_BITS);)
                    669:        if (status & XS_16CL){
                    670:                us->us_if.if_collisions += 16;
                    671:                us->us_if.if_oerrors++;
                    672:                printf("un%d: ethernet jammed\n", unit);
                    673:        }
                    674:        else if (status & XS_SHRT){
                    675:                us->us_if.if_oerrors++;
                    676:                printf( "un%d: ethernet not responding (is it connected?)\n",
                    677:                        unit);
                    678:        }
                    679:        else {
                    680:                us->us_if.if_opackets++;
                    681:                us->us_if.if_collisions += UN_NCOLL(addr);
                    682:        }
                    683:        DEBUGF(undebug & 0x2,
                    684:          printf(" ipkt = %d ierr = %d okt = %d oerr = %d coll = %d\n",
                    685:            us->us_if.if_ipackets, us->us_if.if_ierrors,
                    686:            us->us_if.if_opackets, us->us_if.if_oerrors,
                    687:            us->us_if.if_collisions);)
                    688:        /*  mark the current transmit buffer empty */
                    689:        us->us_xfull[us->us_xbuf] = 0;
                    690:        /*  switch to the other transmit buffer */
                    691:        next_buf = 1 - us->us_xbuf;
                    692:        if (us->us_xfull[next_buf]){    /*  if it's full */
                    693:                unstart(us, addr, next_buf);    /* start output from it */
                    694:                if (us->us_if.if_snd.ifq_head){ /*  if more on out queue */
                    695:                        struct mbuf *m;
                    696: 
                    697:                        IF_DEQUEUE(&us->us_if.if_snd, m); /* fill empty buf */
                    698:                        unput(us, addr, m, 1 - next_buf);
                    699:                }
                    700:        }
                    701:        else {  /*  the other transmit buffer is empty */
                    702:                us->us_oactive = 0;
                    703:                MM_OUT(&addr->un_csr, UN_PAVIENB);      /* Turn off TxRIENB */
                    704:        }
                    705: }
                    706: 
                    707: /*
                    708:  *  unoutput - ethernet output routine.  encapsulate a packet of type
                    709:  *  family for the local net.  use trailer local net encapsulation if
                    710:  *  the number of bytes in the mbufs after the first is a multiple of
                    711:  *  512.
                    712:  */
                    713: unoutput(ifp, m0, dst)
                    714:        register struct ifnet *ifp;
                    715:        register struct mbuf *m0;
                    716:        register struct sockaddr *dst;
                    717: {
                    718:        u_short type;
                    719:        int s;
                    720:        int error;
                    721:        char edst[ETH_ADDR_SIZE];
                    722:        struct in_addr idst;
                    723:        register struct un_softc *us = &un_softc[ifp->if_unit];
                    724:        register struct mbuf *m = m0;
                    725:        register struct ether_header *eh;
                    726:        int off;
                    727:        struct mbuf *m_get();
                    728:        int usetrailers;
                    729: 
                    730:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)){
                    731:                error = ENETDOWN;
                    732:                goto bad;
                    733:        }
                    734:        switch (dst->sa_family){
                    735: 
                    736: #ifdef INET
                    737:        case AF_INET:
                    738:                idst = ((struct sockaddr_in *)dst)->sin_addr;
                    739:                if (!arpresolve(&us->us_ac, m, &idst, edst, &usetrailers)){
                    740:                        /* not resolved */
                    741:                        return(0);
                    742:                }
                    743:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                    744:                if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
                    745:                  m->m_off >= MMINOFF + 2 * sizeof(u_short)){
                    746:                        type = ETHERTYPE_TRAIL + (off>>9);
                    747:                        m->m_off -= 2 * sizeof(u_short);
                    748:                        m->m_len += 2 * sizeof(u_short);
                    749:                        *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
                    750:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                    751:                        /*
                    752:                         *  Packet to be sent with trailer, move first packet
                    753:                         *  (control information) to end of chain.
                    754:                         */
                    755:                        while (m->m_next)
                    756:                                m = m->m_next;
                    757:                        m->m_next = m0;
                    758:                        m = m0->m_next;
                    759:                        m0->m_next = 0;
                    760:                        m0 = m;
                    761:                }
                    762:                else {
                    763:                        type = ETHERTYPE_IP;
                    764:                }
                    765:                break;
                    766: #endif INET
                    767: #ifdef NS
                    768:        case AF_NS:
                    769:                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
                    770:                  (caddr_t)edst, sizeof(edst));
                    771:                type = ETHERTYPE_NS;
                    772:                off = 0;
                    773:                break;
                    774: #endif NS
                    775: #ifdef ISO
                    776:        case AF_ISO: {
                    777:                int     ret;
                    778:                int len;
                    779:                struct iso_addr *dst_nsap = &((struct sockaddr_iso *)dst)->siso_addr;
                    780:  
                    781:                if ((ret = iso_tryloopback(m, dst)) >= 0)
                    782:                        return (ret);
                    783:                else if (ret = iso_snparesolve(&us->us_ac.ac_if, dst_nsap, edst, &len)){
                    784:                        /* not resolved */
                    785:                        IFDEBUG(D_ETHER)
                    786:                                printf("unoutput: clnp packet dropped\n");
                    787:                        ENDDEBUG
                    788:                        m_freem(m);
                    789:                        return(ret);
                    790:                } else if (len != 6) {
                    791:                        printf("unoutput: snpa len is not 6 (%d)\n", len);
                    792:                        m_freem(m);
                    793:                        return(ENETUNREACH);
                    794:                }
                    795: 
                    796: #ifndef        IEEELLC
                    797:                type = ETHERTYPE_CLNP;
                    798: #else
                    799:                /* check for enough space for LLC header */
                    800:                {
                    801:                        struct mbuf *llcm;
                    802:                        char            *cp;
                    803:                        if (m->m_off >= MMAXOFF || m->m_off < MMINOFF + 3) {
                    804:                                MGET(llcm, M_DONTWAIT, MT_DATA);
                    805:                                if (llcm == NULL) {
                    806:                                        m_freem(m);
                    807:                                        return(0);
                    808:                                }
                    809:                                llcm->m_off = MMAXOFF - 3;
                    810:                                llcm->m_len = 3;
                    811:                                llcm->m_next = m;
                    812:                                m = llcm;
                    813:                        } else {
                    814:                                m->m_off -= 3;
                    815:                                m->m_len += 3;
                    816:                        }
                    817:                        type = m_datalen(m);
                    818: 
                    819:                        cp = mtod(m, u_char *);
                    820:                        cp[0] = cp[1] = LLC_ISO_LSAP; cp[2] = LLC_UI;
                    821:                        off = 0;
                    822:                }
                    823: #endif IEEELLC
                    824:                off = 0;
                    825:                IFDEBUG(D_ETHER)
                    826:                        int i;
                    827:                        printf("unoutput: sending pkt to: ");
                    828:                        for (i=0; i<6; i++)
                    829:                                printf("%x ", edst[i] & 0xff);
                    830: #ifdef IEEELLC
                    831:                        printf(" llc len %d", type);
                    832: #endif IEEELLC
                    833:                        printf("\n");
                    834:                ENDDEBUG
                    835:                } break;
                    836: #endif ISO
                    837:        case AF_UNSPEC:
                    838:                eh = (struct ether_header *)dst->sa_data;
                    839:                bcopy((char *)eh->ether_dhost, (caddr_t)edst, sizeof(edst));
                    840:                type = eh->ether_type;
                    841:                break;
                    842:        default:
                    843:                printf("un%d: can't handle af%d\n", ifp->if_unit,
                    844:                  dst->sa_family);
                    845:                error = EAFNOSUPPORT;
                    846:                goto bad;
                    847:        }
                    848:        /*
                    849:         * Add local net header.  If no space in first mbuf,
                    850:         * allocate another.
                    851:         */
                    852:        if (m->m_off > MMAXOFF ||
                    853:            MMINOFF + sizeof(struct ether_header) > m->m_off){
                    854:                m = m_get(M_DONTWAIT, MT_HEADER);
                    855:                /*
                    856:                 *  Note:  m_get, m_freem etc. guard against concurrent
                    857:                 *  updates to the list of free mbufs.
                    858:                 */
                    859:                if (m == 0){
                    860:                        error = ENOBUFS;
                    861:                        goto bad;
                    862:                }
                    863:                m->m_next = m0;
                    864:                m->m_off = MMINOFF;
                    865:                m->m_len = sizeof(struct ether_header);
                    866:        } else {
                    867:                m->m_off -= sizeof(struct ether_header);
                    868:                m->m_len += sizeof(struct ether_header);
                    869:        }
                    870:        eh = mtod(m, struct ether_header *);
                    871:        bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof(edst));
                    872:        bcopy((caddr_t)us->us_addr, (caddr_t)eh->ether_shost,
                    873:          sizeof(eh->ether_shost));
                    874:        bcopy((caddr_t)&type, (caddr_t)&eh->ether_type, sizeof(u_short));
                    875: 
                    876:        /*
                    877:         *  queue packet for transmission.  if there is an empty
                    878:         *  transmit buffer on the adapter, use it.
                    879:         */
                    880:        s = splimp();
                    881:        if (IF_QFULL(&ifp->if_snd)){
                    882:                IF_DROP(&ifp->if_snd);
                    883:                error = ENOBUFS;
                    884:                goto qfull;
                    885:        }
                    886:        if (us->us_xfull[0] == 0 || us->us_xfull[1] == 0){ /* empty xmt buf */
                    887:                struct undevice *addr = (struct undevice *)
                    888:                  uninfo[ifp->if_unit]->iod_addr;
                    889:                int next_buf;
                    890: #ifdef ATR
                    891:                int old_window;
                    892:                move_window(old_window, addr);
                    893: #endif ATR
                    894:                if (us->us_xfull[0] == 0){
                    895:                        next_buf = 0;
                    896:                }
                    897:                else {
                    898:                        next_buf = 1;
                    899:                }
                    900:                unput(us, addr, m, next_buf);
                    901:                if (us->us_oactive == 0){
                    902:                        unstart(us, addr, next_buf);
                    903:                }
                    904: #ifdef ATR
                    905:                restore_window(old_window);
                    906: #endif ATR
                    907:        }
                    908:        else {
                    909:                IF_ENQUEUE(&ifp->if_snd, m);
                    910:        }
                    911:        splx(s);
                    912:        return(0);
                    913: qfull:
                    914:        m0 = m;
                    915:        splx(s);
                    916: bad:
                    917:        m_freem(m0);
                    918:        return(error);
                    919: }
                    920: 
                    921: /*
                    922:  *  unput -  copy packet from an  mbuf chain to one of the adapter's
                    923:  *  transmit buffers.  the packet is extended to the minimum legal
                    924:  *  size if necessary.  the extra bytes could be zeroed out to improve
                    925:  *  security but are not to maximize performance.
                    926:  */
                    927: unput(us, addr, m, xbuf)
                    928:        struct un_softc *us;
                    929:        struct undevice *addr;
                    930:        register struct mbuf *m;
                    931:        register int xbuf;
                    932: {
                    933:        register unsigned off;
                    934:        register struct mbuf *mp;
                    935:        register char *bp;
                    936: 
                    937:        /*
                    938:         *  compute starting address in transmit buffer.  packets must be
                    939:         *  "end_aligned".
                    940:         */
                    941:        for (off = UN_XBSIZE, mp = m; mp; mp = mp->m_next){
                    942:                off -= mp->m_len;
                    943:        }
                    944:        if (UN_XBSIZE - off < ETHERMIN + sizeof(struct ether_header)){
                    945:                /*  packet too short => extend it */
                    946:                off = UN_XBSIZE - ETHERMIN - sizeof(struct ether_header);
                    947:        }
                    948:        if (xbuf == 1){         /* use the second buffer */
                    949:                off += UN_XBSIZE;       /* the 2 buffers are adjacent */
                    950:        }
                    951:        bp = ((char *)(addr->un_xmtbuf)) + off;
                    952:        for (mp = m; mp; mp = mp->m_next){
                    953:                register unsigned len = mp->m_len;
                    954: 
                    955:                bcopyout(mtod(mp, char *), bp, len);
                    956:                bp += len;
                    957:        }
                    958:        /* save starting address so interrupt handler can find it */
                    959:        us->us_xstart[xbuf] = off;  /* start address to be passed to adapter */
                    960:        us->us_xfull[xbuf] = 1; /* mark buffer full */
                    961:        m_freem(m);
                    962: }
                    963: 
                    964: /*
                    965:  *  unget - copy packet from adapter's receive buffers into a chain of mbufs
                    966:  *
                    967:  */
                    968: struct mbuf *
                    969: unget(addr, unbuf, totlen, off0, ifp)
                    970:        struct undevice *addr;
                    971:        char *unbuf;
                    972:        register int totlen;
                    973:        int off0;
                    974:        struct ifnet *ifp;
                    975: {
                    976:        register struct mbuf *m;
                    977:        struct mbuf *top = 0;
                    978:        register struct mbuf **mp = &top;
                    979:        register int off = off0;
                    980:        register int len;
                    981:        register char *cp;
                    982: #ifdef ISO
                    983:        int             copied_snpa = 0;
                    984: #endif ISO
                    985: 
                    986:        cp = unbuf + sizeof(struct ether_header);
                    987:        while (totlen > 0){
                    988:                char *mcp;
                    989: 
                    990:                MGET(m, M_DONTWAIT, MT_DATA);
                    991:                if (m == 0)
                    992:                        goto bad;
                    993:                if (off){       /* trailer exists */
                    994:                        len = totlen - off;
                    995:                        cp = unbuf + sizeof(struct ether_header) + off;
                    996:                } else
                    997:                        len = totlen;
                    998: #ifdef ISO
                    999:                if (!copied_snpa)
                   1000:                        len += sizeof(struct snpa_hdr);
                   1001: #else  ISO
                   1002:                if (ifp)
                   1003:                        len += sizeof(ifp);
                   1004: #endif ISO
                   1005:                if (len >= NBPG){
                   1006:                        MCLGET(m);
                   1007:                        if (m->m_len == CLBYTES)
                   1008:                                m->m_len = len = MIN(len, CLBYTES);
                   1009:                        else
                   1010:                                m->m_len = len = MIN(MLEN, len);
                   1011:                } else {
                   1012:                        m->m_len = len = MIN(MLEN, len);
                   1013:                        m->m_off = MMINOFF;
                   1014:                }
                   1015:                mcp = mtod(m, char *);
                   1016: #ifdef ISO
                   1017:                if (!copied_snpa) {
                   1018:                        /* 
                   1019:                         *      Prepend snpa_hdr to first mbuf 
                   1020:                         *      The hardcoded 12 below refers to the length of the dhost
                   1021:                         *      and shost fields. We recklessly assume 
                   1022:                         *      the order of dhost,shost in the snpa_hdr is the same
                   1023:                         *      as the order in the ether_header.
                   1024:                         */
                   1025:                        struct snpa_hdr         *sh = (struct snpa_hdr *)mcp;
                   1026:                        struct ether_header     *eh = (struct ether_header *)unbuf;
                   1027: 
                   1028:                        bcopy((char *) &ifp, (caddr_t)&sh->snh_ifp, sizeof(ifp));
                   1029:                        bcopy((caddr_t)eh, (caddr_t)sh->snh_dhost, 12);
                   1030:                        mcp += sizeof(struct snpa_hdr);
                   1031:                        len -= sizeof(struct snpa_hdr);
                   1032:                        copied_snpa = 1;
                   1033:                }
                   1034: #else  ISO
                   1035:                if (ifp){
                   1036:                        /* prepend ifp to first mbuf */
                   1037:                        /*
                   1038:                         * bcopy is used since since word moves must
                   1039:                         * be on 4 byte boundaries on the RT PC
                   1040:                         */
                   1041:                        bcopy((char *) &ifp, mcp, sizeof(ifp));
                   1042:                        mcp += sizeof(ifp);
                   1043:                        len -= sizeof(ifp);
                   1044:                        ifp = (struct ifnet *) 0;
                   1045:                }
                   1046: #endif ISO
                   1047:                unbcopy(addr, cp, mcp, len);
                   1048:                cp += len;
                   1049:                *mp = m;
                   1050:                mp = &m->m_next;
                   1051:                if (off == 0){
                   1052:                        totlen -= len;
                   1053:                        continue;
                   1054:                }
                   1055:                off += len;
                   1056:                if (off == totlen){
                   1057:                        cp = unbuf + sizeof(struct ether_header);
                   1058:                        off = 0;
                   1059:                        totlen = off0;
                   1060:                }
                   1061:        }
                   1062:        return(top);
                   1063: bad:
                   1064:        m_freem(top);
                   1065:        return(0);
                   1066: }
                   1067: 
                   1068: 
                   1069: /*
                   1070:  *  ioctl - process an ioctl request.
                   1071:  */
                   1072: unioctl(ifp, cmd, data)
                   1073:        register struct ifnet *ifp;
                   1074:        register int cmd;
                   1075:        register caddr_t data;
                   1076: {
                   1077:        register struct ifaddr *ifa = (struct ifaddr *)data;
                   1078:        register int s = splimp();
                   1079:        register int error = 0;
                   1080: 
                   1081:        switch (cmd){
                   1082:        case SIOCSIFADDR:
                   1083:                ifp->if_flags |= IFF_UP;
                   1084: 
                   1085:                switch (ifa->ifa_addr.sa_family){
                   1086: #ifdef INET
                   1087:                case AF_INET:
                   1088:                        uninit(ifp->if_unit);   /* before arpwhohas */
                   1089:                        ((struct arpcom *) ifp)->ac_ipaddr =
                   1090:                          IA_SIN(ifa)->sin_addr;
                   1091:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                   1092:                        break;
                   1093: #endif INET
                   1094: #ifdef NS
                   1095:                case AF_NS:
                   1096:                    {
                   1097:                        struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
                   1098:                        struct un_softc *us = &un_softc[ifp->if_unit];
                   1099: 
                   1100:                        if (ns_nullhost(*ina))
                   1101:                                ina->x_host = *(union ns_host *)(us->us_addr);
                   1102:                        else {
                   1103:                                ifp->if_flags &= ~IFF_RUNNING;
                   1104:                                bcopy((caddr_t) ina->x_host.c_host,
                   1105:                                  (caddr_t) us->us_addr, sizeof(us->us_addr));
                   1106:                                /*
                   1107:                                 *  the uninit will set the hardware address
                   1108:                                 *  since the IFF_RUNNING flag is off
                   1109:                                 */
                   1110:                        }
                   1111:                        uninit(ifp->if_unit);
                   1112:                        break;
                   1113:                    }
                   1114: #endif NS
                   1115:                default:
                   1116:                        uninit(ifp->if_unit);
                   1117:                        break;
                   1118:                }
                   1119:                break;
                   1120:        case SIOCSIFFLAGS:
                   1121:                if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags &
                   1122:                  IFF_RUNNING){
                   1123: #ifdef ATR
                   1124:                        int old_window;
                   1125: #endif ATR
                   1126:                        struct undevice *addr;
                   1127: 
                   1128:                        addr = (struct undevice *) uninfo[ifp->if_unit]->
                   1129:                                iod_addr;
                   1130: #ifdef ATR
                   1131:                        move_window(old_window, addr);
                   1132: #endif ATR
                   1133:                        (void) unzap((struct undevice *) addr);
                   1134:                        ifp->if_flags &= ~IFF_RUNNING;
                   1135: #ifdef ATR
                   1136:                        restore_window(old_window);
                   1137: #endif ATR
                   1138:                } else if (ifp->if_flags & IFF_UP && (ifp->if_flags &
                   1139:                  IFF_RUNNING) == 0)
                   1140:                        uninit(ifp->if_unit);
                   1141:                break;
                   1142:        default:
                   1143:                error = EINVAL;
                   1144:        }
                   1145:        splx(s);
                   1146:        return(error);
                   1147: }
                   1148: 
                   1149: /*
                   1150:  *  unzap - initialize adapter but don't enable it.
                   1151:  *  returns page number of next receive page to be used.
                   1152:  */
                   1153: unzap(addr)
                   1154:        register struct undevice *addr;
                   1155: {
                   1156:        register int next;
                   1157: 
                   1158:        MM_OUT(&addr->un_csr, 0);               /* disable interrupts */
                   1159:        MM_OUT(&addr->un_edlc.reset, RESET_ON);
                   1160:                /* set reset bit while init'ing */
                   1161:        MM_OUT(&addr->un_edlc.rstat, RS_CLEAR);
                   1162:        MM_OUT(&addr->un_edlc.xstat, XS_CLEAR);
                   1163:        MM_OUT(&addr->un_edlc.rmask, 0);
                   1164:        MM_OUT(&addr->un_edlc.xmask, 0);
                   1165:        MM_OUT(&addr->un_edlc.rmode, RM_NORMAL);
                   1166:        /*
                   1167:         *  the next line puts the transmitter in loopback mode so
                   1168:         *  that a spurious packet is not sent when the reset bit is
                   1169:         *  cleared.
                   1170:         */
                   1171:        MM_OUT(&addr->un_edlc.tmode, TM_NORMAL - TM_LBC);
                   1172:        MM_OUT(&addr->un_edlc.reset, RESET_OFF); /* clear reset bit */
                   1173:        /*
                   1174:         *  clear the receive buffers.  assign the value in the empty
                   1175:         *  page pointer to the full page pointer and clear the packet
                   1176:         *  available flag.
                   1177:         */
                   1178:        next = MM_IN(&addr->un_fppepp) & UN_PAGE_MASK;
                   1179:                /* clears the IKSYDK flag */
                   1180:        MM_OUT(&addr->un_fppepp, next);         /* fpp = epp */
                   1181:        UN_CLRPAV(addr);                /* clear the PAV flag */
                   1182:        MM_OUT(&addr->un_edlc.tmode, TM_NORMAL);
                   1183:                /* put transmitter in normal mode */
                   1184:        DEBUGF(undebug & 0x2, printf("unzap: zzzzapped!\n");)
                   1185:        return(next);
                   1186: }
                   1187: 
                   1188: /*
                   1189:  *  unupdatefpp - update adapter's full page pointer and clear packet available
                   1190:  *  flag if appropriate
                   1191:  */
                   1192: unupdatefpp(addr, nextpage)
                   1193:        register struct undevice *addr;
                   1194:        register int nextpage;
                   1195: {
                   1196:        if (nextpage == /* EPP */ (MM_IN(&addr->un_fppepp) & UN_PAGE_MASK))
                   1197:                UN_CLRPAV(addr);
                   1198:        MM_OUT(&addr->un_fppepp, nextpage);     /* set FPP */
                   1199: }
                   1200: 
                   1201: /*
                   1202:  *  unbcopy - similar to bcopy but can deal with packets that wrap
                   1203:  *  around from the high end of the adapter's receive buffer to the
                   1204:  *  low end
                   1205:  */
                   1206: unbcopy(addr, from, to, len)
                   1207:        register struct undevice *addr;
                   1208:        register char *from;
                   1209:        register char *to;
                   1210:        register int len;
                   1211: {
                   1212:        register char *high_end = &addr->un_rcvbuf[UN_LASTRBUF][UN_RBUFSIZE];
                   1213:        register int n;
                   1214: 
                   1215:        if (from + len <= high_end){
                   1216:                bcopyin(from, to, len);
                   1217:        }
                   1218:        else if (from >= high_end){
                   1219:                from -= sizeof(addr->un_rcvbuf);
                   1220:                bcopyin(from, to, len);
                   1221:        } else {
                   1222:                n = high_end - from;
                   1223:                bcopyin(from, to, n);
                   1224:                to += n;
                   1225:                bcopyin((char *)addr->un_rcvbuf, to, len - n);
                   1226:        }
                   1227: }
                   1228: 
                   1229: /*
                   1230:  *  ungetushortatoff - return the u_short at offset in the received packet,
                   1231:  *  handling wrap-around in the receive buffer and conversion between network
                   1232:  *  and host formats as necessary.
                   1233:  */
                   1234: u_short ungetushortatoff(addr, eh, off)
                   1235:        register struct undevice *addr;
                   1236:        register struct ether_header *eh;
                   1237:        register int off;
                   1238: {
                   1239:        register char *high_end = &addr->un_rcvbuf[UN_LASTRBUF][UN_RBUFSIZE];
                   1240:        register char *p;
                   1241: 
                   1242:        p = (caddr_t)(eh + 1) + off;
                   1243:        if (p >= high_end){
                   1244:                p -= sizeof(addr->un_rcvbuf);
                   1245:        }
                   1246:        return(ntohs((u_short) MM_INW(p)));
                   1247: }
                   1248: 
                   1249: /*
                   1250:  *  unprintethaddr - print an ethernet address
                   1251:  */
                   1252: unprintethaddr(p)
                   1253:        register char *p;
                   1254: {
                   1255:        register int i;
                   1256: 
                   1257:        for (i = 0; i < ETH_ADDR_SIZE; i++){
                   1258:                if (i != 0) printf(":");
                   1259:                printf("%x", *p++);
                   1260:        }
                   1261: }
                   1262: 
                   1263: #endif NUN > 0

unix.superglobalmegacorp.com

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