Annotation of researchv9/sys/boot/stand/if_le.c, revision 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.