|
|
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.