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

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

unix.superglobalmegacorp.com

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