|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993-1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: lance.c ! 28: * Author: Robert V. Baron & Alessandro Forin ! 29: * Date: 5/90 ! 30: * ! 31: * Driver for the DEC LANCE Ethernet Controller. ! 32: */ ! 33: ! 34: /* ! 35: ! 36: Byte ordering issues. ! 37: ! 38: The lance sees data naturally as half word (16 bit) quantitites. ! 39: Bit 2 (BSWP) in control register 3 (CSR3) controls byte swapping. ! 40: To quote the spec: ! 41: ! 42: 02 BSWP BYTE SWAP allows the chip to ! 43: operate in systems that consdier bits (15:08) of data pointers ! 44: by an even addressa and bits (7:0) to be pointed by an ! 45: odd address. ! 46: ! 47: When BSWP=1, the chip will swap the high and low bytes on DMA ! 48: data transfers between the silo and bus memory. Only data from ! 49: silo transfers is swapped; the Initialization Block data and ! 50: the Descriptor Ring entries are NOT swapped. (emphasis theirs) ! 51: ! 52: ! 53: So on systems with BYTE_MSF=1, the BSWP bit should be set. Note, ! 54: however, that all shorts in the descriptor ring and initialization ! 55: block need to be swapped. The BITFIELD macros in lance.h handle this ! 56: magic. ! 57: ! 58: */ ! 59: ! 60: #include <ln.h> ! 61: #if NLN > 0 ! 62: #include <platforms.h> ! 63: ! 64: /* ! 65: * AMD Am7990 LANCE (Ethernet Interface) ! 66: */ ! 67: #include <sys/ioctl.h> ! 68: #include <vm/vm_kern.h> ! 69: ! 70: #include <machine/machspl.h> /* spl definitions */ ! 71: #include <kern/time_out.h> ! 72: #include <sys/syslog.h> ! 73: #include <ipc/ipc_port.h> ! 74: #include <ipc/ipc_kmsg.h> ! 75: ! 76: #include <device/device_types.h> ! 77: #include <device/errno.h> ! 78: #include <device/io_req.h> ! 79: #include <device/if_hdr.h> ! 80: #include <device/if_ether.h> ! 81: #include <device/net_status.h> ! 82: #include <device/net_io.h> ! 83: ! 84: #ifdef FLAMINGO ! 85: #define se_reg_type unsigned int ! 86: #endif ! 87: ! 88: #include <chips/lance.h> ! 89: #include <chips/busses.h> ! 90: ! 91: #define private static ! 92: #define public ! 93: ! 94: typedef struct se_softc *se_softc_t; /* move above prototypes */ ! 95: ! 96: void se_write_reg(); /* forwards */ ! 97: void se_read(); ! 98: void se_rint(); ! 99: void se_tint(); ! 100: ! 101: private vm_offset_t se_Hmem_nogap(), se_Hmem_gap16(); ! 102: private vm_offset_t se_malloc(); ! 103: ! 104: ! 105: /* This config section should go into a separate file */ ! 106: ! 107: #ifdef LUNA88K ! 108: # include <luna88k/board.h> ! 109: # define MAPPED 1 ! 110: #undef bcopy ! 111: extern void bcopy(), bzero(); ! 112: ! 113: #define wbflush() ! 114: #define Hmem(lna) (vm_offset_t)((lna) + sc->lnbuf) ! 115: #define Lmem(lna) (vm_offset_t)((lna) + sc->lnoffset) ! 116: ! 117: #define SPACE (TRI_PORT_RAM_SPACE>>1) ! 118: private struct se_switch se_switch[] = { ! 119: { LANCE_ADDR - TRI_PORT_RAM, /* pointer */ ! 120: SPACE /* host side */, ! 121: SPACE /* lance side */, ! 122: - TRI_PORT_RAM, ! 123: 0, /* romstride */ ! 124: 0, /* ramstride */ ! 125: SPACE, ! 126: /* desc_copyin */ bcopy, ! 127: /* desc_copyout */ bcopy, ! 128: /* data_copyin */ bcopy, ! 129: /* data_copyout */ bcopy, ! 130: /* bzero */ bzero, ! 131: /* mapaddr */ se_Hmem_nogap, ! 132: /* mapoffs */ se_Hmem_nogap ! 133: }, ! 134: }; ! 135: ! 136: #endif ! 137: ! 138: #ifdef DECSTATION ! 139: #include <mips/mips_cpu.h> ! 140: #include <mips/PMAX/pmad_aa.h> ! 141: ! 142: #define MAPPED 1 ! 143: ! 144: /* ! 145: * The LANCE buffer memory as seen from the Pmax cpu is funny. ! 146: * It is viewed as short words (16bits), spaced at word (32bits) ! 147: * intervals. The same applies to the registers. From the LANCE ! 148: * point of view memory is instead contiguous. ! 149: * The ROM that contains the station address is in the space belonging ! 150: * to the clock/battery backup memory. This space is again 16 bits ! 151: * in a 32bit envelope. And the ether address is stored in the "high" ! 152: * byte of 6 consecutive quantities. ! 153: * ! 154: * But Pmaxen and 3maxen (and..) map lance space differently. ! 155: * This requires dynamic adaptation of the driver, which ! 156: * is done via the following switches. ! 157: * For convenience, the switch holds information about ! 158: * the location of the lance control registers as well. ! 159: * This could be either absolute (pmax) or relative to ! 160: * some register base (3max, turbochannel) ! 161: */ ! 162: void copyin_gap16(), copyout_gap16(), bzero_gap16(); ! 163: extern void bcopy(), bzero(); ! 164: void copyin_gap32(), copyout_gap32(); ! 165: ! 166: private struct se_switch se_switch[] = { ! 167: /* pmax */ ! 168: { 0x00000000, 0x01000000, 0x0, 0x05000000, 8, 16, 64*1024, ! 169: copyin_gap16, copyout_gap16, copyin_gap16, copyout_gap16, ! 170: bzero_gap16, se_Hmem_gap16, se_Hmem_gap16}, ! 171: /* 3max */ ! 172: { PMAD_OFFSET_LANCE, PMAD_OFFSET_RAM, PMAD_OFFSET_RAM, PMAD_OFFSET_ROM, ! 173: 16, 0, PMAD_RAM_SIZE, ! 174: bcopy, bcopy, bcopy, bcopy, bzero, se_Hmem_nogap, se_Hmem_nogap}, ! 175: /* 3min */ ! 176: /* XXX re-use other 64k */ ! 177: { 0/*later*/, 0/*later*/, 0x0, 0/*later*/, 0, 128, 64*1024, ! 178: copyin_gap16, copyout_gap16, copyin_gap32, copyout_gap32, ! 179: bzero_gap16, se_Hmem_gap16, se_Hmem_nogap}, ! 180: }; ! 181: ! 182: /* ! 183: * "lna" is what se_malloc hands back. They are offsets using ! 184: * the sizing that the Lance would use. The Lance space is ! 185: * mapped somewhere in the I/O space, as indicated by the softc. ! 186: * Hence we have these two macros: ! 187: */ ! 188: /* H & L are not hi and lo but ! 189: H = HOST == addresses for host to reference board memory ! 190: L = LOCAL == addresses on board ! 191: */ ! 192: #define Hmem(lna) (vm_offset_t)((se_sw->mapaddr)(lna) + sc->lnbuf) ! 193: #define Lmem(lna) (vm_offset_t)((vm_offset_t)lna + sc->lnoffset) ! 194: #endif /*DECSTATION*/ ! 195: ! 196: ! 197: #ifdef VAXSTATION ! 198: #include <vax/ka3100.h> ! 199: ! 200: #define wbflush() ! 201: ! 202: void xzero(x, l) vm_offset_t x; int l; { blkclr(x, l); } ! 203: void xcopy(f, t, l) vm_offset_t f, t; int l; { bcopy(f, t, l); } ! 204: ! 205: private struct se_switch se_switch[] = { ! 206: /* pvax sees contiguous bits in lower 16Meg of memory */ ! 207: { 0, 0, 0, 0, 0, 0, 64*1024, ! 208: xcopy, xcopy, xcopy, xcopy, xzero, se_Hmem_nogap, se_Hmem_nogap}, ! 209: }; ! 210: ! 211: /* ! 212: * "lna" is what se_malloc hands back. They are offsets using ! 213: * the sizing that the Lance would use. The Lance space is ! 214: * mapped somewhere in the I/O space, as indicated by the softc. ! 215: * Hence we have these two macros: ! 216: */ ! 217: /* H & L are not hi and lo but ! 218: H = HOST == addresses for host to reference board memory ! 219: L = LOCAL == addresses on board ! 220: */ ! 221: /* ! 222: * This does not deal with > 16 Meg physical memory, where ! 223: * Hmem != Lmem ! 224: */ ! 225: #define Hmem(lna) (vm_offset_t)((lna) + sc->lnbuf) ! 226: #define Lmem(lna) (vm_offset_t)((lna) + sc->lnoffset) ! 227: ! 228: #endif /*VAXSTATION*/ ! 229: ! 230: ! 231: #ifdef FLAMINGO ! 232: #include <alpha/alpha_cpu.h> ! 233: ! 234: /* XXX might be wrong, mostly stolen from kmin */ ! 235: extern void copyin_gap16(), copyout_gap16(), bzero_gap16(); ! 236: extern void copyin_gap32(), copyout_gap32(); ! 237: extern void bcopy(), bzero(); ! 238: ! 239: private struct se_switch se_switch[] = { ! 240: /* XXX re-use other 64k */ ! 241: { 0/*later*/, 0/*later*/, 0x0, 0/*later*/, 0, 128, 64*1024, ! 242: copyin_gap16, copyout_gap16, copyin_gap32, copyout_gap32, ! 243: bzero_gap16, se_Hmem_gap16, se_Hmem_nogap}, ! 244: }; ! 245: ! 246: /* ! 247: * "lna" is what se_malloc hands back. They are offsets using ! 248: * the sizing that the Lance would use. The Lance space is ! 249: * mapped somewhere in the I/O space, as indicated by the softc. ! 250: * Hence we have these two macros: ! 251: */ ! 252: /* H & L are not hi and lo but ! 253: H = HOST == addresses for host to reference board memory ! 254: L = LOCAL == addresses on board ! 255: */ ! 256: #define Hmem(lna) (vm_offset_t)((se_sw->mapaddr)(lna) + sc->lnbuf) ! 257: #define Lmem(lna) (vm_offset_t)((vm_offset_t)lna + sc->lnoffset) ! 258: #endif /*FLAMINGO*/ ! 259: ! 260: ! 261: /* ! 262: * Map a lance-space offset into an host-space one ! 263: */ ! 264: private vm_offset_t se_Hmem_nogap( vm_offset_t lna) { return lna;} ! 265: private vm_offset_t se_Hmem_gap16( vm_offset_t lna) { return lna << 1;} ! 266: ! 267: /* ! 268: * Memory addresses for LANCE are 24 bits wide. ! 269: */ ! 270: #define Addr_lo(y) ((unsigned short)((vm_offset_t)(y) & 0xffff)) ! 271: #define Addr_hi(y) ((unsigned short)(((vm_offset_t)(y)>>16) & 0xff)) ! 272: ! 273: #define LN_MEMORY_SIZE (se_sw->ramsize) ! 274: ! 275: /* XXX to accomodate heterogeneity this should be made per-drive */ ! 276: /* XXX and then some more */ ! 277: ! 278: struct se_switch *se_sw = se_switch; ! 279: ! 280: void set_se_switch(n) ! 281: int n; ! 282: { ! 283: se_sw = &se_switch[n]; ! 284: } ! 285: ! 286: #ifndef LUNA88K ! 287: void setse_switch(n, r, b, l, o) ! 288: vm_offset_t r, b, l, o; ! 289: int n; ! 290: { ! 291: se_switch[n].regspace = r; ! 292: se_switch[n].bufspace = b; ! 293: se_switch[n].ln_bufspace = l; ! 294: se_switch[n].romspace = o; ! 295: ! 296: /* make sure longword aligned */ ! 297: if (se_switch[n].bufspace & 0x7) { ! 298: se_switch[n].bufspace = (se_switch[n].bufspace+0x7) & ~0x7; ! 299: } ! 300: ! 301: set_se_switch(n); ! 302: } ! 303: #endif ! 304: ! 305: /* ! 306: * Autoconf info ! 307: */ ! 308: ! 309: private vm_offset_t se_std[NLN] = { 0 }; ! 310: private struct bus_device *se_info[NLN]; ! 311: private int se_probe(); ! 312: private void se_attach(); ! 313: ! 314: struct bus_driver se_driver = ! 315: { se_probe, 0, se_attach, 0, se_std, "se", se_info, }; ! 316: ! 317: /* ! 318: * Externally visible functions ! 319: */ ! 320: char *se_unprobed_addr = 0; ! 321: void se_intr(); /* kernel */ ! 322: ! 323: int se_open(), se_output(), se_get_status(), /* user */ ! 324: se_set_status(), se_setinput(), se_restart(); ! 325: ! 326: /* ! 327: * ! 328: * Internal functions & definitions ! 329: * ! 330: */ ! 331: ! 332: private int se_probe(); ! 333: private void se_init(); ! 334: private void init_lance_space(); ! 335: private void se_desc_set_status(); ! 336: private volatile long *se_desc_alloc(); /* must be aligned! */ ! 337: void se_start(); ! 338: private void copy_from_lance(); ! 339: private int copy_to_lance(); ! 340: ! 341: int se_verbose = 0; /* debug flag */ ! 342: ! 343: #define RLOG 4 /* 2**4 = 16 receive descriptors */ ! 344: #define TLOG 4 /* 2**4 = 16 transmit descriptors */ ! 345: #define NRCV (1<<RLOG) /* Receive descriptors */ ! 346: #define NXMT (1<<TLOG) /* Transmit descriptors */ ! 347: ! 348: #define LN_BUFFER_SIZE (0x800-0x80) ! 349: ! 350: /* ! 351: * Ethernet software status per interface. ! 352: * ! 353: * Each interface is referenced by a network interface structure, ! 354: * is_if, which contains the output queue for the interface, its address, ... ! 355: */ ! 356: int se_loopback_hack = 1; ! 357: ! 358: struct se_softc { ! 359: struct ifnet is_if; /* generic interface header */ ! 360: unsigned char is_addr[6]; /* ethernet hardware address */ ! 361: unsigned short pad; ! 362: se_reg_t lnregs; /* Lance registers */ ! 363: vm_offset_t lnbuf; /* Lance memory, Host offset */ ! 364: vm_offset_t lnoffset; /* Lance memory, Lance offset */ ! 365: vm_offset_t lnrom; ! 366: vm_offset_t lnsbrk; /* Lance memory allocator */ ! 367: vm_offset_t lninit_block; /* Init block address */ ! 368: se_desc_t lnrring[NRCV]; /* Receive ring desc. */ ! 369: volatile long *lnrbuf[NRCV]; /* Receive buffers */ ! 370: se_desc_t lntring[NXMT]; /* Transmit ring desc. */ ! 371: volatile long *lntbuf[NXMT]; /* Transmit buffers */ ! 372: ! 373: int rcv_last; /* Rcv buffer last read */ ! 374: ! 375: io_req_t tpkt[NXMT+1]; /* Xmt pkt queue */ ! 376: int xmt_count; /* Xmt queue size */ ! 377: int xmt_last; /* Xmt queue head (insert) */ ! 378: int xmt_complete; /* Xmt queue tail (remove) */ ! 379: ! 380: int se_flags; /* Flags for SIOCSIFFLAGS */ ! 381: int counters[4]; /* error counters */ ! 382: #define bablcnt counters[0] ! 383: #define misscnt counters[1] ! 384: #define merrcnt counters[2] ! 385: #define rstrtcnt counters[3] ! 386: } se_softc_data[NLN]; ! 387: ! 388: se_softc_t se_softc[NLN]; /* quick access */ ! 389: ! 390: /* ! 391: * Probe the Lance to see if it's there ! 392: */ ! 393: private int se_open_state = 0; ! 394: ! 395: private int se_probe( ! 396: vm_offset_t reg, ! 397: register struct bus_device *ui) ! 398: { ! 399: register se_softc_t sc; ! 400: se_reg_t rdp, rap; ! 401: int unit = ui->unit; ! 402: ! 403: /* ! 404: * See if the interface is there by reading the lance CSR. On pmaxen ! 405: * and 3maxen this is superfluous, but.. ! 406: */ ! 407: rdp = (se_reg_t) (reg + se_sw->regspace); ! 408: #ifdef DECSTATION ! 409: if (check_memory(rdp, 0)) ! 410: return 0; ! 411: #endif /*DECSTATION*/ ! 412: #ifdef MAPPED ! 413: SE_probe(reg,ui); ! 414: #endif /*MAPPED*/ ! 415: rap = rdp + 2; /* XXX might not be true in the future XXX */ ! 416: /* rdp and rap are "shorts" on consecutive ! 417: "long" word boundaries */ ! 418: ! 419: /* ! 420: * Bind this interface to the softc. ! 421: */ ! 422: sc = &se_softc_data[unit]; ! 423: se_softc[unit] = sc; ! 424: sc->lnregs = (se_reg_t) (reg + se_sw->regspace); ! 425: sc->lnbuf = (vm_offset_t) (reg + se_sw->bufspace); ! 426: sc->lnoffset = (vm_offset_t) (se_sw->ln_bufspace); ! 427: sc->lnrom = (vm_offset_t) (reg + se_sw->romspace); ! 428: ! 429: /* ! 430: * Reset the interface, and make sure we really do it! (the 3max ! 431: * seems quite stubborn about these registers) ! 432: */ ! 433: se_write_reg(rap, CSR0_SELECT, CSR0_SELECT, "RAP"); ! 434: se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); ! 435: ! 436: /* ! 437: * Allocate lance RAM buffer memory ! 438: */ ! 439: init_lance_space(sc); ! 440: ! 441: /* ! 442: * Initialize the chip ! 443: * ! 444: * NOTE: From now on we will only touch csr0 ! 445: */ ! 446: if (se_ship_init_block(sc, unit)) ! 447: return 0; ! 448: ! 449: /* ! 450: * Tell the world we are alive and well ! 451: */ ! 452: se_open_state++; ! 453: return 1; ! 454: } ! 455: ! 456: int se_ship_init_block( ! 457: register se_softc_t sc, ! 458: int unit) ! 459: { ! 460: se_reg_t rdp = sc->lnregs; ! 461: se_reg_t rap; ! 462: register int i = 0; ! 463: ! 464: rap = rdp + 2; /* XXX might not be true in the future XXX */ ! 465: ! 466: /* ! 467: * Load LANCE control block. ! 468: */ ! 469: ! 470: #ifdef LUNA88K ! 471: /* turn on byte swap bit in csr3, set bcon bit - as in 2.5 */ ! 472: se_write_reg(rap, CSR3_SELECT, CSR3_SELECT, "RAP"); ! 473: se_write_reg(rdp, LN_CSR3_BSWP|LN_CSR3_BCON, ! 474: LN_CSR3_BSWP|LN_CSR3_BCON, "csr3"); ! 475: #endif ! 476: ! 477: se_write_reg(rap, CSR1_SELECT, CSR1_SELECT, "RAP"); ! 478: se_write_reg(rdp, Addr_lo(Lmem(sc->lninit_block)), ! 479: Addr_lo(Lmem(sc->lninit_block)), "csr1"); ! 480: ! 481: se_write_reg(rap, CSR2_SELECT, CSR2_SELECT, "RAP"); ! 482: se_write_reg(rdp, Addr_hi(Lmem(sc->lninit_block)), ! 483: Addr_hi(Lmem(sc->lninit_block)), "csr2"); ! 484: ! 485: /* ! 486: * Start the INIT sequence now ! 487: */ ! 488: se_write_reg(rap, CSR0_SELECT, CSR0_SELECT, "RAP"); ! 489: *rdp = (LN_CSR0_IDON | LN_CSR0_INIT); ! 490: wbflush(); ! 491: ! 492: /* give it plenty of time to settle */ ! 493: while (i++ < 10000) { ! 494: delay(100); ! 495: if ((*rdp & LN_CSR0_IDON) != 0) ! 496: break; ! 497: } ! 498: /* make sure got out okay */ ! 499: if ((*rdp & LN_CSR0_IDON) == 0) { ! 500: printf("se%d: cannot initialize\n", unit); ! 501: if (*rdp & LN_CSR0_ERR) ! 502: printf("se%d: initialization error, csr = %04x\n", ! 503: unit, (*rdp & 0xffff)); ! 504: return 1; ! 505: } ! 506: /* ! 507: * Do not enable interrupts just yet. ! 508: */ ! 509: /* se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); */ ! 510: ! 511: return 0; ! 512: } ! 513: ! 514: void ! 515: se_write_reg( ! 516: register se_reg_t regptr, ! 517: register int val, ! 518: register int result, ! 519: char *regname) ! 520: { ! 521: register int i = 0; ! 522: ! 523: while ((unsigned short)(*regptr) != (unsigned short)result) { ! 524: *regptr = (se_reg_type)val; ! 525: wbflush(); ! 526: if (++i > 10000) { ! 527: printf("se: %s did not settle (to x%x): x%x\n", ! 528: regname, result, (unsigned short)(*regptr)); ! 529: return; ! 530: } ! 531: delay(100); ! 532: } ! 533: } ! 534: ! 535: unsigned short ! 536: se_read_reg( ! 537: register se_reg_t regptr) ! 538: { ! 539: return (unsigned short) (*regptr); ! 540: } ! 541: ! 542: private void ! 543: init_lance_space( ! 544: register se_softc_t sc) ! 545: { ! 546: register int lptr; /* Generic lance pointer */ ! 547: se_desc_t ringaddr; ! 548: long *rom_eaddress = (long *) sc->lnrom; ! 549: int i; ! 550: struct se_init_block init_block; ! 551: ! 552: /* ! 553: * Allocate local RAM buffer memory for the init block, ! 554: * fill in our local copy then copyout. ! 555: */ ! 556: ! 557: sc->lninit_block = se_malloc(sc, sizeof (struct se_init_block)); ! 558: ! 559: /* ! 560: * Set values on stack, then copyout en-masse ! 561: */ ! 562: bzero(&init_block, sizeof(init_block)); ! 563: init_block.mode = 0; ! 564: ! 565: /* byte swapping between host and lance */ ! 566: ! 567: init_block.phys_addr_low = ((rom_eaddress[0]>>se_sw->romstride)&0xff) | ! 568: (((rom_eaddress[1]>>se_sw->romstride)&0xff) << 8); ! 569: init_block.phys_addr_med = ((rom_eaddress[2]>>se_sw->romstride)&0xff) | ! 570: (((rom_eaddress[3]>>se_sw->romstride)&0xff) << 8); ! 571: init_block.phys_addr_high = ((rom_eaddress[4]>>se_sw->romstride)&0xff) | ! 572: (((rom_eaddress[5]>>se_sw->romstride)&0xff) << 8); ! 573: ! 574: /* ! 575: * Allocate both descriptor rings at once. ! 576: * Note that the quadword alignment requirement is ! 577: * inherent in the way we perform allocation, ! 578: * but it does depend on the size of the init block. ! 579: */ ! 580: lptr = se_malloc(sc, sizeof (struct se_desc) * (NXMT + NRCV)); ! 581: ! 582: /* ! 583: * Initialize the buffer descriptors ! 584: */ ! 585: init_block.recv_ring_pointer_lo = Addr_lo(Lmem(lptr)); ! 586: init_block.recv_ring_pointer_hi = Addr_hi(Lmem(lptr)); ! 587: init_block.recv_ring_len = RLOG; ! 588: ! 589: for ( i = 0; i < NRCV ; i++, lptr += sizeof(struct se_desc)) { ! 590: ringaddr = (se_desc_t)Hmem(lptr); ! 591: sc->lnrring[i] = ringaddr; ! 592: sc->lnrbuf[i] = se_desc_alloc (sc, ringaddr); ! 593: } ! 594: ! 595: init_block.xmit_ring_pointer_lo = Addr_lo(Lmem(lptr)); ! 596: init_block.xmit_ring_pointer_hi = Addr_hi(Lmem(lptr)); ! 597: init_block.xmit_ring_len = TLOG; ! 598: ! 599: for ( i = 0 ; i < NXMT ; i++, lptr += sizeof(struct se_desc)) { ! 600: ringaddr = (se_desc_t)Hmem(lptr); ! 601: sc->lntring[i] = ringaddr; ! 602: sc->lntbuf[i] = se_desc_alloc (sc, ringaddr); ! 603: } ! 604: ! 605: /* ! 606: * No logical address filtering ! 607: */ ! 608: init_block.logical_addr_filter0 = 0; ! 609: init_block.logical_addr_filter1 = 0; ! 610: init_block.logical_addr_filter2 = 0; ! 611: init_block.logical_addr_filter3 = 0; ! 612: ! 613: /* ! 614: * Move init block into lance space ! 615: */ ! 616: (se_sw->desc_copyout)((vm_offset_t)&init_block, Hmem(sc->lninit_block), sizeof(init_block)); ! 617: wbflush(); ! 618: } ! 619: ! 620: /* ! 621: * Interface exists: make available by filling in network interface ! 622: * record. System will initialize the interface when it is ready ! 623: * to accept packets. ! 624: */ ! 625: private void ! 626: se_attach( ! 627: register struct bus_device *ui) ! 628: { ! 629: unsigned char *enaddr; ! 630: struct ifnet *ifp; ! 631: long *rom_eaddress; ! 632: int unit = ui->unit; ! 633: se_softc_t sc = se_softc[unit]; ! 634: ! 635: rom_eaddress = (long *) sc->lnrom; ! 636: ! 637: /* ! 638: * Read the address from the prom and save it. ! 639: */ ! 640: enaddr = sc->is_addr; ! 641: enaddr[0] = (unsigned char) ((rom_eaddress[0] >> se_sw->romstride) & 0xff); ! 642: enaddr[1] = (unsigned char) ((rom_eaddress[1] >> se_sw->romstride) & 0xff); ! 643: enaddr[2] = (unsigned char) ((rom_eaddress[2] >> se_sw->romstride) & 0xff); ! 644: enaddr[3] = (unsigned char) ((rom_eaddress[3] >> se_sw->romstride) & 0xff); ! 645: enaddr[4] = (unsigned char) ((rom_eaddress[4] >> se_sw->romstride) & 0xff); ! 646: enaddr[5] = (unsigned char) ((rom_eaddress[5] >> se_sw->romstride) & 0xff); ! 647: ! 648: printf(": %x-%x-%x-%x-%x-%x", ! 649: (rom_eaddress[0] >> se_sw->romstride) & 0xff, ! 650: (rom_eaddress[1] >> se_sw->romstride) & 0xff, ! 651: (rom_eaddress[2] >> se_sw->romstride) & 0xff, ! 652: (rom_eaddress[3] >> se_sw->romstride) & 0xff, ! 653: (rom_eaddress[4] >> se_sw->romstride) & 0xff, ! 654: (rom_eaddress[5] >> se_sw->romstride) & 0xff); ! 655: ! 656: /* ! 657: * Initialize the standard interface descriptor ! 658: */ ! 659: ifp = &sc->is_if; ! 660: ifp->if_unit = unit; ! 661: ifp->if_header_size = sizeof(struct ether_header); ! 662: ifp->if_header_format = HDR_ETHERNET; ! 663: ifp->if_address_size = 6; ! 664: ifp->if_mtu = ETHERMTU; ! 665: ifp->if_flags |= IFF_BROADCAST; ! 666: ! 667: ifp->if_address = (char *) enaddr; ! 668: ! 669: if_init_queues(ifp); ! 670: #ifdef MAPPED ! 671: SE_attach(ui); ! 672: #endif /*MAPPED*/ ! 673: ! 674: } ! 675: ! 676: /* ! 677: * Use a different hardware address for interface ! 678: */ ! 679: void ! 680: se_setaddr( ! 681: unsigned char eaddr[6], ! 682: int unit) ! 683: { ! 684: register se_softc_t sc = se_softc[unit]; ! 685: struct se_init_block init_block; ! 686: ! 687: /* ! 688: * Modify initialization block accordingly ! 689: */ ! 690: (se_sw->desc_copyin) (Hmem(sc->lninit_block), (vm_offset_t)&init_block, sizeof(init_block)); ! 691: bcopy(eaddr, &init_block.phys_addr_low, sizeof(*eaddr)); ! 692: (se_sw->desc_copyout)((vm_offset_t)&init_block, Hmem(sc->lninit_block), sizeof(init_block)); ! 693: /* ! 694: * Make a note of it ! 695: */ ! 696: bcopy(eaddr, sc->is_addr, sizeof(*eaddr)); ! 697: ! 698: /* ! 699: * Restart the interface ! 700: */ ! 701: se_restart(&sc->is_if); ! 702: se_init(unit); ! 703: } ! 704: ! 705: /* ! 706: * Restart interface ! 707: * ! 708: * We use this internally on those errors that hang the chip, ! 709: * not sure yet what use the MI code will make of it. ! 710: * ! 711: * After stopping the chip and effectively turning off the interface ! 712: * we release all pending buffers and cause the chip to init ! 713: * itself. We do not enable interrupts here. ! 714: */ ! 715: int ! 716: se_restart( register struct ifnet *ifp ) ! 717: { ! 718: register se_softc_t sc = se_softc[ifp->if_unit]; ! 719: se_reg_t rdp; ! 720: register int i; ! 721: ! 722: rdp = sc->lnregs; ! 723: ! 724: /* ! 725: * stop the chip ! 726: */ ! 727: se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); ! 728: ! 729: /* ! 730: * stop network activity ! 731: */ ! 732: if (ifp->if_flags & IFF_RUNNING) { ! 733: ifp->if_flags &= ~(IFF_UP | IFF_RUNNING); ! 734: sc->se_flags &= ~(IFF_UP | IFF_RUNNING); ! 735: } ! 736: sc->rstrtcnt++; ! 737: ! 738: if (se_verbose) ! 739: printf("se%d: %d restarts\n", ifp->if_unit, sc->rstrtcnt); ! 740: ! 741: /* ! 742: * free up any buffers currently in use ! 743: */ ! 744: for (i = 0; i < NXMT; i++) ! 745: if (sc->tpkt[i]) { ! 746: iodone(sc->tpkt[i]); ! 747: sc->tpkt[i] = (io_req_t) 0; ! 748: } ! 749: /* ! 750: * INIT the chip again, no need to reload init block address. ! 751: */ ! 752: se_ship_init_block(sc, ifp->if_unit); ! 753: ! 754: return (0); ! 755: } ! 756: ! 757: /* ! 758: * Initialize the interface. ! 759: */ ! 760: private void ! 761: se_init( int unit ) ! 762: { ! 763: register se_softc_t sc = se_softc[unit]; ! 764: register se_desc_t *rp; ! 765: register struct ifnet *ifp = &sc->is_if; ! 766: se_reg_t rdp; ! 767: short mode; ! 768: spl_t s; ! 769: int i; ! 770: ! 771: if (ifp->if_flags & IFF_RUNNING) ! 772: return; ! 773: ! 774: rdp = sc->lnregs; ! 775: ! 776: /* ! 777: * Init the buffer descriptors and indexes for each of the rings. ! 778: */ ! 779: for (i = 0, rp = sc->lnrring; i < NRCV; i++, rp++) ! 780: se_desc_set_status(*rp, LN_RSTATE_OWN); ! 781: ! 782: for (i = 0, rp = sc->lntring; i < NXMT; i++, rp++) ! 783: se_desc_set_status(*rp, 0); ! 784: ! 785: sc->xmt_count = sc->xmt_complete = sc->xmt_last = sc->rcv_last = 0; ! 786: ! 787: /* ! 788: * Deal with loopback mode operation ! 789: */ ! 790: s = splimp(); ! 791: ! 792: (se_sw->desc_copyin) (Hmem(sc->lninit_block), (vm_offset_t)&mode, sizeof(mode)); ! 793: ! 794: if (ifp->if_flags & IFF_LOOPBACK ! 795: && ((mode & LN_MODE_LOOP) == 0)) { ! 796: /* if not already in loopback mode, do external loopback */ ! 797: mode &= ~LN_MODE_INTL; ! 798: mode |= LN_MODE_LOOP; ! 799: (se_sw->desc_copyout) ((vm_offset_t)&mode, Hmem(sc->lninit_block), sizeof(mode)); ! 800: se_restart(ifp); ! 801: se_init(ifp->if_unit); ! 802: splx(s); ! 803: return; ! 804: } ! 805: ! 806: ifp->if_flags |= (IFF_UP | IFF_RUNNING); ! 807: sc->se_flags |= (IFF_UP | IFF_RUNNING); ! 808: ! 809: /* ! 810: * Start the Lance and enable interrupts ! 811: */ ! 812: *rdp = (LN_CSR0_STRT | LN_CSR0_INEA); ! 813: wbflush(); ! 814: ! 815: /* ! 816: * See if anything is already queued ! 817: */ ! 818: se_start(unit); ! 819: splx(s); ! 820: } ! 821: ! 822: ! 823: /* ! 824: * Shut off the lance ! 825: */ ! 826: void ! 827: se_stop(int unit) ! 828: { ! 829: se_reg_t rdp = se_softc[unit]->lnregs; ! 830: ! 831: se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); ! 832: } ! 833: ! 834: ! 835: /* ! 836: * Open the device, declaring the interface up ! 837: * and enabling lance interrupts. ! 838: */ ! 839: /*ARGSUSED*/ ! 840: int ! 841: se_open( ! 842: int unit, ! 843: int flag) ! 844: { ! 845: register se_softc_t sc = se_softc[unit]; ! 846: ! 847: if (unit >= NLN) ! 848: return EINVAL; ! 849: if (!se_open_state) ! 850: return ENXIO; ! 851: ! 852: sc->is_if.if_flags |= IFF_UP; ! 853: se_open_state++; ! 854: se_init(unit); ! 855: return (0); ! 856: } ! 857: ! 858: #ifdef MAPPED ! 859: int se_use_mapped_interface[NLN]; ! 860: #endif /*MAPPED*/ ! 861: ! 862: void ! 863: se_normal(int unit) ! 864: { ! 865: #ifdef MAPPED ! 866: se_use_mapped_interface[unit] = 0; ! 867: #endif /*MAPPED*/ ! 868: if (se_softc[unit]) { ! 869: se_restart((struct ifnet *)se_softc[unit]); ! 870: se_init(unit); ! 871: } ! 872: } ! 873: ! 874: /* ! 875: * Ethernet interface interrupt routine ! 876: */ ! 877: void ! 878: se_intr( ! 879: int unit, ! 880: spl_t spllevel) ! 881: { ! 882: register se_softc_t sc = se_softc[unit]; ! 883: se_reg_t rdp; ! 884: register struct ifnet *ifp = &sc->is_if; ! 885: register unsigned short csr; ! 886: ! 887: #ifdef MAPPED ! 888: if (se_use_mapped_interface[unit]) ! 889: { ! 890: SE_intr(unit,spllevel); ! 891: return; ! 892: } ! 893: #endif /*MAPPED*/ ! 894: ! 895: if (se_open_state < 2) { /* Stray, or not open for business */ ! 896: rdp = (sc ? sc->lnregs : (se_reg_t)se_unprobed_addr); ! 897: *rdp |= LN_CSR0_STOP; ! 898: wbflush(); ! 899: return; ! 900: } ! 901: rdp = sc->lnregs; ! 902: ! 903: /* ! 904: * Read the CSR and process any error condition. ! 905: * Later on, restart the lance by writing back ! 906: * the CSR (for set-to-clear bits). ! 907: */ ! 908: csr = *rdp; /* pick up the csr */ ! 909: ! 910: /* drop spurious interrupts */ ! 911: if ((csr & LN_CSR0_INTR) == 0) ! 912: return; ! 913: ! 914: #ifdef DECSTATION ! 915: splx(spllevel); /* drop priority now */ ! 916: #endif /*DECSTATION*/ ! 917: again: ! 918: /* ! 919: * Check for errors first ! 920: */ ! 921: if ( csr & LN_CSR0_ERR ) { ! 922: if (csr & LN_CSR0_MISS) { ! 923: /* ! 924: * Stop the chip to prevent a corrupt packet from ! 925: * being transmitted. There is a known problem with ! 926: * missed packet errors causing corrupted data to ! 927: * be transmitted to the same host as was just ! 928: * transmitted, with a valid crc appended to the ! 929: * packet. The only solution is to stop the chip, ! 930: * which will clear the Lance silo, thus preventing ! 931: * the corrupt data from being sent. ! 932: */ ! 933: se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); ! 934: ! 935: sc->misscnt++; ! 936: if (se_verbose) { ! 937: int me = 0, lance = 0, index; ! 938: struct se_desc r; ! 939: for (index = 0; index < NRCV; index++) { ! 940: (se_sw->desc_copyin)( ! 941: (vm_offset_t)sc->lnrring[index], ! 942: (vm_offset_t)&r, ! 943: sizeof(r)); ! 944: if (r.status & LN_RSTATE_OWN) ! 945: lance++; ! 946: else ! 947: me++; ! 948: } ! 949: printf("se%d: missed packet (%d) csr = %x, Lance %x, me %x\n", ! 950: unit, sc->misscnt, csr, lance, me); ! 951: } ! 952: se_restart(ifp); ! 953: se_init(unit); ! 954: return; ! 955: } ! 956: if (csr & LN_CSR0_BABL) { ! 957: sc->bablcnt++; ! 958: if (se_verbose) ! 959: printf("se%d: xmt timeout (%d)\n", ! 960: unit, sc->bablcnt); ! 961: } ! 962: if (csr & LN_CSR0_MERR) { ! 963: sc->merrcnt++; ! 964: printf("se%d: memory error (%d)\n", ! 965: unit, sc->merrcnt); ! 966: ! 967: if (((csr & LN_CSR0_RXON) == 0) ! 968: || ((csr & LN_CSR0_TXON) == 0)) { ! 969: se_restart(ifp); ! 970: se_init(unit); ! 971: return; ! 972: } ! 973: } ! 974: } ! 975: ! 976: *rdp = LN_CSR0_INEA | (csr & LN_CSR0_WTC); ! 977: wbflush(); ! 978: ! 979: if ( csr & LN_CSR0_RINT ) ! 980: se_rint( unit ); ! 981: ! 982: if ( csr & LN_CSR0_TINT ) ! 983: se_tint( unit ); ! 984: ! 985: if ((csr = *rdp) & (LN_CSR0_RINT | LN_CSR0_TINT)) ! 986: goto again; ! 987: } ! 988: ! 989: /* ! 990: * Handle a transmitter complete interrupt. ! 991: */ ! 992: void ! 993: se_tint(int unit) ! 994: { ! 995: register se_softc_t sc = se_softc[unit]; ! 996: register index; ! 997: register status; ! 998: io_req_t request; ! 999: struct se_desc r; ! 1000: ! 1001: /* ! 1002: * Free up descriptors for all packets in queue for which ! 1003: * transmission is complete. Start from queue tail, stop at first ! 1004: * descriptor we do not OWN, or which is in an inconsistent state ! 1005: * (lance still working). ! 1006: */ ! 1007: ! 1008: while ((sc->xmt_complete != sc->xmt_last) && (sc->xmt_count > 0)) { ! 1009: ! 1010: index = sc->xmt_complete; ! 1011: (se_sw->desc_copyin) ((vm_offset_t)sc->lntring[index], ! 1012: (vm_offset_t)&r, sizeof(r)); ! 1013: status = r.status; ! 1014: ! 1015: /* ! 1016: * Does lance still own it ? ! 1017: */ ! 1018: if (status & LN_TSTATE_OWN) ! 1019: break; ! 1020: ! 1021: /* ! 1022: * Packet sent allright, release queue slot. ! 1023: */ ! 1024: request = sc->tpkt[index]; ! 1025: sc->tpkt[index] = (io_req_t) 0; ! 1026: sc->xmt_complete = ++index & (NXMT - 1); ! 1027: --sc->xmt_count; ! 1028: ! 1029: sc->is_if.if_opackets++; ! 1030: if (status & (LN_TSTATE_DEF|LN_TSTATE_ONE|LN_TSTATE_MORE)) ! 1031: sc->is_if.if_collisions++; ! 1032: ! 1033: /* ! 1034: * Check for transmission errors. ! 1035: */ ! 1036: if (!se_loopback_hack && status & LN_TSTATE_ERR) { ! 1037: sc->is_if.if_oerrors++; ! 1038: if (se_verbose) ! 1039: printf("se%d: xmt error (x%x)\n", unit, r.status2); ! 1040: ! 1041: if (r.status2 & (LN_TSTATE2_RTRY|LN_TSTATE2_LCOL)) ! 1042: sc->is_if.if_collisions++; ! 1043: ! 1044: /* ! 1045: * Restart chip on errors that disable the ! 1046: * transmitter. ! 1047: */ ! 1048: iodone(request); ! 1049: if (r.status2 & LN_TSTATE2_DISABLE) { ! 1050: register struct ifnet *ifp = &sc->is_if; ! 1051: se_restart(ifp); ! 1052: se_init(ifp->if_unit); ! 1053: return; ! 1054: } ! 1055: } else if (request) { ! 1056: /* ! 1057: * If this was a broadcast packet loop it back. ! 1058: * Signal successful transmission of the packet. ! 1059: */ ! 1060: register struct ether_header *eh; ! 1061: register int i; ! 1062: ! 1063: eh = (struct ether_header *) request->io_data; ! 1064: /* ether broadcast address is in the spec */ ! 1065: for (i = 0; (i < 6) && (eh->ether_dhost[i] == 0xff); i++) ! 1066: ; /* nop */ ! 1067: /* sending to ourselves makes sense sometimes */ ! 1068: if (i != 6 && se_loopback_hack) ! 1069: for (i = 0; ! 1070: (i < 6) && (eh->ether_dhost[i] == sc->is_addr[i]); ! 1071: i++) ! 1072: ; /* nop */ ! 1073: if (i == 6) ! 1074: se_read(sc, 0, request->io_count, request); ! 1075: iodone(request); ! 1076: } ! 1077: } ! 1078: /* ! 1079: * Dequeue next transmit request, if any. ! 1080: */ ! 1081: if (sc->xmt_count <= 0) ! 1082: se_start(unit); ! 1083: } ! 1084: ! 1085: /* ! 1086: * Handle a receiver complete interrupt. ! 1087: */ ! 1088: void ! 1089: se_rint(int unit) ! 1090: { ! 1091: register se_softc_t sc = se_softc[unit]; ! 1092: register index, first, len; ! 1093: unsigned char status, status1; ! 1094: int ring_cnt; ! 1095: struct se_desc r; ! 1096: ! 1097: /* ! 1098: * Starting from where we left off, look around the receive ring and ! 1099: * pass on all complete packets. ! 1100: */ ! 1101: ! 1102: for (;; sc->rcv_last = ++index & (NRCV - 1)) { ! 1103: ! 1104: /* ! 1105: * Read in current descriptor ! 1106: */ ! 1107: read_descriptor: ! 1108: (se_sw->desc_copyin) ((vm_offset_t)sc->lnrring[sc->rcv_last], ! 1109: (vm_offset_t)&r, sizeof(r)); ! 1110: status = r.status; ! 1111: if (status & LN_RSTATE_OWN) ! 1112: break; ! 1113: first = index = sc->rcv_last; ! 1114: ! 1115: /* ! 1116: * If not the start of a packet, error ! 1117: */ ! 1118: if (!(status & LN_RSTATE_STP)) { ! 1119: if (se_verbose) ! 1120: printf("se%d: Rring #%d, status=%x !STP\n", ! 1121: unit, index, status); ! 1122: break; ! 1123: } ! 1124: /* ! 1125: * See if packet is chained (should not) by looking at ! 1126: * the last descriptor (OWN clear and ENP set). ! 1127: * Remember the status info in this last descriptor. ! 1128: */ ! 1129: ring_cnt = 1, status1 = status; ! 1130: while (((status1 & (LN_RSTATE_ERR | LN_RSTATE_OWN | LN_RSTATE_ENP)) == 0) && ! 1131: (ring_cnt++ <= NRCV)) { ! 1132: struct se_desc r1; ! 1133: index = (index + 1) & (NRCV - 1); ! 1134: (se_sw->desc_copyin) ((vm_offset_t)sc->lnrring[index], ! 1135: (vm_offset_t)&r1, sizeof(r1)); ! 1136: status1 = r1.status; ! 1137: } ! 1138: ! 1139: /* ! 1140: * Chained packet (--> illegally sized!); re-init the ! 1141: * descriptors involved and ignore this bogus packet. I ! 1142: * donno how, but it really happens that we get these ! 1143: * monsters. ! 1144: */ ! 1145: if (ring_cnt > 1) { ! 1146: /* ! 1147: * Return all descriptors to lance ! 1148: */ ! 1149: se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN); ! 1150: while (first != index) { ! 1151: first = (first + 1) & (NRCV - 1); ! 1152: se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN); ! 1153: } ! 1154: if ((status1 & LN_RSTATE_ERR) && se_verbose) ! 1155: printf("se%d: rcv error %x (chained)\n", unit, status1); ! 1156: continue; ! 1157: } ! 1158: ! 1159: /* ! 1160: * Good packets must be owned by us and have the end of ! 1161: * packet flag. And nothing else. ! 1162: */ ! 1163: if ((status & ~LN_RSTATE_STP) == LN_RSTATE_ENP) { ! 1164: sc->is_if.if_ipackets++; ! 1165: ! 1166: if ((len = r.message_size) == 0) ! 1167: /* race seen on pmaxen: the lance ! 1168: * has not updated the size yet ?? ! 1169: */ ! 1170: goto read_descriptor; ! 1171: /* ! 1172: * Drop trailing CRC bytes from len and ship packet ! 1173: * up ! 1174: */ ! 1175: se_read(sc, (volatile char*)sc->lnrbuf[first], len-4,0); ! 1176: ! 1177: /* ! 1178: * Return descriptor to lance, and move on to next ! 1179: * packet ! 1180: */ ! 1181: r.status = LN_RSTATE_OWN; ! 1182: (se_sw->desc_copyout)((vm_offset_t)&r, ! 1183: (vm_offset_t)sc->lnrring[first], ! 1184: sizeof(r)); ! 1185: continue; ! 1186: } ! 1187: /* ! 1188: * Not a good packet, see what is wrong ! 1189: */ ! 1190: if (status & LN_RSTATE_ERR) { ! 1191: sc->is_if.if_ierrors++; ! 1192: ! 1193: if (se_verbose) ! 1194: printf("se%d: rcv error (x%x)\n", unit, status); ! 1195: ! 1196: /* ! 1197: * Return descriptor to lance ! 1198: */ ! 1199: se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN); ! 1200: } else { ! 1201: /* ! 1202: * Race condition viz lance, Wait for the next ! 1203: * interrupt. ! 1204: */ ! 1205: return; ! 1206: } ! 1207: } ! 1208: } ! 1209: ! 1210: /* ! 1211: * Output routine. ! 1212: * Call common function for wiring memory, ! 1213: * come back later (to se_start) to get ! 1214: * things going. ! 1215: */ ! 1216: io_return_t ! 1217: se_output( ! 1218: int dev, ! 1219: io_req_t ior) ! 1220: { ! 1221: return net_write(&se_softc[dev]->is_if, (int(*)())se_start, ior); ! 1222: } ! 1223: ! 1224: /* ! 1225: * Start output on interface. ! 1226: * ! 1227: */ ! 1228: void ! 1229: se_start(int unit) ! 1230: { ! 1231: register se_softc_t sc = se_softc[unit]; ! 1232: io_req_t request; ! 1233: struct se_desc r; ! 1234: int tlen; ! 1235: spl_t s; ! 1236: register int index; ! 1237: ! 1238: s = splimp(); ! 1239: ! 1240: for (index = sc->xmt_last; ! 1241: sc->xmt_count < (NXMT - 1); ! 1242: sc->xmt_last = index = (index + 1) & (NXMT - 1)) { ! 1243: /* ! 1244: * Dequeue the next transmit request, if any. ! 1245: */ ! 1246: IF_DEQUEUE(&sc->is_if.if_snd, request); ! 1247: if (request == 0) { ! 1248: /* ! 1249: * Tell the lance to send the packet now ! 1250: * instead of waiting until the next 1.6 ms ! 1251: * poll interval expires. ! 1252: */ ! 1253: *sc->lnregs = LN_CSR0_TDMD | LN_CSR0_INEA; ! 1254: splx(s); ! 1255: return; /* Nothing on the queue */ ! 1256: } ! 1257: ! 1258: /* ! 1259: * Keep request around until transmission complete ! 1260: */ ! 1261: sc->tpkt[index] = request; ! 1262: tlen = copy_to_lance(request, sc->lntbuf[index]); ! 1263: ! 1264: /* ! 1265: * Give away buffer. Must copyin/out, set len, ! 1266: * and set the OWN flag. We do not do chaining. ! 1267: */ ! 1268: (se_sw->desc_copyin)((vm_offset_t)sc->lntring[index], ! 1269: (vm_offset_t)&r, sizeof(r)); ! 1270: r.buffer_size = -(tlen) | 0xf000; ! 1271: r.status = (LN_TSTATE_OWN | LN_TSTATE_STP | LN_TSTATE_ENP); ! 1272: (se_sw->desc_copyout)((vm_offset_t)&r, ! 1273: (vm_offset_t)sc->lntring[index], ! 1274: sizeof(r)); ! 1275: wbflush(); ! 1276: ! 1277: sc->xmt_count++; ! 1278: } ! 1279: /* ! 1280: * Since we actually have queued new packets, tell ! 1281: * the chip to rescan the descriptors _now_. ! 1282: * It is quite unlikely that the ring be filled, ! 1283: * but if it is .. the more reason to do it! ! 1284: */ ! 1285: *sc->lnregs = LN_CSR0_TDMD | LN_CSR0_INEA; ! 1286: splx(s); ! 1287: } ! 1288: ! 1289: ! 1290: /* ! 1291: * Pull a packet off the interface and ! 1292: * hand it up to the higher levels. ! 1293: * ! 1294: * Simulate broadcast packets in software. ! 1295: */ ! 1296: void ! 1297: se_read( ! 1298: register se_softc_t sc, ! 1299: volatile char *lnrbuf, ! 1300: int len, ! 1301: io_req_t loop_back) ! 1302: { ! 1303: register struct ifnet *ifp = &sc->is_if; ! 1304: register ipc_kmsg_t new_kmsg; ! 1305: char *hdr, *pkt; ! 1306: ! 1307: if (len <= sizeof(struct ether_header)) ! 1308: return; /* sanity */ ! 1309: ! 1310: /* ! 1311: * Get a new kmsg to put data into. ! 1312: */ ! 1313: new_kmsg = net_kmsg_get(); ! 1314: if (new_kmsg == IKM_NULL) { ! 1315: /* ! 1316: * No room, drop the packet ! 1317: */ ! 1318: ifp->if_rcvdrops++; ! 1319: return; ! 1320: } ! 1321: ! 1322: hdr = net_kmsg(new_kmsg)->header; ! 1323: pkt = net_kmsg(new_kmsg)->packet; ! 1324: ! 1325: #define OFF0 (sizeof(struct ether_header) - sizeof(struct packet_header)) ! 1326: #define OFF1 (OFF0 & ~3) ! 1327: if (loop_back) { ! 1328: bcopy(loop_back->io_data, hdr, sizeof(struct ether_header)); ! 1329: bcopy(loop_back->io_data + OFF0, ! 1330: pkt, len - OFF0); ! 1331: } else ! 1332: copy_from_lance(lnrbuf, len, (struct ether_header*)hdr, ! 1333: (struct packet_header*)pkt); ! 1334: ! 1335: /* ! 1336: * Set up the 'fake' header with length. Type has been left ! 1337: * in the correct place. ! 1338: */ ! 1339: len = len - OFF0; ! 1340: ((struct packet_header *)pkt)->length = len; ! 1341: ! 1342: /* ! 1343: * Hand the packet to the network module. ! 1344: */ ! 1345: net_packet(ifp, new_kmsg, len, ethernet_priority(new_kmsg)); ! 1346: } ! 1347: ! 1348: ! 1349: /* ! 1350: * Get a packet out of Lance memory and into main memory. ! 1351: */ ! 1352: private void ! 1353: copy_from_lance( ! 1354: register volatile unsigned char *rbuf, ! 1355: register unsigned int nbytes, ! 1356: struct ether_header *hdr, ! 1357: struct packet_header *pkt) ! 1358: { ! 1359: /* ! 1360: * Read in ethernet header ! 1361: */ ! 1362: (se_sw->data_copyin) ((vm_offset_t)rbuf, (vm_offset_t)hdr, sizeof(struct ether_header)); ! 1363: ! 1364: nbytes -= sizeof(struct ether_header); ! 1365: rbuf += (se_sw->mapoffs) (sizeof(struct ether_header)); ! 1366: ! 1367: pkt->type = (unsigned short) hdr->ether_type; ! 1368: ! 1369: (se_sw->data_copyin) ((vm_offset_t)rbuf, (vm_offset_t)(pkt + 1), nbytes); ! 1370: } ! 1371: ! 1372: ! 1373: /* ! 1374: * Move a packet into Lance space ! 1375: */ ! 1376: private int ! 1377: copy_to_lance( ! 1378: register io_req_t request, ! 1379: volatile char *sbuf) ! 1380: { ! 1381: register unsigned short *dp; ! 1382: register int len; ! 1383: ! 1384: dp = (unsigned short *) request->io_data; ! 1385: len = request->io_count; ! 1386: ! 1387: if (len > (int)(ETHERMTU + sizeof(struct ether_header))) { ! 1388: printf("se: truncating HUGE packet\n"); ! 1389: len = ETHERMTU + sizeof(struct ether_header); ! 1390: } ! 1391: ! 1392: (se_sw->data_copyout) ((vm_offset_t)dp, (vm_offset_t)sbuf, len); ! 1393: ! 1394: if (len < LN_MINBUF_NOCH) ! 1395: /* ! 1396: * The lance needs at least this much data in a packet. Who ! 1397: * cares if I send some garbage that was left in the lance ! 1398: * buffer ? If one can spoof packets then one can spoof ! 1399: * packets! ! 1400: */ ! 1401: len = LN_MINBUF_NOCH; ! 1402: return len; ! 1403: } ! 1404: ! 1405: /* ! 1406: * Reset a descriptor's flags. ! 1407: * Optionally give the descriptor to the lance ! 1408: */ ! 1409: private void ! 1410: se_desc_set_status ( ! 1411: register se_desc_t lndesc, ! 1412: int val) ! 1413: { ! 1414: struct se_desc desc; ! 1415: ! 1416: (se_sw->desc_copyin) ((vm_offset_t)lndesc, (vm_offset_t)&desc, sizeof(desc)); ! 1417: desc.desc4.bits = 0; ! 1418: desc.status = val; ! 1419: (se_sw->desc_copyout) ((vm_offset_t)&desc, (vm_offset_t)lndesc, sizeof(desc)); ! 1420: wbflush(); ! 1421: } ! 1422: ! 1423: /* ! 1424: * Set/Get status functions ! 1425: */ ! 1426: int ! 1427: se_get_status( ! 1428: int dev, ! 1429: dev_flavor_t flavor, ! 1430: dev_status_t status, /* pointer to OUT array */ ! 1431: natural_t *status_count) /* out */ ! 1432: { ! 1433: return (net_getstat(&se_softc[dev]->is_if, ! 1434: flavor, status, status_count)); ! 1435: } ! 1436: ! 1437: int ! 1438: se_set_status( ! 1439: int unit, ! 1440: dev_flavor_t flavor, ! 1441: dev_status_t status, ! 1442: natural_t status_count) ! 1443: { ! 1444: register se_softc_t sc; ! 1445: ! 1446: sc = se_softc[unit]; ! 1447: ! 1448: ! 1449: switch (flavor) { ! 1450: ! 1451: case NET_STATUS: ! 1452: break; ! 1453: ! 1454: case NET_ADDRESS: { ! 1455: ! 1456: register union ether_cvt { ! 1457: unsigned char addr[6]; ! 1458: int lwd[2]; ! 1459: } *ec = (union ether_cvt *) status; ! 1460: ! 1461: if (status_count < sizeof(*ec) / sizeof(int)) ! 1462: return (D_INVALID_SIZE); ! 1463: ! 1464: ec->lwd[0] = ntohl(ec->lwd[0]); ! 1465: ec->lwd[1] = ntohl(ec->lwd[1]); ! 1466: ! 1467: se_setaddr(ec->addr, unit); ! 1468: ! 1469: break; ! 1470: } ! 1471: ! 1472: default: ! 1473: return (D_INVALID_OPERATION); ! 1474: } ! 1475: ! 1476: return (D_SUCCESS); ! 1477: } ! 1478: ! 1479: ! 1480: /* ! 1481: * Install new filter. ! 1482: * Nothing special needs to be done here. ! 1483: */ ! 1484: io_return_t ! 1485: se_setinput( ! 1486: int dev, ! 1487: ipc_port_t receive_port, ! 1488: int priority, ! 1489: filter_t *filter, ! 1490: natural_t filter_count) ! 1491: { ! 1492: return (net_set_filter(&se_softc[dev]->is_if, ! 1493: receive_port, priority, ! 1494: filter, filter_count)); ! 1495: } ! 1496: ! 1497: /* ! 1498: * Allocate and initialize a ring descriptor. ! 1499: * Allocates a buffer from the lance memory and writes a descriptor ! 1500: * for that buffer to the host virtual address LNDESC. ! 1501: */ ! 1502: private volatile long ! 1503: *se_desc_alloc ( ! 1504: register se_softc_t sc, ! 1505: register se_desc_t lndesc) ! 1506: { ! 1507: register vm_offset_t dp; /* data pointer */ ! 1508: struct se_desc desc; ! 1509: ! 1510: /* ! 1511: * Allocate buffer in lance space ! 1512: */ ! 1513: dp = se_malloc(sc, LN_BUFFER_SIZE); ! 1514: ! 1515: /* ! 1516: * Build a descriptor pointing to it ! 1517: */ ! 1518: desc.addr_low = Addr_lo(Lmem(dp)); ! 1519: desc.addr_hi = Addr_hi(Lmem(dp)); ! 1520: desc.status = 0; ! 1521: desc.buffer_size = -LN_BUFFER_SIZE; ! 1522: desc.desc4.bits = 0; ! 1523: ! 1524: /* ! 1525: * Copy the descriptor to lance space ! 1526: */ ! 1527: (se_sw->desc_copyout) ((vm_offset_t)&desc, (vm_offset_t)lndesc, sizeof(desc)); ! 1528: wbflush(); ! 1529: ! 1530: return (volatile long *) Hmem(dp); ! 1531: } ! 1532: ! 1533: /* ! 1534: * Allocate a chunk of lance RAM buffer. Since we never ! 1535: * give lance RAM buffer memory back, we'll just step up the ! 1536: * byte-count on a per-unit basis. ! 1537: * ! 1538: * The return value is an index into the lance memory, which can be ! 1539: * passed with Hmem() and Lmem() to get the host and chip virtual addresses. ! 1540: */ ! 1541: private vm_offset_t ! 1542: se_malloc( ! 1543: se_softc_t sc, ! 1544: int size) ! 1545: { ! 1546: register vm_offset_t ret; ! 1547: ! 1548: /* ! 1549: * On first call, zero lance memory ! 1550: */ ! 1551: if (sc->lnsbrk == 0) ! 1552: (se_sw->bzero) (Hmem(0), LN_MEMORY_SIZE); ! 1553: ! 1554: /* ! 1555: * Start out on the first double longword boundary ! 1556: * (this accomodates some machines, with minimal loss) ! 1557: */ ! 1558: if (sc->lnsbrk & 0xf) ! 1559: sc->lnsbrk = (sc->lnsbrk + 0x10) & ~0xf; ! 1560: ! 1561: ret = sc->lnsbrk; ! 1562: sc->lnsbrk += size; ! 1563: ! 1564: if (sc->lnsbrk > LN_MEMORY_SIZE) ! 1565: panic("se_malloc"); ! 1566: ! 1567: return ret; ! 1568: } ! 1569: ! 1570: #endif NLN > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.