Annotation of cci/sys/tahoeif/if_ace.lp.c, revision 1.1

1.1     ! root        1: /*                                                             */
        !             2: /*     if_ace: ACC VERSAbus Ethernet controler (v/eiu)         */
        !             3: /*                                                             */
        !             4: 
        !             5: #include "ace.h"
        !             6: #define        ACEBPTE 64
        !             7: #if NACE > 0
        !             8: #define        ACEDEBUG
        !             9: 
        !            10: #include "../machine/pte.h"
        !            11: 
        !            12: #include "../h/param.h"
        !            13: #include "../h/systm.h"
        !            14: #include "../h/mbuf.h"
        !            15: #include "../h/buf.h"
        !            16: #include "../h/protosw.h"
        !            17: #include "../h/socket.h"
        !            18: #include "../h/vmmac.h"
        !            19: #include "../h/ioctl.h"
        !            20: #include "../h/errno.h"
        !            21: 
        !            22: #include "../net/if.h"
        !            23: #define        LONET   127
        !            24: #include "../net/netisr.h"
        !            25: #include "../net/route.h"
        !            26: #include "../netinet/in.h"
        !            27: #include "../netinet/in_systm.h"
        !            28: #include "../netinet/ip.h"
        !            29: #include "../netinet/ip_var.h"
        !            30: #include "../netinet/if_ether.h"
        !            31: #include "../netpup/pup.h"
        !            32: 
        !            33: #include "../machine/mtpr.h"
        !            34: #include "../tahoeif/if_ace.h"
        !            35: #include "../tahoeif/if_acereg.h"
        !            36: #define        LOHOST  2                       /* no conflict with loop        */
        !            37: #include "../vba/vbavar.h"
        !            38: #define        TRUE    1
        !            39: #define        FALSE   0
        !            40: 
        !            41:                                /* configuration table, for 2 units     */
        !            42:                                /*  should be defined by config         */
        !            43: #define        ACEVECTOR       0x90
        !            44: long   acestd[] = { 0x0ff0000, 0xff0100 };             /* controller   */
        !            45: extern char    ace0utl[], ace1utl[];                   /* dpm          */
        !            46: char   *acemap[]= { ace0utl, ace1utl };
        !            47: extern long    ACE0map[], ACE1map[];
        !            48: long   *ACEmap[] = {ACE0map, ACE1map };
        !            49: long   ACEmapa[] = {0xff780000,0xff790000};
        !            50: char   ace_station[6*NACE] = {                         /* addresses    */
        !            51:        ~0x8,~0x0,~0x3,~0x0,~0x0,~0x1,
        !            52: #if    (NACE > 1)
        !            53:        ~0x8,~0x0,~0x3,~0x0,~0x0,~0x2,
        !            54: #if    (NACE > 2)
        !            55:        ~0x8,~0x0,~0x3,~0x0,~0x0,~0x3,
        !            56:        ~0x8,~0x0,~0x3,~0x0,~0x0,~0x4,
        !            57: #endif (NACE > 2)
        !            58: #endif (NACE > 1)
        !            59: };
        !            60: 
        !            61: char ace_hash_code[8*NACE]={                           /* hash tables  */
        !            62:        ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 0*/
        !            63: #if    (NACE > 1)
        !            64:         ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 1*/
        !            65: #if    (NACE > 2)
        !            66:         ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 2*/
        !            67:         ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF /*u 3*/
        !            68: #endif (NACE > 2)
        !            69: #endif (NACE > 1)
        !            70: }; 
        !            71: 
        !            72: short random_mask_tbl[16] = {                          /* backoff table*/
        !            73:        0x0040, 0x00C0, 0x01C0, 0x03C0, 
        !            74:         0x07C0, 0x0FC0, 0x1FC0, 0x3FC0,
        !            75:         0x7FC0, 0xFFC0, 0xFFC0, 0xFFC0,
        !            76:         0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0  };
        !            77: 
        !            78: int    aceprobe(), aceattach(), acerint(), acecint();
        !            79: struct vba_device *aceinfo[NACE];
        !            80: struct vba_driver acedriver =
        !            81:        { aceprobe, 0,aceattach,0,acestd,"ace",aceinfo,"v/eiu",0 };
        !            82:        
        !            83: #define        ACEUNIT(x)      minor(x)
        !            84: int    aceinit(),aceoutput(),aceioctl(),acereset();
        !            85: struct mbuf *aceget();
        !            86: 
        !            87: /*
        !            88:  * Ethernet software status per interface.
        !            89:  *
        !            90:  * Each interface is referenced by a network interface structure,
        !            91:  * is_if, which the routing code uses to locate the interface.
        !            92:  * This structure contains the output queue for the interface, its address, ...
        !            93:  */
        !            94: struct ace_softc {
        !            95:        struct  arpcom is_ac;           /* Ethernet common part         */
        !            96: #define        is_if   is_ac.ac_if             /* network-visible interface    */
        !            97: #define        is_addr is_ac.ac_enaddr         /* hardware Ethernet address    */
        !            98:        char    *is_dpm;
        !            99:        short   is_flags;
        !           100: #define        ACEF_OACTIVE    0x1             /* output is active             */
        !           101: #define        ACEF_RCVPENDING 0x2             /* start rcv in acecint         */
        !           102:        short   is_promiscuous;         /* true is enabled              */
        !           103:        short   is_segboundry;          /* first TX Seg in dpm          */
        !           104:        short   is_eictr;               /* Rx segment tracking ctr      */
        !           105:        short   is_eoctr;               /* Tx segment tracking ctr      */
        !           106:        short   is_txnext;              /* Next available Tx segment    */
        !           107:        short   is_currnd;              /* current random backoff       */
        !           108:        struct  ace_stats is_stats;     /* holds board statistics       */
        !           109: } ace_softc[NACE];
        !           110: 
        !           111: aceprobe(reg)
        !           112: caddr_t reg;
        !           113: {
        !           114: register struct acedevice *addr = (struct acedevice *)reg;
        !           115: register i;
        !           116: #ifdef ACEDEBUG
        !           117: printf("aceprobe: veiu @%X\n",reg);
        !           118: #endif ACEDEBUG
        !           119: 
        !           120: #ifdef lint
        !           121:        i = 0; acerint(i); acecint(i);
        !           122: #endif
        !           123: 
        !           124:        if (badaddr(reg,2)) return(0);
        !           125:        addr->csr = CSR_RESET;
        !           126:        DELAY(10000);
        !           127:        return (1);
        !           128: 
        !           129: }
        !           130: 
        !           131: 
        !           132: /*
        !           133:  * Interface exists: make available by filling in network interface
        !           134:  * record.  System will initialize the interface when it is ready
        !           135:  * to accept packets.
        !           136:  */
        !           137: aceattach(ui)
        !           138: struct vba_device *ui;
        !           139: {
        !           140: register short unit = ui->ui_unit;
        !           141: register struct ace_softc *is = &ace_softc[unit];
        !           142: register struct ifnet *ifp = &is->is_if;
        !           143: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        !           144: register short *pData0,i;
        !           145: register char *pData1;
        !           146: struct sockaddr_in *sin;
        !           147: #ifdef ACEDEBUG
        !           148: printf("ace%dattach: ui %X\n",unit,ui);
        !           149: #endif ACEDEBUG
        !           150: 
        !           151:        ifp->if_unit = unit;
        !           152:        ifp->if_name = "ace";
        !           153:        ifp->if_mtu = ETHERMTU;
        !           154: 
        !           155:        /*
        !           156:         * Reset the board and map the statistics
        !           157:         * buffer onto the Unibus.
        !           158:         */
        !           159:        addr->csr = CSR_RESET;
        !           160:                                /* set the station address      */
        !           161:        for (pData0 = (short *)addr->rar.station_addr,
        !           162:             pData1 = &ace_station[unit * 6], i = 6;
        !           163:             --i >= 0;)
        !           164:            *(pData0++) = *(pData1++);
        !           165:                                /* Copy to arp structure        */
        !           166:        for (pData0 = (short *)addr->rar.station_addr,
        !           167:             pData1 = (char *)(is->is_addr), i = 6;
        !           168:             --i >= 0;)
        !           169:            *(pData1++) = ~(*(pData0++));
        !           170: #ifdef ACEDEBUG
        !           171: printf("ace%d: addr=%x:%x:%x:%x:%x:%x\n",
        !           172:                unit,
        !           173:                is->is_addr[0]&0xff, is->is_addr[1]&0xff,
        !           174:                is->is_addr[2]&0xff, is->is_addr[3]&0xff,
        !           175:                is->is_addr[4]&0xff, is->is_addr[5]&0xff);
        !           176: #endif ACEDEBUG
        !           177: 
        !           178:        is->is_promiscuous = (TRUE)? CSR_PROMISCUOUS: 0;
        !           179:        for (pData0 = (short *)addr->rar.mcast_hash_code, 
        !           180:             pData1 = &ace_hash_code[unit * 8], i =  8;
        !           181:             --i >= 0;)
        !           182:            *(pData0++) = *(pData1++);
        !           183: 
        !           184:        addr->rar.broadcast_en[0] = ~0xffff;
        !           185:        addr->rar.broadcast_en[1] = ~0xffff;
        !           186: 
        !           187:        is->is_dpm = acemap[unit];
        !           188:        ioaccess(ACEmap[unit],ACEmapa[unit],ACEBPTE);
        !           189:        for (pData0 = (short *)is->is_dpm, i = 16384; --i >= 0;)
        !           190:            *(pData0++) = 0;
        !           191: 
        !           192:        is->is_segboundry = 8;
        !           193:        for (pData1 = (char*)((int)is->is_dpm + (is->is_segboundry << 11)),
        !           194:             i = (SEG_MAX + 1) - is->is_segboundry;
        !           195:             (--i >= 0);
        !           196:             pData1 += sizeof (struct tx_segment))
        !           197:         {
        !           198:          ((struct tx_segment*)pData1)->tx_csr = 15;
        !           199:         }
        !           200: 
        !           201:        is->is_eictr = 0;
        !           202:        is->is_eoctr = is->is_txnext = is->is_segboundry;
        !           203:        is->is_currnd = 49123;
        !           204:        for (pData1 = (char *)&is->is_stats,i = sizeof (struct ace_stats); 
        !           205:             (--i != 0);)
        !           206:          *(pData1++) = 0;   
        !           207: 
        !           208:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           209:        sin->sin_family = AF_INET;
        !           210:        sin->sin_addr = arpmyaddr((struct arpcom *)0);
        !           211:        ifp->if_init = aceinit;
        !           212:        ifp->if_output = aceoutput;
        !           213:        ifp->if_ioctl = aceioctl;
        !           214:        ifp->if_reset = acereset;
        !           215:        if_attach(ifp);
        !           216: #ifdef ACEDEBUG
        !           217: printf("aceattach: ifattach complete\n");
        !           218: #endif ACEDEBUG
        !           219: }
        !           220: 
        !           221: /*
        !           222:  * Reset of interface after "system" reset.
        !           223:  */
        !           224: acereset(unit, vban)
        !           225: int unit, vban;
        !           226: {
        !           227: register struct vba_device *ui;
        !           228: #ifdef ACEDEBUG
        !           229: printf("ace%dreset:\n",unit,vban);
        !           230: #endif ACEDEBUG
        !           231: 
        !           232:        if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
        !           233:            ui->ui_vbanum != vban)
        !           234:                return;
        !           235:        printf(" ace%d", unit);
        !           236:        aceinit(unit);
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * Initialization of interface; clear recorded pending operations
        !           241:  */
        !           242: aceinit(unit)
        !           243: int unit;
        !           244: {
        !           245: register struct ace_softc *is = &ace_softc[unit];
        !           246: register struct vba_device *ui = aceinfo[unit];
        !           247: register struct acedevice *addr;
        !           248: register struct ifnet *ifp = &is->is_if;
        !           249: register struct sockaddr_in *sin;
        !           250: register int i,s;
        !           251: #ifdef ACEDEBUG
        !           252: printf("ace%dinit:\n",unit);
        !           253: #endif ACEDEBUG
        !           254: 
        !           255:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           256:        if (sin->sin_addr.s_addr == 0)          /* address still unknown */
        !           257:          {
        !           258: #ifdef ACEDEBUG
        !           259: printf("ace%dinit: no address assigned\n",unit);
        !           260: #endif ACEDEBUG
        !           261:                return;
        !           262:          }
        !           263: 
        !           264:        if (!(ifp->if_flags & IFF_RUNNING))
        !           265:          {
        !           266: 
        !           267:        /*
        !           268:         * Reset the controller, initialize the recieve buffers,
        !           269:         * and turn the controller on again and set board online.
        !           270:         */
        !           271:            addr = (struct acedevice *)ui->ui_addr;
        !           272:            s = splimp();
        !           273:            addr->csr = CSR_GO;
        !           274:               
        !           275:            if (addr->csr & CSR_ACTIVE)
        !           276:              {
        !           277:                addr->ivct = ACEVECTOR + (unit*8); 
        !           278:                addr->csr |= CSR_ENINT | is->is_promiscuous;
        !           279:                if (ifp->if_net == LONET)
        !           280:                  addr->csr |= (CSR_LOOP3);
        !           281:                is->is_flags = ACEF_OACTIVE;
        !           282:                is->is_if.if_flags |= IFF_UP|IFF_RUNNING;
        !           283: #ifdef ACEDEBUG
        !           284:                printf("aceinit: csr %x, segb %x, tseg %x, rseg %x\n",
        !           285:                             (addr->csr & 0xffff),
        !           286:                             ((addr->segb >> 11) & 0xf),
        !           287:                             ((addr->tseg >> 11) & 0xf),
        !           288:                             ((addr->rseg >> 11) & 0xf));
        !           289: #endif ACEDEBUG
        !           290:                acecint(unit);
        !           291:              }
        !           292: #ifdef ACEDEBUG
        !           293:            else
        !           294:              {
        !           295:                printf("ace%dinit: would not go active\n",unit);
        !           296:              }
        !           297: #endif ACEDEBUG
        !           298:            splx(s);
        !           299:          }
        !           300:        if_rtinit(&is->is_if, RTF_UP);
        !           301:        arpattach(&is->is_ac);
        !           302:        arpwhohas(&is->is_ac, &sin->sin_addr);
        !           303: }
        !           304: 
        !           305: /*
        !           306:  * Start output on interface.
        !           307:  * Get another datagram to send off of the interface queue,
        !           308:  * and map it to the interface before starting the output.
        !           309:  */
        !           310: acestart(dev)
        !           311: dev_t dev;
        !           312: {
        !           313: int unit = ACEUNIT(dev), len;
        !           314: struct vba_device *ui = aceinfo[unit];
        !           315: register struct ace_softc *is = &ace_softc[unit];
        !           316: register struct tx_segment *txs;
        !           317: struct mbuf *m;
        !           318: short retries,idx;
        !           319: #ifdef ACEDEBUG
        !           320: printf("ace%dstart: dev %X, tx seg %x\n",unit,dev,is->is_txnext);
        !           321: #endif ACEDEBUG
        !           322: 
        !           323:        txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
        !           324:        if (txs->tx_csr & TCS_TBFULL) return;
        !           325:        IF_DEQUEUE(&is->is_if.if_snd, m);
        !           326:        if (m == 0)
        !           327:          {
        !           328:            if (TRUE) return;
        !           329:          }
        !           330:        len = aceput(txs->tx_data, m);
        !           331: #ifdef ACEDEBUG
        !           332:        printf("sending[");
        !           333:        for (idx = 0;(idx < len);idx++)
        !           334:          {
        !           335:            printf("%x ",txs->tx_data[idx] & 0xff);
        !           336:          }
        !           337:        printf("]\n");
        !           338: #endif ACEDEBUG
        !           339:        retries = (txs->tx_csr & TCS_RTC);
        !           340:        acebakoff(is,txs,retries);
        !           341:        /*
        !           342:         * Ensure minimum packet length.
        !           343:         * This makes the safe assumtion that there are no virtual holes
        !           344:         * after the data.
        !           345:         * For security, it might be wise to zero out the added bytes,
        !           346:         * but we're mainly interested in speed at the moment.
        !           347:         */
        !           348:        if (len - sizeof(struct ether_header) < ETHERMIN)
        !           349:                len = ETHERMIN + sizeof(struct ether_header);
        !           350:        if ((is->is_txnext += 1) > SEG_MAX)
        !           351:          is->is_txnext = is->is_segboundry;
        !           352:        txs->tx_csr = (TCS_TBFULL|len);
        !           353:        is->is_if.if_opackets++;
        !           354: #ifdef ACEDEBUG
        !           355:        printf("sending %x bytes,retries fixed %x\n",
        !           356:                        (txs->tx_csr & 0xffff),retries);
        !           357: #endif ACEDEBUG
        !           358:        is->is_flags |= ACEF_OACTIVE;
        !           359: }
        !           360: 
        !           361: /*
        !           362:  * Command done interrupt.
        !           363:  */
        !           364: acecint(unit)
        !           365: int unit;
        !           366: {
        !           367: register struct ace_softc *is = &ace_softc[unit];
        !           368: struct vba_device *ui = aceinfo[unit];
        !           369: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        !           370: register struct tx_segment *txseg;     /* ptr to V/EIU tx seg            */
        !           371: short eostat;
        !           372: #ifdef ACEDEBUG
        !           373: printf("ace%dcint: \n",unit);
        !           374: #endif ACEDEBUG
        !           375: 
        !           376:        if ((is->is_flags & ACEF_OACTIVE) == 0)
        !           377:          {
        !           378:            printf("ace%dcint: stray xmit interrupt\n", unit);
        !           379:                return;
        !           380:          }
        !           381: 
        !           382:        is->is_flags &= ~ACEF_OACTIVE;
        !           383:        txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
        !           384:        if (((eostat = txseg->tx_csr) & TCS_TBFULL) == 0)
        !           385:          {
        !           386:            is->is_stats.tx_retries += (eostat & TCS_RTC);
        !           387:            if (eostat & TCS_RTFAIL)
        !           388:              {
        !           389:                is->is_stats.tx_discarded++;
        !           390:                is->is_if.if_oerrors++;
        !           391:              }
        !           392:            else
        !           393:              is->is_stats.tx_datagrams++;
        !           394:            if (++is->is_eoctr >= 16)
        !           395:              is->is_eoctr = is->is_segboundry; 
        !           396:          } 
        !           397: #ifdef ACEDEBUG
        !           398:        else
        !           399:          {
        !           400: printf("ace%dcint: tx segment %X busy\n",unit,is->is_eoctr);
        !           401:          }
        !           402: #endif ACEDEBUG
        !           403:        acestart(unit);
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Ethernet interface receiver interrupt.
        !           408:  * If input error just drop packet.
        !           409:  * Otherwise purge input buffered data path and examine 
        !           410:  * packet to determine type.  If can't determine length
        !           411:  * from type, then have to drop packet.  Othewise decapsulate
        !           412:  * packet based on type and pass to type specific higher-level
        !           413:  * input routine.
        !           414:  */
        !           415: acerint(unit)
        !           416: int unit;
        !           417: {
        !           418: register struct ace_softc *is = &ace_softc[unit];
        !           419: struct acedevice *addr = (struct acedevice *)aceinfo[unit]->ui_addr;
        !           420: register struct ifqueue *inq;
        !           421: register struct ace_rheader *ace;
        !           422: register struct rx_segment *rxseg;     /* ptr to V/EIU rx seg            */
        !           423: short eistat;
        !           424: struct mbuf *m;
        !           425: int len, off, resid;
        !           426: #ifdef ACEDEBUG
        !           427: printf("ace%xrint: rxseg %x\n",unit,is->is_eictr);
        !           428: #endif ACEDEBUG
        !           429: 
        !           430:        is->is_if.if_ipackets++;
        !           431:        rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
        !           432:        if (++is->is_eictr >= is->is_segboundry) 
        !           433:          is->is_eictr = 0;
        !           434: #ifdef ACEDEBUG
        !           435:        printf("[(%x)",(rxseg->rx_csr & 0xffff));
        !           436:        for (off = 0;(off < 64);off++)
        !           437:          {
        !           438:            printf("%x ",rxseg->rx_data[off] & 0xff);
        !           439:          }
        !           440:        printf("]\n");
        !           441: #endif ACEDEBUG
        !           442:        if ((eistat = rxseg->rx_csr) & RCS_RBFULL)
        !           443:          {
        !           444:            len = (eistat & RCS_RBC);
        !           445:            if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
        !           446:                (len < ET_MINLEN) || (len > (ET_MAXLEN+CRC_SIZE)))
        !           447:              {
        !           448:                if (eistat & RCS_ROVRN) is->is_stats.rx_overruns++;
        !           449:                if (eistat & RCS_RCRC) is->is_stats.rx_crc_errors++;
        !           450:                if (eistat & RCS_RODD) is->is_stats.rx_align_errors++;
        !           451:                if (len < ET_MINLEN) is->is_stats.rx_underruns++;
        !           452:                if (len > (ET_MAXLEN+CRC_SIZE)) is->is_stats.rx_overruns++;
        !           453:                is->is_if.if_ierrors++;
        !           454: #ifdef ACEDEBUG
        !           455:                if (is->is_if.if_ierrors % 100 == 0)
        !           456:                        printf("ace%d: += 100 input errors\n", unit);
        !           457: #endif
        !           458:                rxseg->rx_csr = 0;
        !           459:                return;
        !           460:              }
        !           461:            else
        !           462:              {
        !           463:                is->is_stats.rx_datagrams++;
        !           464:              }
        !           465:          }
        !           466: #ifdef ACEDEBUG
        !           467:        else
        !           468:          {
        !           469:            printf("ace%d: stray recv interrupt\n", unit);
        !           470:            return;
        !           471:          }
        !           472: #endif ACEDEBUG
        !           473:        ace = (struct ace_rheader *)(rxseg->rx_data);
        !           474:        len = ace->acer_length - sizeof(struct ace_rheader);
        !           475: 
        !           476:        /*
        !           477:         * Deal with trailer protocol: if type is PUP trailer
        !           478:         * get true type from first 16-bit word past data.
        !           479:         * Remember that type was trailer by setting off.
        !           480:         */
        !           481:        ace->acer_type = ntohs((u_short)ace->acer_type);
        !           482: #define        acedataaddr(ace, off, type)     ((type)(((caddr_t)((ace)+1)+(off))))
        !           483:        if (ace->acer_type >= ETHERPUP_TRAIL &&
        !           484:            ace->acer_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
        !           485:                off = (ace->acer_type - ETHERPUP_TRAIL) * 512;
        !           486:                if (off >= ETHERMTU)
        !           487:                        goto setup;             /* sanity */
        !           488:                ace->acer_type = ntohs(*acedataaddr(ace, off, u_short *));
        !           489:                resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
        !           490:                if (off + resid > len)
        !           491:                        goto setup;             /* sanity */
        !           492:                len = off + resid;
        !           493:        } else
        !           494:                off = 0;
        !           495:        if (len == 0)
        !           496:                goto setup;
        !           497: 
        !           498:        /*
        !           499:         * Pull packet off interface.  Off is nonzero if packet
        !           500:         * has trailing header; aceget will then force this header
        !           501:         * information to be at the front, but we still have to drop
        !           502:         * the type and length which are at the front of any trailer data.
        !           503:         */
        !           504:        m = aceget(rxseg->rx_data, len, off);
        !           505:        if (m == 0)
        !           506:                goto setup;
        !           507:        if (off) {
        !           508:                m->m_off += 2 * sizeof (u_short);
        !           509:                m->m_len -= 2 * sizeof (u_short);
        !           510:        }
        !           511:        switch (ace->acer_type) {
        !           512: 
        !           513: #ifdef INET
        !           514:        case ETHERPUP_IPTYPE:
        !           515:                schednetisr(NETISR_IP);
        !           516:                inq = &ipintrq;
        !           517:                break;
        !           518: 
        !           519:        case ETHERPUP_ARPTYPE:
        !           520:                arpinput(&is->is_ac, m);
        !           521:                goto setup;
        !           522: #endif
        !           523:        default:
        !           524:                m_freem(m);
        !           525:                goto setup;
        !           526:        }
        !           527: 
        !           528:        if (IF_QFULL(inq)) {
        !           529:                IF_DROP(inq);
        !           530:                m_freem(m);
        !           531:                goto setup;
        !           532:        }
        !           533:        IF_ENQUEUE(inq, m);
        !           534: 
        !           535: setup:
        !           536:        rxseg->rx_csr = 0;
        !           537: }
        !           538: 
        !           539: /*
        !           540:  * Ethernet output routine.
        !           541:  * Encapsulate a packet of type family for the local net.
        !           542:  * Use trailer local net encapsulation if enough data in first
        !           543:  * packet leaves a multiple of 512 bytes of data in remainder.
        !           544:  */
        !           545: aceoutput(ifp, m0, dst)
        !           546: struct ifnet *ifp;
        !           547: struct mbuf *m0;
        !           548: struct sockaddr *dst;
        !           549: {
        !           550: register short unit = ifp->if_unit;
        !           551: register struct ace_softc *is = &ace_softc[unit];
        !           552: register struct mbuf *m = m0;
        !           553: register struct ether_header *ace;
        !           554: register int off;
        !           555: int type, s, error;
        !           556: u_char edst[6];
        !           557: struct in_addr idst;
        !           558: #ifdef ACEDEBUG
        !           559: printf("ace%doutput: ifp %X, m0 %X, dst %X\n",unit,ifp,m0,dst);
        !           560: #endif ACEDEBUG
        !           561: 
        !           562:        switch (dst->sa_family) {
        !           563: 
        !           564: #ifdef INET
        !           565:        case AF_INET:
        !           566:                idst = ((struct sockaddr_in *)dst)->sin_addr;
        !           567:                if (!arpresolve(&is->is_ac, m, &idst, edst))
        !           568:                        return (0);     /* if not yet resolved */
        !           569:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
        !           570:                /* need per host negotiation */
        !           571:                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
        !           572:                  if (off > 0 && (off & 0x1ff) == 0 &&
        !           573:                      m->m_off >= MMINOFF + 2 * sizeof (u_short))
        !           574:                    {
        !           575:                        type = ETHERPUP_TRAIL + (off>>9);
        !           576:                        m->m_off -= 2 * sizeof (u_short);
        !           577:                        m->m_len += 2 * sizeof (u_short);
        !           578:                        *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
        !           579:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
        !           580:                        goto gottrailertype;
        !           581:                    }
        !           582:                type = ETHERPUP_IPTYPE;
        !           583:                off = 0;
        !           584:                goto gottype;
        !           585: #endif
        !           586: 
        !           587:        case AF_UNSPEC:
        !           588:                ace = (struct ether_header *)dst->sa_data;
        !           589:                bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
        !           590:                type = ace->ether_type;
        !           591:                goto gottype;
        !           592: 
        !           593:        default:
        !           594:                printf("ace%d: can't handle af%d\n", unit,dst->sa_family);
        !           595:                error = EAFNOSUPPORT;
        !           596:                goto bad;
        !           597:        }
        !           598: 
        !           599: gottrailertype:
        !           600:        /*
        !           601:         * Packet to be sent as trailer: move first packet
        !           602:         * (control information) to end of chain.
        !           603:         */
        !           604:        while (m->m_next)
        !           605:                m = m->m_next;
        !           606:        m->m_next = m0;
        !           607:        m = m0->m_next;
        !           608:        m0->m_next = 0;
        !           609:        m0 = m;
        !           610: 
        !           611: gottype:
        !           612:        /*
        !           613:         * Add local net header.  If no space in first mbuf,
        !           614:         * allocate another.
        !           615:         */
        !           616:        if (m->m_off > MMAXOFF ||
        !           617:            MMINOFF + sizeof (struct ether_header) > m->m_off) {
        !           618:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           619:                if (m == 0) {
        !           620:                        error = ENOBUFS;
        !           621:                        goto bad;
        !           622:                }
        !           623:                m->m_next = m0;
        !           624:                m->m_off = MMINOFF;
        !           625:                m->m_len = sizeof (struct ether_header);
        !           626:        } else {
        !           627:                m->m_off -= sizeof (struct ether_header);
        !           628:                m->m_len += sizeof (struct ether_header);
        !           629:        }
        !           630:        ace = mtod(m, struct ether_header *);
        !           631:        ace->ether_type = htons((u_short)type);
        !           632:        bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
        !           633:        bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 6);
        !           634: 
        !           635:        /*
        !           636:         * Queue message on interface, and start output if interface
        !           637:         * not yet active.
        !           638:         */
        !           639:        s = splimp();
        !           640:        if (IF_QFULL(&ifp->if_snd)) {
        !           641:                IF_DROP(&ifp->if_snd);
        !           642:                splx(s);
        !           643:                m_freem(m);
        !           644:                return (ENOBUFS);
        !           645:        }
        !           646:        IF_ENQUEUE(&ifp->if_snd, m);
        !           647:        acestart(unit);
        !           648:        splx(s);
        !           649:        return (0);
        !           650: 
        !           651: bad:
        !           652:        m_freem(m0);
        !           653:        return (error);
        !           654: }
        !           655: 
        !           656: /*
        !           657:  * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
        !           658:  * If packet size is less than the minimum legal size,
        !           659:  * the buffer is expanded.  We probably should zero out the extra
        !           660:  * bytes for security, but that would slow things down.
        !           661:  */
        !           662: aceput(txbuf, m)
        !           663: u_char *txbuf;
        !           664: struct mbuf *m;
        !           665: {
        !           666: register struct mbuf *mp;
        !           667: register int off,total;
        !           668: u_char *bp;
        !           669: #ifdef ACEDEBUG
        !           670: printf("aceput: txbuf %X, mbuf %X\n",txbuf,mp);
        !           671: #endif ACEDEBUG
        !           672: 
        !           673:        total = 0;
        !           674:                                /* Leave room for the destination       */
        !           675:        off = 0;
        !           676:        bp = (u_char *)(txbuf + off);
        !           677:        for (mp = m;(mp); mp = mp->m_next)
        !           678:          {
        !           679:          register unsigned len = mp->m_len;
        !           680:          u_char *mcp;
        !           681: 
        !           682:                if (len == 0)
        !           683:                        continue;
        !           684:                total += len;
        !           685:                mcp = mtod(mp, u_char *);
        !           686:                if ((unsigned)bp & 01) {
        !           687:                        *bp++ = *mcp++;
        !           688:                        len--;
        !           689:                }
        !           690:                if (off = (len >> 1)) {
        !           691:                        register u_short *to, *from;
        !           692: 
        !           693:                        to = (u_short *)bp;
        !           694:                        from = (u_short *)mcp;
        !           695:                        do
        !           696:                                *to++ = *from++;
        !           697:                        while (--off > 0);
        !           698:                        bp = (u_char *)to,
        !           699:                        mcp = (u_char *)from;
        !           700:                }
        !           701:                if (len & 01)
        !           702:                        *bp++ = *mcp++;
        !           703:          }
        !           704:        m_freem(m);
        !           705:        return(total);
        !           706: }
        !           707: 
        !           708: /*
        !           709:  * Routine to copy from VERSAbus memory into mbufs.
        !           710:  *
        !           711:  * Warning: This makes the fairly safe assumption that
        !           712:  * mbufs have even lengths.
        !           713:  */
        !           714: struct mbuf *
        !           715: aceget(rxbuf, totlen, off0)
        !           716: u_char *rxbuf;
        !           717: int totlen, off0;
        !           718: {
        !           719: register struct mbuf *m;
        !           720: struct mbuf *top = 0, **mp = &top;
        !           721: register int off = off0, len;
        !           722: u_char *cp;
        !           723: #ifdef ACEDEBUG
        !           724: printf("aceget: rxbuf %X\n",rxbuf);
        !           725: #endif ACEDEBUG
        !           726: 
        !           727:        cp = rxbuf + sizeof (struct ether_header);
        !           728:        while (totlen > 0)
        !           729:          {
        !           730:          register int words;
        !           731:          u_char *mcp;
        !           732: 
        !           733:                MGET(m, M_DONTWAIT, MT_DATA);
        !           734:                if (m == 0)
        !           735:                        goto bad;
        !           736:                if (off) {
        !           737:                        len = totlen - off;
        !           738:                        cp = rxbuf +
        !           739:                                sizeof (struct ether_header) + off;
        !           740:                } else
        !           741:                        len = totlen;
        !           742:                if (len >= CLBYTES) {
        !           743:                        struct mbuf *p;
        !           744: 
        !           745:                        MCLGET(p, 1);
        !           746:                        if (p != 0) {
        !           747:                                m->m_len = len = CLBYTES;
        !           748:                                m->m_off = (int)p - (int)m;
        !           749:                        } else {
        !           750:                                m->m_len = len = MIN(MLEN, len);
        !           751:                                m->m_off = MMINOFF;
        !           752:                        }
        !           753:                } else {
        !           754:                        m->m_len = len = MIN(MLEN, len);
        !           755:                        m->m_off = MMINOFF;
        !           756:                }
        !           757:                mcp = mtod(m, u_char *);
        !           758:                if (words = (len >> 1)) {
        !           759:                        register u_short *to, *from;
        !           760: 
        !           761:                        to = (u_short *)mcp;
        !           762:                        from = (u_short *)cp;
        !           763:                        do
        !           764:                                *to++ = *from++;
        !           765:                        while (--words > 0);
        !           766:                        mcp = (u_char *)to;
        !           767:                        cp = (u_char *)from;
        !           768:                }
        !           769:                if (len & 01)
        !           770:                        *mcp++ = *cp++;
        !           771:                *mp = m;
        !           772:                mp = &m->m_next;
        !           773:                if (off == 0) {
        !           774:                        totlen -= len;
        !           775:                        continue;
        !           776:                }
        !           777:                off += len;
        !           778:                if (off == totlen) {
        !           779:                        cp = rxbuf + sizeof (struct ether_header);
        !           780:                        off = 0;
        !           781:                        totlen = off0;
        !           782:                }
        !           783:          }
        !           784:        return (top);
        !           785: bad:
        !           786:        m_freem(top);
        !           787:        return (0);
        !           788: }
        !           789: 
        !           790: /*+procedure                                                   */
        !           791: /*                                                             */
        !           792: 
        !           793: acebakoff(is, txseg, retries)
        !           794: struct ace_softc *is;          /* ptr to UCB for this device     */
        !           795: struct tx_segment *txseg;      /* ptr to V/EIU tx seg            */
        !           796: register int retries;          /* # of randoms to generate       */
        !           797: {
        !           798: short *pMask;                  /* ptr to mask table.        */
        !           799: register short *pBakNum;       /* ptr to # entry in Tx seg table */
        !           800: register short random_num;     /* random number value.      */
        !           801: 
        !           802: 
        !           803:        pMask   = &random_mask_tbl[0];
        !           804:        pBakNum = &txseg->tx_backoff[0];
        !           805: 
        !           806:        for (; --retries >= 0;)
        !           807:          {
        !           808:            random_num   = (is->is_currnd = (is->is_currnd * 18741)-13849);
        !           809:            random_num  &= *(pMask++);
        !           810:            *(pBakNum++) = random_num ^ (short)(0xFF00 | 0x00FC);
        !           811:          }
        !           812: }
        !           813: 
        !           814: /*
        !           815:  * Process an ioctl request.
        !           816:  */
        !           817: aceioctl(ifp, cmd, data)
        !           818: register struct ifnet *ifp;
        !           819: int cmd;
        !           820: caddr_t data;
        !           821: {
        !           822: register struct ifreq *ifr = (struct ifreq *)data;
        !           823: int s = splimp(), error = 0;
        !           824: #ifdef ACEDEBUG
        !           825: printf("aceioctl: ifp %X, cmd %X, data %X\n",ifp,cmd,data);
        !           826: #endif ACEDEBUG
        !           827: 
        !           828:        switch (cmd) {
        !           829: 
        !           830:        case SIOCSIFADDR:
        !           831:                if (ifp->if_flags & IFF_RUNNING)
        !           832:                        if_rtinit(ifp, -1);     /* delete previous route */
        !           833:                acesetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
        !           834:                aceinit(ifp->if_unit);
        !           835:                break;
        !           836: 
        !           837:        default:
        !           838:                error = EINVAL;
        !           839:        }
        !           840:        splx(s);
        !           841:        return (error);
        !           842: }
        !           843: 
        !           844: acesetaddr(ifp, sin)
        !           845: register struct ifnet *ifp;
        !           846: register struct sockaddr_in *sin;
        !           847: {
        !           848: #ifdef ACEDEBUG
        !           849: printf("acesetaddr: ifp %X, sin %X\n",ifp,sin);
        !           850: #endif ACEDEBUG
        !           851: 
        !           852:        ifp->if_addr = *(struct sockaddr *)sin;
        !           853:        ifp->if_net = in_netof(sin->sin_addr);
        !           854:        ifp->if_host[0] = in_lnaof(sin->sin_addr);
        !           855:        sin = (struct sockaddr_in *)&ifp->if_broadaddr;
        !           856:        sin->sin_family = AF_INET;
        !           857:        sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
        !           858:        ifp->if_flags |= IFF_BROADCAST;
        !           859: }
        !           860: #endif NACE > 0

unix.superglobalmegacorp.com

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