|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.