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

1.1     ! root        1: /*                                                             */
        !             2: /*     if_ace: ACC VERSAbus Ethernet controler (v/eiu)         */
        !             3: /*                                                             */
        !             4: #include "ace.h"
        !             5: #if NACE > 0
        !             6: 
        !             7: #include "../machine/pte.h"
        !             8: 
        !             9: #include "../h/param.h"
        !            10: #include "../h/systm.h"
        !            11: #include "../h/mbuf.h"
        !            12: #include "../h/buf.h"
        !            13: #include "../h/protosw.h"
        !            14: #include "../h/socket.h"
        !            15: #include "../h/vmmac.h"
        !            16: #include "../h/ioctl.h"
        !            17: #include "../h/errno.h"
        !            18: #include "../h/vmparam.h"
        !            19: 
        !            20: #include "../net/if.h"
        !            21: #include "../net/netisr.h"
        !            22: #include "../net/route.h"
        !            23: #include "../netinet/in.h"
        !            24: #include "../netinet/in_systm.h"
        !            25: #include "../netinet/ip.h"
        !            26: #include "../netinet/ip_var.h"
        !            27: #include "../netinet/if_ether.h"
        !            28: #include "../netpup/pup.h"
        !            29: 
        !            30: #include "../machine/mtpr.h"
        !            31: #include "../tahoeif/if_acereg.h"
        !            32: #include "../vba/vbavar.h"
        !            33: 
        !            34: #define        LONET   124
        !            35: #define        LOHOST  1
        !            36: #define        TRUE    1
        !            37: #define        FALSE   0
        !            38: 
        !            39:                                /* configuration table, for 2 units     */
        !            40:                                /*  should be defined by config         */
        !            41: #define        ACEVECTOR       0x90
        !            42: long   acestd[] = { 0x0ff0000, 0xff0100 };             /* controller   */
        !            43: 
        !            44: extern char    ace0utl[], ace1utl[];                   /* dpm          */
        !            45: char   *acemap[]= { ace0utl, ace1utl };
        !            46: extern long    ACE0map[], ACE1map[];
        !            47: long   *ACEmap[] = {ACE0map, ACE1map };
        !            48: long   ACEmapa[] = {0xfff80000,0xfff90000};
        !            49: 
        !            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: 
        !            85: int    aceinit(),aceoutput(),aceioctl(),acereset();
        !            86: struct mbuf *aceget();
        !            87: 
        !            88: struct ace_softc ace_softc[NACE];
        !            89: extern struct  ifnet   loif;
        !            90: 
        !            91: int    numace  = NACE;                         /* for nstat unix command */
        !            92: 
        !            93: /*------ debugging tools ------------*/
        !            94: #ifdef ACEPRINTFS
        !            95: int    aceprintfs;
        !            96: #define INTTRACE               1
        !            97: #define RTINTRACE              2
        !            98: #define STARTTRACE             4
        !            99: #define ACEOTRACE              8
        !           100: #define RTINTRACE1             0x10
        !           101: #define IOCTLTRACE             0x20
        !           102: #define ATRACE                 0x40
        !           103: #define SETETTRACE             0x80
        !           104: #define        ALLTRACE                (INTTRACE | RTINTRACE | STARTTRACE | ACEOTRACE\
        !           105:                        | RTINTRACE1 | IOCTLTRACE | ATRACE | SETETTRACE)
        !           106: 
        !           107: #define ACETRACE(X,Y)  {if (aceprintfs & X) Y}
        !           108: #else ACEPRINTFS
        !           109: #define ACETRACE(X,Y)
        !           110: #endif ACEPRINTFS
        !           111: 
        !           112: /*------ performance study tools ---------------*/
        !           113: #ifdef NET_PERF
        !           114: #define        ACESTUDY(X)     {X}
        !           115: #else  NET_PERF
        !           116: #define ACESTUDY(X)
        !           117: #endif
        !           118: 
        !           119: aceprobe(reg)
        !           120: caddr_t reg;
        !           121: {
        !           122: register struct acedevice *addr = (struct acedevice *)reg;
        !           123: register i;
        !           124: 
        !           125:        ACETRACE(ALLTRACE, printf("aceprobe: veiu @%X\n",reg);)
        !           126: 
        !           127: 
        !           128: #ifdef lint
        !           129:        i = 0; acerint(i); acecint(i);
        !           130: #endif
        !           131: 
        !           132:        if (badaddr(reg,2)) return(0);
        !           133:        movew((short)CSR_RESET,&addr->csr);
        !           134:        DELAY(10000);
        !           135:        return (1);
        !           136: 
        !           137: }
        !           138: 
        !           139: 
        !           140: /*
        !           141:  * Interface exists: make available by filling in network interface
        !           142:  * record.  System will initialize the interface when it is ready
        !           143:  * to accept packets.
        !           144:  */
        !           145: aceattach(ui)
        !           146: struct vba_device *ui;
        !           147: {
        !           148: register short unit = ui->ui_unit;
        !           149: register struct ace_softc *is = &ace_softc[unit];
        !           150: register struct ifnet *ifp = &is->is_if;
        !           151: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        !           152: register short *pData0,i, data;
        !           153: register char *pData1;
        !           154: register short Csr;
        !           155: struct sockaddr_in *sin;
        !           156: 
        !           157:        ACETRACE( ALLTRACE, printf("ace%dattach: ui %X\n",unit,ui);)
        !           158: 
        !           159:        ifp->if_unit = unit;
        !           160:        ifp->if_name = "ace";
        !           161:        ifp->if_mtu = ETHERMTU;
        !           162: 
        !           163:        /*
        !           164:         * Set vector,station's addresses,cleanup dpm.
        !           165:         */
        !           166:                /* set the station address, copy to arp structure */
        !           167:        acesetetaddr(unit,addr, &ace_station[unit * 6]);
        !           168:        /*
        !           169:        for (pData0 = (short *)addr->rar.station_addr,
        !           170:             pData1 = &ace_station[unit * 6], i = 6;
        !           171:             --i >= 0;) {
        !           172:            movew((short)(*pData1++),(pData0++)); 
        !           173:            }
        !           174:        for (pData0 = (short *)addr->rar.station_addr,
        !           175:             pData1 = (char *)(is->is_addr), i = 6;
        !           176:             --i >= 0;)
        !           177:            *(pData1++) = ~(*(pData0++));
        !           178: 
        !           179:        ACETRACE(ALLTRACE,
        !           180:                printf("ace%d: addr=%x:%x:%x:%x:%x:%x\n",
        !           181:                        unit,
        !           182:                        is->is_addr[0]&0xff, is->is_addr[1]&0xff,
        !           183:                        is->is_addr[2]&0xff, is->is_addr[3]&0xff,
        !           184:                        is->is_addr[4]&0xff, is->is_addr[5]&0xff);)
        !           185:        */
        !           186: 
        !           187:        is->is_promiscuous = (FALSE)? CSR_PROMISCUOUS: 0;
        !           188:        for (pData0 = (short *)addr->rar.mcast_hash_code, 
        !           189:             pData1 = &ace_hash_code[unit * 8], i =  8;
        !           190:             --i >= 0;){
        !           191:            movew((short)(*pData1++),(pData0++)); 
        !           192:        }
        !           193: 
        !           194:        movew((short)~0xffff,&addr->rar.broadcast_en[0]); 
        !           195:        movew((short)~0xffff,&addr->rar.broadcast_en[1]);
        !           196: 
        !           197:        aceclean((int)unit);
        !           198: 
        !           199:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           200:        sin->sin_family = AF_INET;
        !           201:        sin->sin_addr = arpmyaddr((struct arpcom *)0);
        !           202:        ifp->if_init = aceinit;
        !           203:        ifp->if_output = aceoutput;
        !           204:        ifp->if_ioctl = aceioctl;
        !           205:        ifp->if_reset = acereset;
        !           206:        if_attach(ifp);
        !           207: }
        !           208: 
        !           209: acesetetaddr(unit,addr,station_addr)
        !           210: short unit;
        !           211: struct acedevice *addr;
        !           212: char *station_addr;
        !           213: {
        !           214: register short *pData0, i;
        !           215: register char *pData1;
        !           216: register struct ace_softc *is = &ace_softc[unit];
        !           217: 
        !           218:        for (pData0 = (short *)addr->rar.station_addr,
        !           219:                pData1 = station_addr, i = 6; --i >= 0;) {
        !           220:            movew((short)(*pData1++),(pData0++)); 
        !           221:            }
        !           222:        for (pData0 = (short *)addr->rar.station_addr,
        !           223:                pData1 = (char *)(is->is_addr), i = 6; --i >= 0;)
        !           224:            *(pData1++) = ~(*(pData0++));
        !           225: 
        !           226:        ACETRACE(SETETTRACE,
        !           227:                printf("ace%d: addr=%x:%x:%x:%x:%x:%x\n",
        !           228:                        unit,
        !           229:                        is->is_addr[0]&0xff, is->is_addr[1]&0xff,
        !           230:                        is->is_addr[2]&0xff, is->is_addr[3]&0xff,
        !           231:                        is->is_addr[4]&0xff, is->is_addr[5]&0xff);)
        !           232: }
        !           233: 
        !           234: 
        !           235: /*
        !           236:  * Reset of interface after "system" reset.
        !           237:  */
        !           238: acereset(unit, vban)
        !           239: int unit, vban;
        !           240: {
        !           241: register struct vba_device *ui;
        !           242: 
        !           243:        ACETRACE(ALLTRACE, printf("ace%dreset:\n",unit,vban);)
        !           244: 
        !           245:        if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
        !           246:            ui->ui_vbanum != vban)
        !           247:                return;
        !           248:        printf(" ace%d", unit);
        !           249:        aceinit(unit);
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * Initialization of interface; clear recorded pending operations
        !           254:  */
        !           255: aceinit(unit)
        !           256: int unit;
        !           257: {
        !           258: register struct ace_softc *is = &ace_softc[unit];
        !           259: register struct vba_device *ui = aceinfo[unit];
        !           260: register struct acedevice *addr;
        !           261: register struct ifnet *ifp = &is->is_if;
        !           262: register struct sockaddr_in *sin;
        !           263: register short Csr;
        !           264: register int i,s;
        !           265: 
        !           266:        ACETRACE(ALLTRACE, printf("ace%dinit:\n",unit);)
        !           267: 
        !           268:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           269:        if (sin->sin_addr.s_addr == 0)          /* address still unknown */
        !           270:                return;
        !           271:        if (!(ifp->if_flags & IFF_RUNNING))
        !           272:          {
        !           273: 
        !           274:        /*
        !           275:         * Reset the controller, initialize the recieve buffers,
        !           276:         * and turn the controller on again and set board online.
        !           277:         */
        !           278:            addr = (struct acedevice *)ui->ui_addr;
        !           279:            s = splimp();
        !           280:            movew((short)CSR_RESET,&addr->csr);
        !           281:            DELAY(10000);
        !           282: 
        !           283:            /* clean up dpm since the controller might jumble dpm after
        !           284:               reset */
        !           285:            aceclean((int)unit);
        !           286:            movew((short)CSR_GO,&addr->csr);    /* addr->csr = CSR_GO; */
        !           287:            Csr = addr->csr;
        !           288:            if (Csr & CSR_ACTIVE)
        !           289:              {
        !           290:                movew((short)(ACEVECTOR + (unit*8)),&addr->ivct);
        !           291:                Csr |= CSR_ENINT | is->is_promiscuous;
        !           292:                if (ifp->if_net == LONET)
        !           293:                        Csr |= (CSR_LOOP3);
        !           294:                movew(Csr,&addr->csr);
        !           295: 
        !           296:                is->is_flags = 0;
        !           297:                is->is_xcnt = 0;
        !           298:                is->is_if.if_flags |= IFF_UP|IFF_RUNNING;
        !           299:              }
        !           300:            else
        !           301:              {
        !           302:                ACETRACE(ALLTRACE,
        !           303:                        printf("ace%dinit: would not go active\n",unit);)
        !           304:              }
        !           305:            splx(s);
        !           306:          }
        !           307: 
        !           308:        if (is->is_if.if_flags & IFF_UP) {
        !           309:                if_rtinit(&is->is_if, RTF_UP);
        !           310:                aceStart((int)unit);
        !           311:                }
        !           312:        arpattach(&is->is_ac);
        !           313:        arpwhohas(&is->is_ac, &sin->sin_addr);
        !           314: }
        !           315: 
        !           316: /*
        !           317:  * Start output on interface.
        !           318:  * Get another datagram to send off of the interface queue,
        !           319:  * and map it to the interface before starting the output.
        !           320:  *
        !           321:  */
        !           322: acestart(dev)
        !           323: dev_t dev;
        !           324: {
        !           325: register struct tx_segment *txs;
        !           326: register long len,x;
        !           327: int unit = ACEUNIT(dev);
        !           328: struct vba_device *ui = aceinfo[unit];
        !           329: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        !           330: register struct ace_softc *is = &ace_softc[unit];
        !           331: register long  tripnum = 0;
        !           332: struct mbuf *m;
        !           333: short retries,idx;
        !           334: 
        !           335:        ACETRACE(STARTTRACE,
        !           336:                printf("ace%dstart: dev %X, txnext seg %x\n",unit,dev,
        !           337:                        (addr->tseg >> 11) & 0xf);)
        !           338: 
        !           339:        ACESTUDY(is->is_stats.tx_startcnt++;)
        !           340: again:
        !           341:        txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
        !           342:        if (txs->tx_csr & TCS_TBFULL) {
        !           343:                ACETRACE(ALLTRACE, printf("ace%dstart:segment %x is busy\n", 
        !           344:                                unit, is->is_txnext);)
        !           345:                is->is_stats.tx_busy++;
        !           346:                return;
        !           347:        }
        !           348: 
        !           349:        x = splimp();
        !           350:        IF_DEQUEUE(&is->is_if.if_snd, m);
        !           351:        splx(x);
        !           352:        if (m == 0)
        !           353:                return;
        !           354: 
        !           355:        len = aceput((int) unit, txs->tx_data, m);
        !           356:        retries = (txs->tx_csr & TCS_RTC);
        !           357:        acebakoff(is,txs,retries);
        !           358: 
        !           359:        /*
        !           360:         * Ensure minimum packet length.
        !           361:         * This makes the safe assumtion that there are no virtual holes
        !           362:         * after the data.
        !           363:         * For security, it might be wise to zero out the added bytes,
        !           364:         * but we're mainly interested in speed at the moment.
        !           365:         */
        !           366:        if (len - SIZEOF_ETHEADER < ETHERMIN)
        !           367:                len = ETHERMIN + SIZEOF_ETHEADER;
        !           368:        if (++is->is_txnext > SEG_MAX) 
        !           369:                is->is_txnext = is->is_segboundry;
        !           370:        is->is_if.if_opackets++;
        !           371:        is->is_xcnt++;
        !           372:        len = (len & 0x7fff) | TCS_TBFULL;
        !           373: 
        !           374:        ACETRACE(STARTTRACE,
        !           375:             printf("ace%dstart GO [csr %x][%x,%x,%x,%x,%x,%x] [%x,%x,%x,%x,%x,%x] [%x] [%x] \n",unit,
        !           376:                        (len & 0xffff),
        !           377:                        (txs->tx_data[0] & 0xff),(txs->tx_data[1] & 0xff), 
        !           378:                        (txs->tx_data[2] & 0xff),(txs->tx_data[3] & 0xff), 
        !           379:                        (txs->tx_data[4] & 0xff),(txs->tx_data[5] & 0xff), 
        !           380:                        (txs->tx_data[6] & 0xff),(txs->tx_data[7] & 0xff), 
        !           381:                        (txs->tx_data[8] & 0xff),(txs->tx_data[9] & 0xff), 
        !           382:                        (txs->tx_data[10] & 0xff),(txs->tx_data[11] & 0xff),
        !           383:                        (txs->tx_data[12] & 0xff),(txs->tx_data[13] & 0xff));)
        !           384:        movew((short)len,txs);
        !           385: 
        !           386:        goto again;
        !           387: }
        !           388: 
        !           389: /*
        !           390:  * Transmit done interrupt.
        !           391:  */
        !           392: acecint(unit)
        !           393: int unit;
        !           394: {
        !           395: register struct ace_softc *is = &ace_softc[unit];
        !           396: struct vba_device *ui = aceinfo[unit];
        !           397: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        !           398: register struct tx_segment *txseg;     /* ptr to V/EIU tx seg            */
        !           399: short txidx,eostat;
        !           400: 
        !           401:        ACESTUDY(is->is_stats.tx_cintcnt++;)
        !           402: 
        !           403:        if (is->is_xcnt <= 0)  {
        !           404:                txidx = ((addr->tseg >> 11) & 0xf);
        !           405:                printf("ace%dcint: stray xmit interrupt,xcnt %d\n",
        !           406:                        unit,is->is_xcnt);
        !           407:                printf("\t**eoctr %d, ctlr's tseg %d\n",is->is_eoctr,txidx);
        !           408:                is->is_xcnt = 0;
        !           409:                aceStart((int)unit);
        !           410:                return;
        !           411:        }
        !           412: 
        !           413:        is->is_xcnt--;
        !           414:        txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
        !           415:        if (((eostat = txseg->tx_csr) & TCS_TBFULL) == 0) {
        !           416:                is->is_stats.tx_retries += (eostat & TCS_RTC);
        !           417:                if (eostat & TCS_RTFAIL)  {
        !           418:                        is->is_stats.tx_discarded++;
        !           419:                        is->is_if.if_oerrors++;
        !           420:                }
        !           421:                else 
        !           422:                        is->is_stats.tx_datagrams++;
        !           423: 
        !           424:                if (++is->is_eoctr >= 16)
        !           425:                        is->is_eoctr = is->is_segboundry; 
        !           426:        } 
        !           427:        else {
        !           428:                ACESTUDY(is->is_stats.tx_cbusy++;)
        !           429:        }
        !           430: 
        !           431:        aceStart((int)unit);
        !           432: }
        !           433: 
        !           434: /*
        !           435:  * Ethernet interface receiver interrupt.
        !           436:  * If input error just drop packet.
        !           437:  * Otherwise purge input buffered data path and examine 
        !           438:  * packet to determine type.  If can't determine length
        !           439:  * from type, then have to drop packet.  Othewise decapsulate
        !           440:  * packet based on type and pass to type specific higher-level
        !           441:  * input routine.
        !           442:  */
        !           443: 
        !           444: 
        !           445: acerint(unit)
        !           446: int unit;
        !           447: {
        !           448: register struct ace_softc *is = &ace_softc[unit];
        !           449: register struct ifqueue *inq;
        !           450: register struct ether_header *ace;
        !           451: register struct rx_segment *rxseg;     /* ptr to V/EIU rx seg            */
        !           452: register long  tripnum = 0;
        !           453: struct acedevice *addr = (struct acedevice *)aceinfo[unit]->ui_addr;
        !           454: short eistat;
        !           455: struct mbuf *m;
        !           456: int len, s, off, resid;
        !           457:        
        !           458:        ACESTUDY(is->is_stats.rx_rintcnt++;)
        !           459: more:
        !           460:        rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
        !           461: 
        !           462:        if ((eistat = rxseg->rx_csr) & RCS_RBFULL)
        !           463:          {
        !           464:            is->is_if.if_ipackets++;
        !           465:            if (++is->is_eictr >= is->is_segboundry) 
        !           466:                    is->is_eictr = 0;
        !           467: 
        !           468:            ACETRACE(RTINTRACE, printf("ace%drint: is_eictr %x,[csr %x]\n",
        !           469:                        unit,is->is_eictr,(eistat & 0xffff));)
        !           470:            ACESTUDY(if (tripnum) is->is_stats.rx_rwoint++;)
        !           471: 
        !           472:            len = (eistat & RCS_RBC);
        !           473:            if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
        !           474:                (len < ET_MINLEN) || (len > (ET_MAXLEN+CRC_SIZE)))
        !           475:              {
        !           476:                if (eistat & RCS_ROVRN) is->is_stats.rx_overruns++;
        !           477:                if (eistat & RCS_RCRC) is->is_stats.rx_crc_errors++;
        !           478:                if (eistat & RCS_RODD) is->is_stats.rx_align_errors++;
        !           479:                if (len < ET_MINLEN) is->is_stats.rx_underruns++;
        !           480:                if (len > (ET_MAXLEN+CRC_SIZE)) is->is_stats.rx_overruns++;
        !           481:                is->is_if.if_ierrors++;
        !           482:                rxseg->rx_csr = 0;
        !           483: 
        !           484:                ACETRACE( RTINTRACE,
        !           485:                        if (is->is_if.if_ierrors % 100 == 0)
        !           486:                                printf("ace%d: += 100 input errors\n", unit);)
        !           487:                return;
        !           488:              }
        !           489:            else is->is_stats.rx_datagrams++;
        !           490:          }
        !           491:        else
        !           492:          {
        !           493:            if (tripnum==0) {
        !           494:                ACESTUDY(is->is_stats.rx_busy++;)
        !           495:            }
        !           496:            return;
        !           497:          }
        !           498:        ace = (struct ether_header *)(rxseg->rx_data);
        !           499:        len -= SIZEOF_ETHEADER;
        !           500: 
        !           501:        /*
        !           502:         * Deal with trailer protocol: if type is PUP trailer
        !           503:         * get true type from first 16-bit word past data.
        !           504:         * Remember that type was trailer by setting off.
        !           505:         */
        !           506:        ace->ether_type = ntohs((u_short)ace->ether_type);
        !           507: #define        acedataaddr(ace, off, type)     ((type)(((caddr_t)(((char *)ace)+SIZEOF_ETHEADER)+(off))))
        !           508: 
        !           509: /*     #define acedataaddr(ace, off, type)     ((type)(((caddr_t)((ace)+1)+(off))))
        !           510: */
        !           511:        if (ace->ether_type >= ETHERPUP_TRAIL &&
        !           512:            ace->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
        !           513:                off = (ace->ether_type - ETHERPUP_TRAIL) * 512;
        !           514:                if (off >= ETHERMTU)
        !           515:                        goto setup;             /* sanity */
        !           516:                ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *));
        !           517:                resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
        !           518:                if (off + resid > len)
        !           519:                        goto setup;             /* sanity */
        !           520:                len = off + resid;
        !           521:        } else
        !           522:                off = 0;
        !           523:        if (len == 0)
        !           524:                goto setup;
        !           525: 
        !           526:        /*
        !           527:         * Pull packet off interface.  Off is nonzero if packet
        !           528:         * has trailing header; aceget will then force this header
        !           529:         * information to be at the front, but we still have to drop
        !           530:         * the type and length which are at the front of any trailer data.
        !           531:         */
        !           532:        m = aceget((int)unit, rxseg->rx_data, len, off);
        !           533:        if (m == 0)
        !           534:                goto setup;
        !           535:        if (off) {
        !           536:                m->m_off += 2 * sizeof (u_short);
        !           537:                m->m_len -= 2 * sizeof (u_short);
        !           538:        }
        !           539:        switch (ace->ether_type) {
        !           540: 
        !           541: #ifdef INET
        !           542:        case ETHERPUP_IPTYPE:
        !           543:                if (tripnum == 0) {
        !           544:                        /* rely on the fact that ip_input() will drain
        !           545:                           the incoming queue after the first software 
        !           546:                           interrupt */
        !           547:                        schednetisr(NETISR_IP);
        !           548:                }
        !           549:                inq = &ipintrq;
        !           550:                break;
        !           551: 
        !           552:        case ETHERPUP_ARPTYPE:
        !           553:                arpinput(&is->is_ac, m);
        !           554:                goto setup;
        !           555: #endif
        !           556:        default:
        !           557:                ACETRACE(RTINTRACE,
        !           558:                        printf("\nUndefined packet type %d\n",ace->ether_type);)
        !           559:                m_freem(m);
        !           560:                goto setup;
        !           561:        }
        !           562: 
        !           563:        if (IF_QFULL(inq)) {
        !           564:                IF_DROP(inq);
        !           565:                m_freem(m);
        !           566:                goto setup;
        !           567:        }
        !           568:        s = splimp();
        !           569:        IF_ENQUEUE(inq, m);
        !           570:        splx(s);
        !           571: 
        !           572:        ACETRACE(RTINTRACE1,printf("acerint: enqlen %d: ",inq->ifq_len);)
        !           573:        ACETRACE(RTINTRACE1,aceprm(m);)
        !           574: setup:
        !           575:        rxseg->rx_csr = 0;
        !           576:        goto more;
        !           577: }
        !           578: 
        !           579: /*
        !           580:  * Ethernet output routine.
        !           581:  * Encapsulate a packet of type family for the local net.
        !           582:  * Use trailer local net encapsulation if enough data in first
        !           583:  * packet leaves a multiple of 512 bytes of data in remainder.
        !           584:  */
        !           585: aceoutput(ifp, m0, dst)
        !           586: struct ifnet *ifp;
        !           587: struct mbuf *m0;
        !           588: struct sockaddr *dst;
        !           589: {
        !           590: register short unit = ifp->if_unit;
        !           591: register struct ace_softc *is = &ace_softc[unit];
        !           592: register struct mbuf *m = m0;
        !           593: register struct ether_header *ace;
        !           594: register int off;
        !           595: register struct mbuf *mcopy;
        !           596: int type, s, error;
        !           597: u_char edst[6];
        !           598: struct in_addr idst;
        !           599: 
        !           600: #ifndef INET
        !           601:        ACETRACE(ACEOTRACE, 
        !           602:                printf("ace%doutput: ifp %lx, m0 %lx, dst ADDR %lx: ", 
        !           603:                        unit,ifp,m0, dst);)
        !           604:        ACETRACE(ACEOTRACE,aceprm(m0);)
        !           605: #endif
        !           606: 
        !           607:        switch (dst->sa_family) {
        !           608: 
        !           609: #ifdef INET
        !           610:        case AF_INET:
        !           611:                idst = ((struct sockaddr_in *)dst)->sin_addr;
        !           612:                ACETRACE(ACEOTRACE, 
        !           613:                        printf("ace%doutput: ifp %lx, m0 %lx, dst %lx: ", 
        !           614:                                unit,ifp,m0, idst.S_un.S_addr);)
        !           615:                ACETRACE(ACEOTRACE,aceprm(m0);)
        !           616: 
        !           617:                /* translate internet to ethernet address */
        !           618:                switch(arpresolve(&is->is_ac, m, &idst, edst)) {
        !           619:                case ARPRESOLVE_WILLSEND:
        !           620:                        return (0);     /* if not yet resolved */
        !           621:                case ARPRESOLVE_BROADCAST:
        !           622:                        mcopy = m_copy(m, 0, (int)M_COPYALL);
        !           623:                        MBUFNULL(42, mcopy);    /* for debugging */
        !           624:                        if (mcopy)
        !           625:                                looutput(&loif, mcopy, dst);
        !           626: 
        !           627:                        /* falls through ... */
        !           628:                case ARPRESOLVE_OK:
        !           629:                        break;
        !           630:                }
        !           631: 
        !           632:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
        !           633: 
        !           634:                /* need per host negotiation */
        !           635:                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
        !           636:                  if (off > 0 && (off & 0x1ff) == 0 &&
        !           637:                      m->m_off >= MMINOFF + 2 * sizeof (u_short))
        !           638:                    {
        !           639:                        type = ETHERPUP_TRAIL + (off>>9);
        !           640:                        m->m_off -= 2 * sizeof (u_short);
        !           641:                        m->m_len += 2 * sizeof (u_short);
        !           642:                        *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
        !           643:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
        !           644:                        goto gottrailertype;
        !           645:                    }
        !           646:                type = ETHERPUP_IPTYPE;
        !           647:                off = 0;
        !           648:                goto gottype;
        !           649: #endif
        !           650: 
        !           651:        case AF_UNSPEC:
        !           652:                ace = (struct ether_header *)dst->sa_data;
        !           653:                bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
        !           654:                type = ace->ether_type;
        !           655:                goto gottype;
        !           656: 
        !           657:        default:
        !           658:                printf("ace%d: can't handle af%d\n", unit,dst->sa_family);
        !           659:                error = EAFNOSUPPORT;
        !           660:                goto bad;
        !           661:        }
        !           662: 
        !           663: gottrailertype:
        !           664:        /*
        !           665:         * Packet to be sent as trailer: move first packet
        !           666:         * (control information) to end of chain.
        !           667:         */
        !           668:        while (m->m_next)
        !           669:                m = m->m_next;
        !           670:        m->m_next = m0;
        !           671:        m = m0->m_next;
        !           672:        m0->m_next = 0;
        !           673:        m0 = m;
        !           674: 
        !           675: gottype:
        !           676:        /*
        !           677:         * Add local net header.  If no space in first mbuf,
        !           678:         * allocate another.
        !           679:         */
        !           680:        if (m->m_off > MMAXOFF ||
        !           681:            MMINOFF + SIZEOF_ETHEADER > m->m_off) { 
        !           682:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           683:                MBUFNULL(30, m);
        !           684:                if (m == 0) {
        !           685:                        error = ENOBUFS;
        !           686:                        goto bad;
        !           687:                }
        !           688:                m->m_next = m0;
        !           689:                m->m_off = MMINOFF;
        !           690:                m->m_len = SIZEOF_ETHEADER;
        !           691:        } else {
        !           692:                m->m_off -= SIZEOF_ETHEADER;
        !           693:                m->m_len += SIZEOF_ETHEADER;
        !           694:        }
        !           695:        ace = mtod(m, struct ether_header *);
        !           696:        ace->ether_type = htons((u_short)type);
        !           697:        bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
        !           698:        bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 6);
        !           699: 
        !           700:        /*
        !           701:         * Queue message on interface, and start output if interface
        !           702:         * not yet active.
        !           703:         */
        !           704:        s = splimp();
        !           705:        if (IF_QFULL(&ifp->if_snd)) {
        !           706:                IF_DROP(&ifp->if_snd);
        !           707:                splx(s);
        !           708:                m_freem(m);
        !           709:                return (ENOBUFS);
        !           710:        }
        !           711:        IF_ENQUEUE(&ifp->if_snd, m);
        !           712:        splx(s);
        !           713: 
        !           714:        ACETRACE (ACEOTRACE, printf("ace%doutput: enqu mbuf %lx: ",unit,m);)
        !           715:        ACETRACE (ACEOTRACE, aceprm(m);)
        !           716:        ACESTUDY (is->is_stats.tx_outcnt++;)
        !           717: 
        !           718:        aceStart((int)unit);
        !           719:        return (0);
        !           720: 
        !           721: bad:
        !           722:        ACETRACE(ACEOTRACE, printf("ace%doutput: BAD.\n");)
        !           723:        m_freem(m0);
        !           724:        return (error);
        !           725: }
        !           726: 
        !           727: aceStart(unit)
        !           728: int unit;
        !           729: {
        !           730: register struct ace_softc *is = &ace_softc[unit];
        !           731: 
        !           732:        if (!(is->is_flags & ACEF_OACTIVE)) {
        !           733:                is->is_flags |= ACEF_OACTIVE;
        !           734:                acestart((dev_t)unit);
        !           735:                is->is_flags &= ~ACEF_OACTIVE;
        !           736:        }
        !           737: }
        !           738: 
        !           739: /*
        !           740:  * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
        !           741:  * If packet size is less than the minimum legal size,
        !           742:  * the buffer is expanded.  We probably should zero out the extra
        !           743:  * bytes for security, but that would slow things down.
        !           744:  */
        !           745: aceput(unit, txbuf, m)
        !           746: int    unit;                   /* for statistics collection */
        !           747: u_char *txbuf;
        !           748: struct mbuf *m;
        !           749: {
        !           750: register       u_char *bp;
        !           751: register       u_char *mcp;
        !           752: register       short *s1;
        !           753: register       short *s2;
        !           754: register       unsigned len;
        !           755: register       struct mbuf *mp;
        !           756: int total, idx;
        !           757: 
        !           758:        ACETRACE(STARTTRACE, printf("aceput: txbuf %X, mbuf %X, m->m_off %d\n",
        !           759:                txbuf,m,m->m_off);)
        !           760:        ACETRACE(STARTTRACE,aceprm(m);)
        !           761: 
        !           762:        total = 0;
        !           763:        bp = (u_char *)txbuf;
        !           764:        for (mp = m;(mp); mp = mp->m_next)
        !           765:          {
        !           766:                len = mp->m_len;
        !           767:                if (len == 0)
        !           768:                        continue;
        !           769: 
        !           770:                total += len;
        !           771:                mcp = mtod(mp, u_char *);
        !           772: 
        !           773:                /*bcopy((caddr_t)mcp,(caddr_t)bp,len);*/
        !           774:                /*bp += len;*/
        !           775: 
        !           776:                if (((int)mcp & 01) && ((int)bp & 01)) {
        !           777:                        /* source & destination at odd addresses */
        !           778:                        /* *bp++ = *mcp++; */
        !           779:                        asm("movob (r11),(r12)");
        !           780:                        asm("addl2 $1,r12");
        !           781:                        asm("addl2 $1,r11");
        !           782:                        --len;
        !           783:                }
        !           784:                if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
        !           785:                        register int    l;
        !           786: 
        !           787:                        s1 = (short *)bp;
        !           788:                        s2 = (short *)mcp;
        !           789:                        l = (len >> 1);         /* count # of shorts */
        !           790:                        while (l-->0) {         /* copy shorts */
        !           791:                                /* *s1++ = *s2++; */
        !           792:                                asm("movow (r9),(r10)");
        !           793:                                asm("addl2 $2,r10");
        !           794:                                asm("addl2 $2,r9");
        !           795:                        }
        !           796:                        len &= 1;               /* # remaining bytes */
        !           797:                        bp = (u_char *)s1;
        !           798:                        mcp = (u_char *)s2;
        !           799:                }
        !           800:                while (len-- > 0) {
        !           801:                        /* *bp++ = *mcp++;  */
        !           802:                        asm("movob (r11),(r12)");
        !           803:                        asm("addl2 $1,r12");
        !           804:                        asm("addl2 $1,r11");
        !           805:                }
        !           806:          }
        !           807:        m_freem(m);
        !           808:        return(total);
        !           809: }
        !           810: 
        !           811: movew(data,to)
        !           812: short data;
        !           813: short *to;
        !           814: {
        !           815:        asm("movow 6(fp),*8(fp)");
        !           816: }
        !           817: 
        !           818: 
        !           819: #ifdef ACEPRINTFS
        !           820: aceprm(mp)
        !           821: struct mbuf *mp;
        !           822: {
        !           823:        register u_char *mcp;
        !           824:        register struct mbuf *mpp;
        !           825:        register long idx;
        !           826:        register long totlen,lx;
        !           827: 
        !           828:            for(totlen=0,mpp=mp->m_next; mpp; mpp=mpp->m_next) 
        !           829:                totlen += mpp->m_len; 
        !           830: 
        !           831:            mcp = mtod(mp, u_char *);
        !           832:            printf("mbuf[len %d,off %d],[next %lx,totlen %ld],[",
        !           833:                        mp->m_len,mp->m_off,mp->m_next,totlen);
        !           834:            for (idx=0 ; (idx < 20 ); idx++)
        !           835:                  {
        !           836:                    printf("%x ",mcp[idx] & 0xff);
        !           837:                  }
        !           838:            printf("]\n");
        !           839: }
        !           840: #endif ACEPRINTFS
        !           841: 
        !           842: /*
        !           843:  * Routine to copy from VERSAbus memory into mbufs.
        !           844:  *
        !           845:  * Warning: This makes the fairly safe assumption that
        !           846:  * mbufs have even lengths.
        !           847:  */
        !           848: struct mbuf *
        !           849: aceget(unit, rxbuf, totlen, off0)
        !           850: int    unit;                   /* for statistics collection */
        !           851: u_char *rxbuf;
        !           852: int totlen, off0;
        !           853: {
        !           854: register       u_char *cp;
        !           855: register       u_char *mcp;
        !           856: register       int     tlen;
        !           857: int            len;
        !           858: 
        !           859: register struct mbuf *m;
        !           860: struct mbuf *top = 0, **mp = &top;
        !           861: int off = off0;
        !           862: 
        !           863:        ACETRACE(RTINTRACE, printf("aceget: rxbuf %lx, len %d, off %d\n",
        !           864:                                rxbuf,totlen,off0);)
        !           865: 
        !           866:        cp = rxbuf + SIZEOF_ETHEADER;
        !           867:        while (totlen > 0)
        !           868:          {
        !           869:          register int words;
        !           870: 
        !           871:                MGET(m, M_DONTWAIT, MT_DATA);
        !           872:                MBUFNULL(33, m);
        !           873:                if (m == 0)
        !           874:                        goto bad;
        !           875:                if (off) {
        !           876:                        len = totlen - off;
        !           877:                        cp = rxbuf +
        !           878:                                SIZEOF_ETHEADER + off;
        !           879:                } else
        !           880:                        len = totlen;
        !           881: 
        !           882:                if (len >= CLBYTES) {
        !           883:                        struct mbuf *p;
        !           884: 
        !           885:                        MCLGET(p, 1);
        !           886:                        if (p != 0) {
        !           887:                                m->m_len = len = CLBYTES;
        !           888:                                m->m_off = (int)p - (int)m;
        !           889:                        } else {
        !           890:                                m->m_len = len = MIN(MLEN, len);
        !           891:                                m->m_off = MMINOFF;
        !           892:                        }
        !           893:                } else {
        !           894:                        m->m_len = len = MIN(MLEN, len);
        !           895:                        m->m_off = MMINOFF;
        !           896:                }
        !           897: 
        !           898:                mcp = mtod(m, u_char *);
        !           899: 
        !           900:                /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
        !           901:                /*cp += len; mcp += len;*/
        !           902: 
        !           903:                tlen = len;
        !           904:                if (((int)mcp & 01) && ((int)cp & 01)) {
        !           905:                        /* source & destination at odd addresses */
        !           906:                        *mcp++ = *cp++;
        !           907:                        --tlen;
        !           908:                }
        !           909:                if (tlen > 1 && (((int)mcp & 01)==0) && (((int)cp & 01)==0)) {
        !           910:                        register short  *s1;
        !           911:                        register short  *s2;
        !           912:                        register int    l;
        !           913: 
        !           914:                        s1 = (short *)mcp;
        !           915:                        s2 = (short *)cp;
        !           916:                        l = (tlen >> 1);                /* count # of shorts */
        !           917:                        while (l-->0)           /* copy shorts */
        !           918:                                *s1++ = *s2++;
        !           919:                        tlen &= 1;              /* # remaining bytes */
        !           920:                        mcp = (u_char *)s1;
        !           921:                        cp = (u_char *)s2;
        !           922:                }
        !           923:                while (tlen-- > 0)
        !           924:                        *mcp++ = *cp++;
        !           925: 
        !           926:                *mp = m;
        !           927:                mp = &m->m_next;
        !           928:                if (off == 0) {
        !           929:                        totlen -= len;
        !           930:                        continue;
        !           931:                }
        !           932:                off += len;
        !           933:                if (off == totlen) {
        !           934:                        cp = rxbuf + SIZEOF_ETHEADER;
        !           935:                        off = 0;
        !           936:                        totlen = off0;
        !           937:                }
        !           938:          }
        !           939:        return (top);
        !           940: bad:
        !           941:        m_freem(top);
        !           942:        return (0);
        !           943: }
        !           944: 
        !           945: /*+procedure                                                   */
        !           946: /*                                                             */
        !           947: 
        !           948: acebakoff(is, txseg, retries)
        !           949: struct ace_softc *is;          /* ptr to UCB for this device     */
        !           950: struct tx_segment *txseg;      /* ptr to V/EIU tx seg            */
        !           951: register int retries;          /* # of randoms to generate       */
        !           952: {
        !           953: short *pMask;                  /* ptr to mask table.        */
        !           954: register short *pBakNum;       /* ptr to # entry in Tx seg table */
        !           955: register short random_num;     /* random number value.      */
        !           956: 
        !           957: 
        !           958:        pMask   = &random_mask_tbl[0];
        !           959:        pBakNum = &txseg->tx_backoff[0];
        !           960: 
        !           961:        for (; --retries >= 0;)
        !           962:          {
        !           963:            random_num   = (is->is_currnd = (is->is_currnd * 18741)-13849);
        !           964:            random_num  &= *(pMask++);
        !           965:            *(pBakNum++) = random_num ^ (short)(0xFF00 | 0x00FC);
        !           966:          }
        !           967: }
        !           968: 
        !           969: /*
        !           970:  * Process an ioctl request.
        !           971:  */
        !           972: aceioctl(ifp, cmd, data)
        !           973: register struct ifnet *ifp;
        !           974: int cmd;
        !           975: caddr_t data;
        !           976: {
        !           977: register struct vba_device *ui;
        !           978: register struct acedevice *addr;
        !           979: register struct sockaddr_in *et_addr;
        !           980: register struct ace_softc *is;
        !           981: register struct ifreq *ifr = (struct ifreq *)data;
        !           982: int s , error = 0;
        !           983: 
        !           984:        ACETRACE (IOCTLTRACE,
        !           985:                printf("aceioctl: ifp %X, cmd %X, data %X\n",ifp,cmd,data);)
        !           986: 
        !           987:        switch (cmd) {
        !           988: 
        !           989:        case SIOCSIFADDR:
        !           990:                s = splimp();
        !           991:                if (ifp->if_flags & IFF_RUNNING)
        !           992:                        if_rtinit(ifp, -1);     /* delete previous route */
        !           993:                acesetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
        !           994:                aceinit(ifp->if_unit);
        !           995:                splx(s);
        !           996:                break;
        !           997: 
        !           998:        case SIOCSETETADDR:     /* Set Ethernet station address */
        !           999:                s = splimp();
        !          1000:                ifp->if_flags &= (~IFF_RUNNING | IFF_UP);
        !          1001:                et_addr = (struct sockaddr_in *)&ifr->ifr_addr;
        !          1002:                ui = aceinfo[ifp->if_unit];
        !          1003:                addr = (struct acedevice *)ui->ui_addr;
        !          1004:                movew((short)CSR_RESET,&addr->csr);     /* Reset again */
        !          1005:                DELAY(10000);
        !          1006:                /* Set station address and copy addr to arp struct */
        !          1007:                acesetetaddr(ifp->if_unit,addr,&et_addr->sin_zero[2]);
        !          1008:                aceinit(ifp->if_unit);          /* Re-initialize */
        !          1009:                splx(s);
        !          1010:                break;
        !          1011: 
        !          1012:        default:
        !          1013:                error = EINVAL;
        !          1014:        }
        !          1015:        return (error);
        !          1016: }
        !          1017: 
        !          1018: acesetaddr(ifp, sin)
        !          1019: register struct ifnet *ifp;
        !          1020: register struct sockaddr_in *sin;
        !          1021: {
        !          1022: 
        !          1023:        ACETRACE (IOCTLTRACE, printf("acesetaddr: ifp %X, sin %X\n",ifp,sin);)
        !          1024: 
        !          1025:        arpremove(&ifp->if_addr);
        !          1026:        ifp->if_addr = *(struct sockaddr *)sin;
        !          1027:        ifp->if_net = in_netof(sin->sin_addr);
        !          1028:        ifp->if_host[0] = in_lnaof(sin->sin_addr);
        !          1029:        sin = (struct sockaddr_in *)&ifp->if_broadaddr;
        !          1030:        sin->sin_family = AF_INET;
        !          1031:        sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
        !          1032:        ifp->if_flags |= IFF_BROADCAST;
        !          1033: }
        !          1034: 
        !          1035: aceclean(unit)
        !          1036: int    unit;
        !          1037: {
        !          1038: register struct ace_softc *is = &ace_softc[unit];
        !          1039: register struct ifnet *ifp = &is->is_if;
        !          1040: register struct vba_device *ui = aceinfo[unit];
        !          1041: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        !          1042: register short i, data;
        !          1043: register char *pData1;
        !          1044: 
        !          1045:        is->is_dpm = acemap[unit];              /* init dpm             */
        !          1046:        ioaccess(ACEmap[unit],ACEmapa[unit],ACEBPTE);
        !          1047:        bzero((char *)is->is_dpm, (16384*2));
        !          1048: 
        !          1049:        is->is_currnd = 49123;
        !          1050:        is->is_segboundry = (addr->segb >> 11) & 0xf;
        !          1051:        for (pData1 = (char*)((int)is->is_dpm + (is->is_segboundry << 11)),
        !          1052:             i = (SEG_MAX + 1) - is->is_segboundry;
        !          1053:             (--i >= 0); pData1 += sizeof (struct tx_segment))
        !          1054:             acebakoff(is,((struct tx_segment*)pData1),15);
        !          1055: 
        !          1056:        is->is_eictr = 0;
        !          1057:        is->is_eoctr = is->is_txnext = is->is_segboundry;
        !          1058:        bzero((char *)&is->is_stats, sizeof(is->is_stats));
        !          1059: 
        !          1060: }
        !          1061: #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.