Annotation of researchv9/sys/boot/stand/if_le.c, revision 1.1.1.1

1.1       root        1: #ifndef LEBOOT
                      2: #ifndef lint
                      3: static char sccsid[] = "@(#)if_le.c 1.1 86/02/03 Copyr 1985 Sun Micro";
                      4: #endif
                      5: #endif
                      6: 
                      7: /*
                      8:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      9:  */
                     10: 
                     11: /*
                     12:  * For Sun-3/25 debugging we want DEBUG on.  For production, turn it off.
                     13:  */
                     14: /* #define DEBUG */
                     15: /* #define DEBUG1 */
                     16: 
                     17: #define LANCEBUG 1     /* Rev C Lance chip bug */
                     18: 
                     19: /* 
                     20:  * Parameters controlling TIMEBOMB action: times out if chip hangs.
                     21:  *
                     22:  */
                     23: #define        TIMEBOMB        1000000 /* One million times around is all... */
                     24: 
                     25: /*
                     26:  * Sun Lance Ethernet Controller interface
                     27:  */
                     28: #include "saio.h"
                     29: #include "param.h"
                     30: #include "../h/socket.h"
                     31: #include "../sunif/if_lereg.h"
                     32: #include "../net/if.h"
                     33: #include "../netinet/in.h"
                     34: #include "../netinet/if_ether.h"
                     35: #include "../mon/idprom.h"
                     36: #include "../mon/cpu.map.h"
                     37: 
                     38: /* Determine whether we are PROM or not. */
                     39: #ifdef LEBOOT
                     40: #define PROM
                     41: #endif LEBOOT
                     42: 
                     43: int    lancexmit(), lancepoll(), lancereset();
                     44: 
                     45: struct saif leif = {
                     46:        lancexmit,
                     47:        lancepoll,
                     48:        lancereset,
                     49: };
                     50: 
                     51: #define        LANCERBUFSIZ    1600
                     52: #define        LANCETBUFSIZ    1600
                     53: 
                     54: struct lance_softc {
                     55:        char            es_scrat[PROTOSCRATCH]; /* work space for nd */
                     56:        struct le_device        *es_lance;      /* Device register address */
                     57:        struct ether_addr       es_enaddr;      /* Our Ethernet address */
                     58:        struct le_init_block    es_ib;          /* Initialization block */
                     59:        struct le_md            *es_rmdp[2];    /* Receive Desc Ring ptrs */
                     60:        struct le_md            *es_tmdp;       /* Transmit Desc Ring ptr */
                     61:        u_char                  es_rbuf[2][LANCERBUFSIZ]; /* Receive Buffers */
                     62: #ifndef PROM
                     63:        u_char                  es_tbuf[LANCETBUFSIZ];  /* Transmit Buffer */
                     64: #endif PROM
                     65:        int                     es_next_rmd;    /* Next descriptor in ring */
                     66:        /*
                     67:         * The transmit and receive ring descriptors.  The es_{r,t}mdp
                     68:         * entries point into these arrays.  We allocate an extra one of
                     69:         * each so that we can guarantee 8-byte alignment.  (That is, we
                     70:         * don't necessarily point locations an integral number of le_mds
                     71:         * from the start of the arrays.
                     72:         */
                     73:        struct le_md            es_rmd[3],
                     74:                                es_tmd[2];
                     75: };
                     76: 
                     77: 
                     78: /*
                     79:  * Need to initialize the Ethernet control reg to:
                     80:  *     Reset is active
                     81:  *     Loopback is NOT active
                     82:  *     Interrupt enable is not active.
                     83:  */
                     84: u_long lancestd[] = {VIOPG_AMD_ETHER << BYTES_PG_SHIFT};
                     85: 
                     86: struct devinfo lanceinfo = {
                     87:        sizeof (struct le_device),
                     88:        sizeof (struct lance_softc),
                     89:        0,                              /* Local bytes (we use dma) */
                     90:        1,                              /* Standard addr count */
                     91:        lancestd,                       /* Standard addrs */
                     92:        MAP_OBIO,                       /* Device type */
                     93:        0,                              /* transfer size handled by ND */
                     94: };
                     95: 
                     96: int lanceprobe(), xxboot(), lanceopen(), lanceclose(), etherstrategy();
                     97: int nullsys();
                     98: 
                     99: struct boottab ledriver = {
                    100:        "le", lanceprobe, xxboot, lanceopen, lanceclose,
                    101:        etherstrategy, "le: Sun/Lance Ethernet", &lanceinfo,
                    102: };
                    103: 
                    104: extern struct ether_addr etherbroadcastaddr;
                    105: 
                    106: /*
                    107:  * Probe for device.
                    108:  * Must return -1 for failure for monitor probe
                    109:  */
                    110: lanceprobe(sip)
                    111:        struct saioreq *sip;
                    112: {
                    113:        register short *sp;
                    114:        struct idprom id;
                    115: 
                    116:        if (IDFORM_1 == idprom(IDFORM_1, &id)
                    117:            && id.id_machine == IDM_SUN3_M25)
                    118:                return (0);
                    119:        else
                    120:                return (-1);
                    121: }
                    122: 
                    123: /*
                    124:  * Open Lance Ethernet nd connection, return -1 for errors.
                    125:  */
                    126: lanceopen(sip)
                    127:        struct saioreq *sip;
                    128: {
                    129:        register int result;
                    130: 
                    131: #ifdef DEBUG1
                    132:        printf("le: lanceopen[\n");
                    133: #endif
                    134:        sip->si_sif = &leif;
                    135:        if ( lanceinit(sip) || (result = etheropen(sip)) < 0 ) {
                    136:                lanceclose(sip);                /* Make sure we kill chip */
                    137: #ifdef DEBUG1
                    138:                printf("le: lanceopen --> -1\n");
                    139: #endif
                    140:                return (-1);
                    141:        }
                    142: #ifdef DEBUG1
                    143:        printf("le: lanceopen --> %x\n", result);
                    144: #endif
                    145:        return (result);
                    146: }
                    147: 
                    148: /*
                    149:  * Set up memory maps and Ethernet chip.
                    150:  * Returns 1 for error (after printing message), 0 for ok.
                    151:  */
                    152: int
                    153: lanceinit(sip)
                    154:        struct saioreq *sip;
                    155: {
                    156:        register struct lance_softc *es;
                    157:        int paddr;
                    158:        int i;
                    159:        struct idprom id;
                    160:        
                    161:        /* 
                    162:         * Our locals were obtined from DMA space, now put the locals
                    163:         * pointer in the standard place.  This is OK since close()
                    164:         * will only deallocate from devdata if its size in devinfo is >0.
                    165:         */
                    166:        es = (struct lance_softc *)sip->si_dmaaddr;
                    167:        sip->si_devdata = (caddr_t)es;
                    168:        es->es_lance = (struct le_device *) sip->si_devaddr;
                    169: 
                    170:        if (IDFORM_1 != idprom(IDFORM_1, &id)) {
                    171:                printf("le: No ID PROM\n");
                    172:                return 1;
                    173:        }
                    174: 
                    175:        return lancereset(es, sip);
                    176: }
                    177: 
                    178: /*
                    179:  * Basic Lance initialization
                    180:  * Returns 1 for error (after printing message), 0 for ok.
                    181:  */
                    182: int
                    183: lancereset(es, sip)
                    184:        register struct lance_softc *es;
                    185:        struct saioreq *sip;
                    186: {
                    187:        register struct le_device *le = es->es_lance;
                    188:        register struct le_init_block *ib = &es->es_ib;
                    189:        int timeout = TIMEBOMB;
                    190:        int i;
                    191: 
                    192: #ifdef DEBUG1
                    193:        printf("le: lancereset(%x, %x)\n", es, sip);
                    194: #endif
                    195: 
                    196:        /* Reset the chip */
                    197:        le->le_rap = LE_CSR0;
                    198:        le->le_csr = LE_STOP;
                    199: 
                    200:        /* Perform the basic initialization */
                    201:        
                    202:        /* Construct the initialization block */
                    203:        bzero((caddr_t)&es->es_ib, sizeof (struct le_init_block));
                    204: 
                    205:        /* Leave the mode word 0 for normal operating mode */
                    206: 
                    207:        myetheraddr(&es->es_enaddr);
                    208: 
                    209:        /* Oh, for a consistent byte ordering among processors */
                    210:        ib->ib_padr[0] = es->es_enaddr.ether_addr_octet[1];
                    211:        ib->ib_padr[1] = es->es_enaddr.ether_addr_octet[0];
                    212:        ib->ib_padr[2] = es->es_enaddr.ether_addr_octet[3];
                    213:        ib->ib_padr[3] = es->es_enaddr.ether_addr_octet[2];
                    214:        ib->ib_padr[4] = es->es_enaddr.ether_addr_octet[5];
                    215:        ib->ib_padr[5] = es->es_enaddr.ether_addr_octet[4];
                    216: 
                    217:        /* Leave address filter 0 -- we don't want Multicast packets */
                    218: 
                    219:        /*
                    220:         * Set up transmit and receive ring pointers,
                    221:         * taking the 8-byte alignment requirement into account.
                    222:         */
                    223:        es->es_rmdp[0] = (struct le_md *) ((u_long)(&es->es_rmd[0]) & ~07) + 1;
                    224:        es->es_rmdp[1] = es->es_rmdp[0] + 1;
                    225:        es->es_tmdp    = (struct le_md *) ((u_long)(&es->es_tmd[0]) & ~07) + 1;
                    226: 
                    227:        ib->ib_rdrp.drp_laddr = (long)es->es_rmdp[0];
                    228:        ib->ib_rdrp.drp_haddr = (long)es->es_rmdp[0] >> 16;
                    229:        ib->ib_rdrp.drp_len  = 1;   /* 2 to the 1 power = 2 */
                    230:        
                    231:        ib->ib_tdrp.drp_laddr = (long)es->es_tmdp;
                    232:        ib->ib_tdrp.drp_haddr = (long)es->es_tmdp >> 16;
                    233:        ib->ib_tdrp.drp_len  = 0;   /* 2 to the 0 power = 1 */
                    234: 
                    235:        /* Clear all the descriptors */
                    236:        bzero((caddr_t)es->es_rmdp[0], 2 * sizeof (struct le_md));
                    237:        bzero((caddr_t)es->es_tmdp, sizeof (struct le_md));
                    238: 
                    239:        /* Give the init block to the chip */
                    240:        le->le_rap = LE_CSR1;   /* select the low address register */
                    241:        le->le_rdp = (long)ib & 0xffff;
                    242: 
                    243:        le->le_rap = LE_CSR2;   /* select the high address register */
                    244:        le->le_rdp = ((long)ib >> 16) & 0xff;
                    245: 
                    246:        le->le_rap = LE_CSR3;   /* Bus Master control register */
                    247:        le->le_rdp = LE_BSWP;
                    248: 
                    249:        le->le_rap = LE_CSR0;   /* main control/status register */
                    250:        le->le_csr = LE_INIT;
                    251: 
                    252:        while( ! (le->le_csr & LE_IDON) ) {
                    253:                if (timeout-- <= 0) {
                    254:                    printf("le: cannot initialize\n");
                    255:                    return (1);
                    256:                }
                    257:        }
                    258:        le->le_csr = LE_IDON;   /* Clear the indication */
                    259: 
                    260:        /* Hang out the receive buffers */
                    261:        es->es_next_rmd = 0;
                    262: 
                    263:        install_buf_in_rmd(es->es_rbuf[0], es->es_rmdp[0]);
                    264:        install_buf_in_rmd(es->es_rbuf[1], es->es_rmdp[1]);
                    265: 
                    266:        le->le_csr = LE_STRT;
                    267: 
                    268: #ifdef DEBUG1
                    269:        printf("le: lancereset returns OK\n");
                    270: #endif
                    271:        return 0;               /* It all worked! */
                    272: }
                    273: 
                    274: install_buf_in_rmd(buffer, rmd)
                    275:        u_char *buffer;
                    276:        register struct le_md *rmd;
                    277: {
                    278:        rmd->lmd_ladr = (u_short)buffer;
                    279:        rmd->lmd_hadr = (long)buffer >> 16;
                    280:        rmd->lmd_bcnt = -LANCERBUFSIZ;
                    281:        rmd->lmd_mcnt = 0;
                    282:        rmd->lmd_flags = LMD_OWN;
                    283: }
                    284: 
                    285: /*
                    286:  * Transmit a packet.
                    287:  * If possible, just points to the packet without copying it anywhere.
                    288:  */
                    289: lancexmit(es, buf, count)
                    290:        register struct lance_softc *es;
                    291:        char *buf;
                    292:        int count;
                    293: {
                    294:        register struct le_device *le = es->es_lance;
                    295:        struct le_md *tmd = es->es_tmdp; /* Transmit Msg. Descriptor */
                    296:        caddr_t tbuf;
                    297:        int timeout = TIMEBOMB;
                    298: 
                    299: #ifdef DEBUG2
                    300:        printf( "xmit np_blkno %x\n",
                    301:                ((struct ndpack *)(buf+14))->np_blkno);
                    302: #endif
                    303:        /*
                    304:         * We assume the buffer is in an area accessible by the chip.
                    305:         * The caller of xmit is currently ndxmit(), which only sends
                    306:         * an nd structure, which we happen to know is allocated in the
                    307:         * right area (in fact, it's part of the struct nd which
                    308:         * is the first thing in our own es structure).  If we wish to
                    309:         * use xmit for some other purpose, the buffer might not be
                    310:         * accessible by the chip, so to be general we ought to copy
                    311:         * into some accessible place.  HOWEVER, PROM space is really tight,
                    312:         * so this generality is not free.
                    313:         */
                    314: #ifdef PROM
                    315:        tbuf = buf;
                    316: #else  PROM
                    317: /* FIXME, constant address masks here! */
                    318:        if ( ((int)buf & 0x0F000000) == 0x0F000000) { /* we can point to it */
                    319:            tbuf = buf;
                    320:        } else {
                    321:            tbuf = (caddr_t)es->es_tbuf;
                    322:            bcopy((caddr_t)buf, tbuf, count);
                    323:        }
                    324: #endif PROM
                    325:        
                    326:        tmd->lmd_hadr = (int)tbuf >> 16;
                    327:        tmd->lmd_ladr = (u_short) tbuf;
                    328:        tmd->lmd_bcnt = -count;
                    329:        
                    330: #ifdef notdef
                    331:        if (tmd->lmd_bcnt < -MINPACKET)
                    332:            tmd->lmd_bcnt = -MINPACKET;
                    333: #endif
                    334:        tmd->lmd_flags3 = 0;
                    335:        tmd->lmd_flags = LMD_STP | LMD_ENP | LMD_OWN;
                    336:        
                    337:        le->le_csr = LE_TDMD;
                    338: 
                    339:        do {
                    340:            if ( le->le_csr & LE_TINT ) {
                    341:                le->le_csr = LE_TINT; /* Clear interrupt */
                    342:                break;
                    343:            }
                    344:        } while ( --timeout > 0);
                    345: 
                    346:        if ( (tmd->lmd_flags & LMD_ERR)
                    347:        ||   (tmd->lmd_flags3 & TMD_BUFF)
                    348:        ||   (timeout <= 0) ) {
                    349: #ifdef DEBUG
                    350:                printf("le: xmit failed - tmd1 flags %x tmd3 %x\n",
                    351:                        tmd->lmd_flags, tmd->lmd_flags3);
                    352: #endif
                    353:                return (1);
                    354:        }
                    355: 
                    356:        return (0);
                    357: }
                    358: 
                    359: int
                    360: lancepoll(es, buf)
                    361:        register struct lance_softc *es;
                    362:        char *buf;
                    363: {
                    364:        register struct le_device *le = es->es_lance;
                    365:        register struct le_md *rmd;
                    366:        register struct ether_header *header;
                    367:        int length;
                    368: 
                    369: #ifdef DEBUG1
                    370:        printf("le: poll\n");
                    371: #endif
                    372:        if ( ! (le->le_csr & LE_RINT)  )
                    373:                return (0);             /* No packet yet */
                    374: 
                    375: #ifdef DEBUG1
                    376:        printf("le: received packet\n");
                    377: #endif
                    378: 
                    379:        le->le_csr = LE_RINT;           /* Clear interrupt */
                    380: 
                    381:        rmd = es->es_rmdp[es->es_next_rmd];
                    382: 
                    383:        if ( (rmd->lmd_flags & ~RMD_OFLO) != (LMD_STP|LMD_ENP) ) {
                    384: #ifdef DEBUG
                    385:                printf("Receive packet error - rmd flags %x\n",rmd->lmd_flags);
                    386: #endif
                    387:                length = 0;
                    388:                goto restorebuf;
                    389:        }
                    390: 
                    391:        /* Get input data length and a pointer to the ethernet header */
                    392: 
                    393:        length = rmd->lmd_mcnt - 4;     /* don't count the 4 CRC bytes */
                    394:        header = (struct ether_header *)es->es_rbuf[es->es_next_rmd];
                    395: 
                    396: #ifdef LANCEBUG
                    397:        /*
                    398:         * Check for unreported packet errors.  Rev C of the LANCE chip
                    399:         * has a bug which can cause "random" bytes to be prepended to
                    400:         * the start of the packet.  The work-around is to make sure that
                    401:         * the Ethernet destination address in the packet matches our
                    402:         * address.
                    403:         */
                    404: #define ether_addr_not_equal(a,b)      \
                    405:        (  ( *(long  *)(&a.ether_addr_octet[0]) != \
                    406:             *(long  *)(&b.ether_addr_octet[0]) )  \
                    407:        || ( *(short *)(&a.ether_addr_octet[4]) != \
                    408:             *(short *)(&b.ether_addr_octet[4]) )  \
                    409:        )
                    410: 
                    411:        if( ether_addr_not_equal(header->ether_dhost, es->es_enaddr)
                    412:        &&  ether_addr_not_equal(header->ether_dhost, etherbroadcastaddr) ) {
                    413:                printf("le: LANCE Rev C Extra Byte(s) bug; Packet punted\n");
                    414:                length = 0;
                    415:                /* Don't return directly; restore the buffer first */
                    416:        }
                    417: #endif LANCEBUG
                    418: 
                    419: #ifdef DEBUG2
                    420:        if( header->ether_dhost.ether_addr_octet[0] == 0xff )
                    421:                printf("Broadcast packet\n");
                    422:        else    printf("recv np_blkno %x\n",
                    423:                        ((struct ndpack *)(buf+14))->np_blkno);
                    424: #endif
                    425:        
                    426:        /* Copy packet to user's buffer */
                    427:        if ( length > 0 )
                    428:                bcopy((caddr_t)header, buf, length);
                    429: 
                    430: restorebuf:
                    431:        rmd->lmd_mcnt = 0;
                    432:        rmd->lmd_flags = LMD_OWN;
                    433: 
                    434:        /* Get ready to use the other buffer next time */
                    435:        /* What about errors ? */
                    436:        es->es_next_rmd = 1 - es->es_next_rmd;
                    437: 
                    438:        return (length);
                    439: }
                    440: 
                    441: /*
                    442:  * Close down Lance Ethernet device.
                    443:  * On the Model 25, we reset the chip and take it off the wire, since
                    444:  * it is sharing main memory with us (occasionally reading and writing),
                    445:  * and most programs don't know how to deal with that -- they just assume
                    446:  * that main memory is theirs to play with.
                    447:  */
                    448: lanceclose(sip)
                    449:        struct saioreq *sip;
                    450: {
                    451:        struct lance_softc *es = (struct lance_softc *) sip->si_devdata;
                    452:        struct le_device *le = es->es_lance;
                    453: 
                    454:        /* Reset the chip */
                    455:        le->le_rap = LE_CSR0;
                    456:        le->le_csr = LE_STOP;
                    457: }

unix.superglobalmegacorp.com

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