Annotation of Net2/arch/i386/netboot/ne2100.c, revision 1.1.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.