Annotation of cci/sys/tahoeif/if_ace.c, revision 1.1.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.