Annotation of Net2/arch/i386/netboot/ne2100.c, revision 1.1

1.1     ! root        1: /* netboot
        !             2:  *
        !             3:  * ne2100.c,v
        !             4:  * Revision 1.1  1993/07/08  16:04:05  brezak
        !             5:  * Diskless boot prom code from Jim McKim ([email protected])
        !             6:  *
        !             7:  * Revision 1.1.1.1  1993/05/28  11:41:07  mckim
        !             8:  * Initial version.
        !             9:  *
        !            10:  *
        !            11:  * source in this file came from
        !            12:  * the Mach ethernet boot written by Leendert van Doorn.
        !            13:  *
        !            14:  * A very simple network driver for NE2100 boards that polls.
        !            15:  *
        !            16:  * Copyright (c) 1992 by Leendert van Doorn
        !            17:  */
        !            18: 
        !            19: #include "assert.h"
        !            20: #include "nbtypes.h"
        !            21: #include "packet.h"
        !            22: #include "ether.h"
        !            23: #include "lance.h"
        !            24: #include "proto.h"
        !            25: 
        !            26: /* configurable parameters */
        !            27: #define        NE_BASEREG      0x300           /* base register */
        !            28: #define        NE_DMACHANNEL   5               /* DMA channel */
        !            29: 
        !            30: /* Lance register offsets */
        !            31: #define LA_CSR          (NE_BASEREG+0x10)
        !            32: #define LA_CSR1         (NE_BASEREG+0x10)
        !            33: #define LA_CSR2         (NE_BASEREG+0x10)
        !            34: #define LA_CSR3         (NE_BASEREG+0x10)
        !            35: #define LA_RAP          (NE_BASEREG+0x12)
        !            36: 
        !            37: /*
        !            38:  * Some driver specific constants.
        !            39:  * Take care when tuning, this program only has 32 Kb
        !            40:  */
        !            41: #define        LANCEBUFSIZE    1518            /* plus 4 CRC bytes */
        !            42: #define        MAXLOOP         1000000L        /* arbitrary retry limit */
        !            43: #define        LOG2NRCVRING    2               /* log2(NRCVRING) */
        !            44: #define        NRCVRING        (1 << LOG2NRCVRING)
        !            45: 
        !            46: u_char eth_myaddr[ETH_ADDRSIZE];
        !            47: 
        !            48: static int next_rmd;                   /* next receive element */
        !            49: static initblock_t *initblock;         /* initialization block */
        !            50: static tmde_t *tmd;                    /* transmit ring */
        !            51: static rmde_t *rmd;                    /* receive ring */
        !            52: static char rbuffer[NRCVRING][LANCEBUFSIZE]; /* receive buffers */
        !            53: 
        !            54: static char *top = (char *)RAMSIZE;
        !            55: static char last;
        !            56: 
        !            57: static char *
        !            58: aalloc(size, align)
        !            59:      int size, align;
        !            60: {
        !            61:   register char *p;
        !            62:   register int mask;
        !            63: 
        !            64:   if (align == 0)
        !            65:     align = sizeof(int);
        !            66:   mask = align - 1;
        !            67:   assert((align & mask) == 0);
        !            68:   top = top - (size + align);
        !            69:   p = (char *)((int)top & ~mask);
        !            70:   assert(p > &last);
        !            71:   assert(p <= (char *) RAMSIZE);
        !            72:   return top = p;
        !            73: }
        !            74: 
        !            75: /*
        !            76:  * Program DMA channel 'chan' for cascade mode
        !            77:  */
        !            78: static void
        !            79: dma_cascade(chan)
        !            80:     int chan;
        !            81: {
        !            82:     assert(chan >= 0);
        !            83:     assert(chan <= 7);
        !            84:     if (chan >= 0 && chan <= 3) {
        !            85:        outb(0x0B, 0xC0 | (chan & 03));
        !            86:        outb(0x0A, chan & 03);
        !            87:     } else {
        !            88:        outb(0xD6, 0xC0 | ((chan - 4) & 03));
        !            89:        outb(0xD4, (chan - 4) & 03);
        !            90:     }
        !            91: }
        !            92: 
        !            93: /*
        !            94:  * Reset ethernet board (i.e. after a timeout)
        !            95:  */
        !            96: void
        !            97: EtherReset(void) {
        !            98:     long l;
        !            99:     u_long addr;
        !           100:     int i;
        !           101: 
        !           102:     /* program DMA chip */
        !           103:     dma_cascade(NE_DMACHANNEL);
        !           104: 
        !           105:     /* stop the chip, and make sure it did */
        !           106:     outw(LA_RAP, RDP_CSR0);
        !           107:     outw(LA_CSR, CSR_STOP);
        !           108:     for (l = 0; (inw(LA_CSR) & CSR_STOP) == 0; l++) {
        !           109:        if (l >= MAXLOOP) {
        !           110:            printf("Lance failed to stop\n");
        !           111:            return;
        !           112:        }
        !           113:     }
        !           114: 
        !           115:     /* fill lance initialization block */
        !           116:     bzero(initblock, sizeof(initblock_t));
        !           117: 
        !           118:     /* set my ethernet address */
        !           119:     initblock->ib_padr[0] = eth_myaddr[0];
        !           120:     initblock->ib_padr[1] = eth_myaddr[1];
        !           121:     initblock->ib_padr[2] = eth_myaddr[2];
        !           122:     initblock->ib_padr[3] = eth_myaddr[3];
        !           123:     initblock->ib_padr[4] = eth_myaddr[4];
        !           124:     initblock->ib_padr[5] = eth_myaddr[5];
        !           125: 
        !           126:     /* receive ring pointer */
        !           127:     addr = LA(rmd);
        !           128:     initblock->ib_rdralow = (u_short)addr;
        !           129:     initblock->ib_rdrahigh = (u_char)(addr >> 16);
        !           130:     initblock->ib_rlen = LOG2NRCVRING << 5;
        !           131: 
        !           132:     /* transmit ring with one element */
        !           133:     addr = LA(tmd);
        !           134:     initblock->ib_tdralow = (u_short)addr;
        !           135:     initblock->ib_tdrahigh = (u_char)(addr >> 16);
        !           136:     initblock->ib_tlen = 0 << 5;
        !           137: 
        !           138:     /* setup the receive ring entries */
        !           139:     for (next_rmd = 0, i = 0; i < NRCVRING; i++) {
        !           140:        addr = LA(&rbuffer[i]);
        !           141:        rmd[i].rmd_ladr = (u_short)addr;
        !           142:        rmd[i].rmd_hadr = (u_char)(addr >> 16);
        !           143:        rmd[i].rmd_mcnt = 0;
        !           144:        rmd[i].rmd_bcnt = -LANCEBUFSIZE;
        !           145:        rmd[i].rmd_flags = RMD_OWN;
        !           146:     }
        !           147: 
        !           148:     /* zero transmit ring */
        !           149:     bzero(tmd, sizeof(tmde_t));
        !           150: 
        !           151:     /* give lance the init block */
        !           152:     addr = LA(initblock);
        !           153:     outw(LA_RAP, RDP_CSR1);
        !           154:     outw(LA_CSR1, (u_short)addr);
        !           155:     outw(LA_RAP, RDP_CSR2);
        !           156:     outw(LA_CSR2, (char)(addr >> 16));
        !           157:     outw(LA_RAP, RDP_CSR3);
        !           158:     outw(LA_CSR3, 0);
        !           159: 
        !           160:     /* and initialize it */
        !           161:     outw(LA_RAP, RDP_CSR0);
        !           162:     outw(LA_CSR, CSR_INIT|CSR_STRT);
        !           163: 
        !           164:     /* wait for the lance to complete initialization and fire it up */
        !           165:     for (l = 0; (inw(LA_CSR) & CSR_IDON) == 0; l++) {
        !           166:        if (l >= MAXLOOP) {
        !           167:            printf("Lance failed to initialize\n");
        !           168:            break;
        !           169:        }
        !           170:     }
        !           171:     for (l=0; (inw(LA_CSR)&(CSR_TXON|CSR_RXON))!=(CSR_TXON|CSR_RXON); l++) {
        !           172:        if (l >= MAXLOOP) {
        !           173:            printf("Lance not started\n");
        !           174:            break;
        !           175:        }
        !           176:     }
        !           177: }
        !           178: 
        !           179: /*
        !           180:  * Get ethernet address and compute checksum to be sure
        !           181:  * that there is a board at this address.
        !           182:  */
        !           183: int
        !           184: EtherInit()
        !           185: {
        !           186:     u_short checksum, sum;
        !           187:     int i;
        !           188: 
        !           189:     for (i = 0; i < 6; i++)
        !           190:        eth_myaddr[i] = inb(NE_BASEREG + i);
        !           191: 
        !           192:     sum = 0;
        !           193:     for (i = 0x00; i <= 0x0B; i++)
        !           194:        sum += inb(NE_BASEREG + i);
        !           195:     for (i = 0x0E; i <= 0xF; i++)
        !           196:        sum += inb(NE_BASEREG + i);
        !           197:     checksum = inb(NE_BASEREG + 0x0C) | (inb(NE_BASEREG + 0x0D) << 8);
        !           198:     if (sum != checksum)
        !           199:        return 0;
        !           200: 
        !           201:     /* initblock, tmd, and rmd should be 8 byte aligned ! */
        !           202:     initblock = (initblock_t *) aalloc(sizeof(initblock_t), 8);
        !           203:     tmd = (tmde_t *) aalloc(sizeof(tmde_t), 8);
        !           204:     rmd = (rmde_t *) aalloc(NRCVRING * sizeof(rmde_t), 8);
        !           205:     EtherReset();
        !           206:     return 1;
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * Disable DMA for channel 'chan'
        !           211:  */
        !           212: static void
        !           213: dma_done(chan)
        !           214:     int chan;
        !           215: {
        !           216:     assert(chan >= 0);
        !           217:     assert(chan <= 7);
        !           218:     if (chan >= 0 && chan <= 3)
        !           219:        outb(0x0A, 0x04 | (chan & 03));
        !           220:     else
        !           221:        outb(0xD4, 0x04 | ((chan - 4 ) & 03));
        !           222: }
        !           223: 
        !           224: /*
        !           225:  * Stop ethernet board
        !           226:  */
        !           227: void
        !           228: EtherStop()
        !           229: {
        !           230:     long l;
        !           231: 
        !           232:     /* stop chip and disable DMA access */
        !           233:     outw(LA_RAP, RDP_CSR0);
        !           234:     outw(LA_CSR, CSR_STOP);
        !           235:     for (l = 0; (inw(LA_CSR) & CSR_STOP) == 0; l++) {
        !           236:        if (l >= MAXLOOP) {
        !           237:            printf("Lance failed to stop\n");
        !           238:            break;
        !           239:        }
        !           240:     }
        !           241:     dma_done(NE_DMACHANNEL);
        !           242: }
        !           243: 
        !           244: /*
        !           245:  * Send an ethernet packet to destination 'dest'
        !           246:  */
        !           247: void
        !           248: EtherSend(pkt, proto, dest)
        !           249:     packet_t *pkt;
        !           250:     u_short proto;
        !           251:     u_char *dest;
        !           252: {
        !           253:     ethhdr_t *ep;
        !           254:     long l;
        !           255:     u_long addr;
        !           256:     u_short csr;
        !           257: 
        !           258:     /* add ethernet header and fill in source & destination */
        !           259:     pkt->pkt_len += sizeof(ethhdr_t);
        !           260:     pkt->pkt_offset -= sizeof(ethhdr_t);
        !           261:     ep = (ethhdr_t *) pkt->pkt_offset;
        !           262:     ep->eth_proto = htons(proto);
        !           263:     bcopy(dest, ep->eth_dst, ETH_ADDRSIZE);
        !           264:     bcopy(eth_myaddr, ep->eth_src, ETH_ADDRSIZE);
        !           265:     if (pkt->pkt_len < 60)
        !           266:        pkt->pkt_len = 60;
        !           267:     assert(pkt->pkt_len <= 1514);
        !           268: 
        !           269:     /* set up transmit ring element */
        !           270:     assert((tmd->tmd_flags & TMD_OWN) == 0);
        !           271:     addr = LA(pkt->pkt_offset);
        !           272:     assert((addr & 1) == 0);
        !           273:     tmd->tmd_ladr = (u_short)addr;
        !           274:     tmd->tmd_hadr = (u_char)(addr >> 16);
        !           275:     tmd->tmd_bcnt = -pkt->pkt_len;
        !           276:     tmd->tmd_err = 0;
        !           277:     tmd->tmd_flags = TMD_OWN|TMD_STP|TMD_ENP;
        !           278: 
        !           279:     /* start transmission */
        !           280:     outw(LA_CSR, CSR_TDMD);
        !           281: 
        !           282:     /* wait for interrupt and acknowledge it */
        !           283:     for (l = 0; l < MAXLOOP; l++) {
        !           284:        if ((csr = inw(LA_CSR)) & CSR_TINT) {
        !           285:            outw(LA_CSR, CSR_TINT);
        !           286:            break;
        !           287:        }
        !           288:     }
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * Poll the LANCE just see if there's an Ethernet packet
        !           293:  * available. If there is, its contents is returned in a
        !           294:  * pkt structure, otherwise a nil pointer is returned.
        !           295:  */
        !           296: packet_t *
        !           297: EtherReceive(void) {
        !           298:     packet_t *pkt;
        !           299:     rmde_t *rp;
        !           300:     u_long addr;
        !           301:     u_short csr;
        !           302: 
        !           303:     pkt = (packet_t *)0;
        !           304:     if ((csr = inw(LA_CSR)) & CSR_RINT) {
        !           305:        outw(LA_CSR, CSR_RINT);
        !           306:        assert(next_rmd >= 0);
        !           307:        assert(next_rmd <= NRCVRING);
        !           308:        rp = &rmd[next_rmd];
        !           309:        if ((rp->rmd_flags & ~RMD_OFLO) == (RMD_STP|RMD_ENP)) {
        !           310:            pkt = PktAlloc(0);
        !           311:            pkt->pkt_len = rp->rmd_mcnt - 4;
        !           312:            assert(pkt->pkt_len >= 0);
        !           313:            assert(pkt->pkt_len < PKT_DATASIZE);
        !           314:            bcopy(rbuffer[next_rmd], pkt->pkt_offset, pkt->pkt_len);
        !           315:            /* give packet back to the lance */
        !           316:            rp->rmd_bcnt = -LANCEBUFSIZE;
        !           317:            rp->rmd_mcnt = 0;
        !           318:            rp->rmd_flags = RMD_OWN;
        !           319:        }
        !           320:        next_rmd = (next_rmd + 1) & (NRCVRING - 1);
        !           321:     }
        !           322:     return pkt;
        !           323: }
        !           324: 
        !           325: /*
        !           326:  * Print an ethernet address in human readable form
        !           327:  */
        !           328: void
        !           329: EtherPrintAddr(addr)
        !           330:     u_char *addr;
        !           331: {
        !           332:     printf("%x:%x:%x:%x:%x:%x",
        !           333:        addr[0] & 0xFF, addr[1] & 0xFF, addr[2] & 0xFF,
        !           334:        addr[3] & 0xFF, addr[4] & 0xFF, addr[5] & 0xFF);
        !           335: }

unix.superglobalmegacorp.com

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