Annotation of sys/dev/ic/i82596.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: i82596.c,v 1.26 2006/03/25 22:41:43 djm Exp $ */
2: /* $NetBSD: i82586.c,v 1.18 1998/08/15 04:42:42 mycroft Exp $ */
3:
4: /*-
5: * Copyright (c) 1998 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Paul Kranenburg and Charles M. Hannum.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39: /*-
40: * Copyright (c) 1997 Paul Kranenburg.
41: * Copyright (c) 1992, 1993, University of Vermont and State
42: * Agricultural College.
43: * Copyright (c) 1992, 1993, Garrett A. Wollman.
44: *
45: * Portions:
46: * Copyright (c) 1994, 1995, Rafal K. Boni
47: * Copyright (c) 1990, 1991, William F. Jolitz
48: * Copyright (c) 1990, The Regents of the University of California
49: *
50: * All rights reserved.
51: *
52: * Redistribution and use in source and binary forms, with or without
53: * modification, are permitted provided that the following conditions
54: * are met:
55: * 1. Redistributions of source code must retain the above copyright
56: * notice, this list of conditions and the following disclaimer.
57: * 2. Redistributions in binary form must reproduce the above copyright
58: * notice, this list of conditions and the following disclaimer in the
59: * documentation and/or other materials provided with the distribution.
60: * 3. All advertising materials mentioning features or use of this software
61: * must display the following acknowledgement:
62: * This product includes software developed by the University of Vermont
63: * and State Agricultural College and Garrett A. Wollman, by William F.
64: * Jolitz, and by the University of California, Berkeley, Lawrence
65: * Berkeley Laboratory, and its contributors.
66: * 4. Neither the names of the Universities nor the names of the authors
67: * may be used to endorse or promote products derived from this software
68: * without specific prior written permission.
69: *
70: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
71: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73: * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
74: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
75: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
76: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
77: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
78: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
79: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80: * SUCH DAMAGE.
81: */
82: /*
83: * Intel 82586/82596 Ethernet chip
84: * Register, bit, and structure definitions.
85: *
86: * Original StarLAN driver written by Garrett Wollman with reference to the
87: * Clarkson Packet Driver code for this chip written by Russ Nelson and others.
88: *
89: * BPF support code taken from hpdev/if_le.c, supplied with tcpdump.
90: *
91: * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni.
92: *
93: * Majorly cleaned up and 3C507 code merged by Charles Hannum.
94: *
95: * Converted to SUN ie driver by Charles D. Cranor,
96: * October 1994, January 1995.
97: * This sun version based on i386 version 1.30.
98: */
99: /*
100: * The i82596 is a very painful chip, found in sun3's, sun-4/100's
101: * sun-4/200's, and VME based suns. The byte order is all wrong for a
102: * SUN, making life difficult. Programming this chip is mostly the same,
103: * but certain details differ from system to system. This driver is
104: * written so that different "ie" interfaces can be controled by the same
105: * driver.
106: */
107:
108: /*
109: Mode of operation:
110:
111: We run the 82596 in a standard Ethernet mode. We keep NFRAMES
112: received frame descriptors around for the receiver to use, and
113: NRXBUF associated receive buffer descriptors, both in a circular
114: list. Whenever a frame is received, we rotate both lists as
115: necessary. (The 596 treats both lists as a simple queue.) We also
116: keep a transmit command around so that packets can be sent off
117: quickly.
118:
119: We configure the adapter in AL-LOC = 1 mode, which means that the
120: Ethernet/802.3 MAC header is placed at the beginning of the receive
121: buffer rather than being split off into various fields in the RFD.
122: This also means that we must include this header in the transmit
123: buffer as well.
124:
125: By convention, all transmit commands, and only transmit commands,
126: shall have the I (IE_CMD_INTR) bit set in the command. This way,
127: when an interrupt arrives at i82596_intr(), it is immediately possible
128: to tell what precisely caused it. ANY OTHER command-sending
129: routines should run at splnet(), and should post an acknowledgement
130: to every interrupt they generate.
131:
132: To save the expense of shipping a command to 82596 every time we
133: want to send a frame, we use a linked list of commands consisting
134: of alternate XMIT and NOP commands. The links of these elements
135: are manipulated (in i82596_xmit()) such that the NOP command loops back
136: to itself whenever the following XMIT command is not yet ready to
137: go. Whenever an XMIT is ready, the preceding NOP link is pointed
138: at it, while its own link field points to the following NOP command.
139: Thus, a single transmit command sets off an interlocked traversal
140: of the xmit command chain, with the host processor in control of
141: the synchronization.
142: */
143:
144: #include "bpfilter.h"
145:
146: #include <sys/param.h>
147: #include <sys/systm.h>
148: #include <sys/mbuf.h>
149: #include <sys/socket.h>
150: #include <sys/ioctl.h>
151: #include <sys/errno.h>
152: #include <sys/syslog.h>
153: #include <sys/device.h>
154:
155: #include <net/if.h>
156: #include <net/if_dl.h>
157: #include <net/if_types.h>
158: #include <net/if_media.h>
159:
160: #if NBPFILTER > 0
161: #include <net/bpf.h>
162: #endif
163:
164: #ifdef INET
165: #include <netinet/in.h>
166: #include <netinet/in_systm.h>
167: #include <netinet/in_var.h>
168: #include <netinet/ip.h>
169: #include <netinet/if_ether.h>
170: #endif
171:
172: #include <uvm/uvm_extern.h>
173:
174: #include <machine/bus.h>
175:
176: #include <dev/ic/i82596reg.h>
177: #include <dev/ic/i82596var.h>
178:
179: static char *padbuf;
180:
181: void i82596_reset(struct ie_softc *, int);
182: void i82596_watchdog(struct ifnet *);
183: int i82596_init(struct ie_softc *);
184: int i82596_ioctl(struct ifnet *, u_long, caddr_t);
185: void i82596_start(struct ifnet *);
186:
187: int i82596_rint(struct ie_softc *, int);
188: int i82596_tint(struct ie_softc *, int);
189:
190: int i82596_mediachange(struct ifnet *);
191: void i82596_mediastatus(struct ifnet *, struct ifmediareq *);
192:
193: int i82596_readframe(struct ie_softc *, int);
194: int i82596_get_rbd_list(struct ie_softc *,
195: u_int16_t *, u_int16_t *, int *);
196: void i82596_release_rbd_list(struct ie_softc *, u_int16_t, u_int16_t);
197: int i82596_drop_frames(struct ie_softc *);
198: int i82596_chk_rx_ring(struct ie_softc *);
199:
200: void i82596_start_transceiver(struct ie_softc *);
201: void i82596_stop(struct ie_softc *);
202: void i82596_xmit(struct ie_softc *);
203:
204: void i82596_setup_bufs(struct ie_softc *);
205: void i82596_simple_command(struct ie_softc *, int, int);
206: int ie_cfg_setup(struct ie_softc *, int, int, int);
207: int ie_ia_setup(struct ie_softc *, int);
208: void ie_run_tdr(struct ie_softc *, int);
209: int ie_mc_setup(struct ie_softc *, int);
210: void ie_mc_reset(struct ie_softc *);
211: int i82596_cmd_wait(struct ie_softc *);
212:
213: #ifdef I82596_DEBUG
214: void print_rbd(struct ie_softc *, int);
215: #endif
216:
217: struct cfdriver ie_cd = {
218: NULL, "ie", DV_IFNET
219: };
220:
221: /*
222: * generic i82596 probe routine
223: */
224: int
225: i82596_probe(sc)
226: struct ie_softc *sc;
227: {
228: int i;
229:
230: sc->scp = sc->sc_msize - IE_SCP_SZ;
231: sc->iscp = 0;
232: sc->scb = 32;
233:
234: (sc->ie_bus_write16)(sc, IE_ISCP_BUSY(sc->iscp), 1);
235: (sc->ie_bus_write16)(sc, IE_ISCP_SCB(sc->iscp), sc->scb);
236: (sc->ie_bus_write24)(sc, IE_ISCP_BASE(sc->iscp), sc->sc_maddr);
237: (sc->ie_bus_write24)(sc, IE_SCP_ISCP(sc->scp), sc->sc_maddr);
238: (sc->ie_bus_write16)(sc, IE_SCP_BUS_USE(sc->scp), sc->sysbus);
239:
240: (sc->hwreset)(sc, IE_CARD_RESET);
241:
242: if ((sc->ie_bus_read16)(sc, IE_ISCP_BUSY(sc->iscp))) {
243: #ifdef I82596_DEBUG
244: printf("%s: ISCP set failed\n", sc->sc_dev.dv_xname);
245: #endif
246: return 0;
247: }
248:
249: if (sc->port) {
250: (sc->ie_bus_write24)(sc, sc->scp, 0);
251: (sc->ie_bus_write24)(sc, IE_SCP_TEST(sc->scp), -1);
252: (sc->port)(sc, IE_PORT_TEST);
253: for (i = 9000; i-- &&
254: (sc->ie_bus_read16)(sc, IE_SCP_TEST(sc->scp));
255: DELAY(100))
256: ;
257: }
258:
259: return 1;
260: }
261:
262: /*
263: * Front-ends call this function to attach to the MI driver.
264: *
265: * The front-end has responsibility for managing the ICP and ISCP
266: * structures. Both of these are opaque to us. Also, the front-end
267: * chooses a location for the SCB which is expected to be addressable
268: * (through `sc->scb') as an offset against the shared-memory bus handle.
269: *
270: * The following MD interface function must be setup by the front-end
271: * before calling here:
272: *
273: * hwreset - board dependent reset
274: * hwinit - board dependent initialization
275: * chan_attn - channel attention
276: * intrhook - board dependent interrupt processing
277: * memcopyin - shared memory copy: board to KVA
278: * memcopyout - shared memory copy: KVA to board
279: * ie_bus_read16 - read a sixteen-bit i82596 pointer
280: * ie_bus_write16 - write a sixteen-bit i82596 pointer
281: * ie_bus_write24 - write a twenty-four-bit i82596 pointer
282: *
283: */
284: void
285: i82596_attach(sc, name, etheraddr, media, nmedia, defmedia)
286: struct ie_softc *sc;
287: const char *name;
288: u_int8_t *etheraddr;
289: int *media, nmedia, defmedia;
290: {
291: int i;
292: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
293:
294: /* Setup SCP+ISCP */
295: (sc->ie_bus_write16)(sc, IE_ISCP_BUSY(sc->iscp), 1);
296: (sc->ie_bus_write16)(sc, IE_ISCP_SCB(sc->iscp), sc->scb);
297: (sc->ie_bus_write24)(sc, IE_ISCP_BASE(sc->iscp), sc->sc_maddr);
298: (sc->ie_bus_write24)(sc, IE_SCP_ISCP(sc->scp), sc->sc_maddr +sc->iscp);
299: (sc->ie_bus_write16)(sc, IE_SCP_BUS_USE(sc->scp), sc->sysbus);
300: (sc->hwreset)(sc, IE_CARD_RESET);
301:
302: /* Setup Iface */
303: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
304: ifp->if_softc = sc;
305: ifp->if_start = i82596_start;
306: ifp->if_ioctl = i82596_ioctl;
307: ifp->if_watchdog = i82596_watchdog;
308: ifp->if_flags =
309: #ifdef I82596_DEBUG
310: IFF_DEBUG |
311: #endif
312: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
313: IFQ_SET_READY(&ifp->if_snd);
314:
315: /* Initialize media goo. */
316: ifmedia_init(&sc->sc_media, 0, i82596_mediachange, i82596_mediastatus);
317: if (media != NULL) {
318: for (i = 0; i < nmedia; i++)
319: ifmedia_add(&sc->sc_media, media[i], 0, NULL);
320: ifmedia_set(&sc->sc_media, defmedia);
321: } else {
322: ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
323: ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
324: }
325:
326: if (padbuf == NULL) {
327: padbuf = malloc(ETHER_MIN_LEN - ETHER_CRC_LEN, M_DEVBUF,
328: M_NOWAIT);
329: if (padbuf == NULL) {
330: printf("%s: can't allocate pad buffer\n",
331: sc->sc_dev.dv_xname);
332: return;
333: }
334: bzero(padbuf, ETHER_MIN_LEN - ETHER_CRC_LEN);
335: }
336:
337: /* Attach the interface. */
338: if_attach(ifp);
339: ether_ifattach(ifp);
340:
341: printf(" %s v%d.%d, address %s\n", name, sc->sc_vers / 10,
342: sc->sc_vers % 10, ether_sprintf(etheraddr));
343: }
344:
345:
346: /*
347: * Device timeout/watchdog routine.
348: * Entered if the device neglects to generate an interrupt after a
349: * transmit has been started on it.
350: */
351: void
352: i82596_watchdog(ifp)
353: struct ifnet *ifp;
354: {
355: struct ie_softc *sc = ifp->if_softc;
356:
357: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
358: ++ifp->if_oerrors;
359:
360: i82596_reset(sc, 1);
361: }
362:
363: int
364: i82596_cmd_wait(sc)
365: struct ie_softc *sc;
366: {
367: /* spin on i82596 command acknowledge; wait at most 0.9 (!) seconds */
368: int i, off;
369:
370: for (i = 180000; i--; DELAY(5)) {
371: /* Read the command word */
372: off = IE_SCB_CMD(sc->scb);
373: bus_space_barrier(sc->bt, sc->bh, off, 2,
374: BUS_SPACE_BARRIER_READ);
375: if ((sc->ie_bus_read16)(sc, off) == 0) {
376: #ifdef I82596_DEBUG
377: if (sc->sc_debug & IED_CMDS)
378: printf("%s: cmd_wait after %d usec\n",
379: sc->sc_dev.dv_xname, (180000 - i) * 5);
380: #endif
381: return (0);
382: }
383: }
384:
385: #ifdef I82596_DEBUG
386: if (sc->sc_debug & IED_CMDS)
387: printf("i82596_cmd_wait: timo(%ssync): scb status: %b\n",
388: sc->async_cmd_inprogress? "a" : "",
389: sc->ie_bus_read16(sc, IE_SCB_STATUS(sc->scb)),
390: IE_STAT_BITS);
391: #endif
392: return (1); /* Timeout */
393: }
394:
395: /*
396: * Send a command to the controller and wait for it to either complete
397: * or be accepted, depending on the command. If the command pointer
398: * is null, then pretend that the command is not an action command.
399: * If the command pointer is not null, and the command is an action
400: * command, wait for one of the MASK bits to turn on in the command's
401: * status field.
402: * If ASYNC is set, we just call the chip's attention and return.
403: * We may have to wait for the command's acceptance later though.
404: */
405: int
406: i82596_start_cmd(sc, cmd, iecmdbuf, mask, async)
407: struct ie_softc *sc;
408: int cmd;
409: int iecmdbuf;
410: int mask;
411: int async;
412: {
413: int i, off;
414:
415: #ifdef I82596_DEBUG
416: if (sc->sc_debug & IED_CMDS)
417: printf("start_cmd: %p, %x, %x, %b, %ssync\n",
418: sc, cmd, iecmdbuf, mask, IE_STAT_BITS, async?"a":"");
419: #endif
420: if (sc->async_cmd_inprogress != 0) {
421: /*
422: * If previous command was issued asynchronously, wait
423: * for it now.
424: */
425: if (i82596_cmd_wait(sc) != 0)
426: return (1);
427: sc->async_cmd_inprogress = 0;
428: }
429:
430: off = IE_SCB_CMD(sc->scb);
431: (sc->ie_bus_write16)(sc, off, cmd);
432: bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_WRITE);
433: (sc->chan_attn)(sc);
434:
435: if (async) {
436: sc->async_cmd_inprogress = 1;
437: return (0);
438: }
439:
440: if (IE_ACTION_COMMAND(cmd) && iecmdbuf) {
441: int status;
442: /*
443: * Now spin-lock waiting for status. This is not a very nice
444: * thing to do, and can kill performance pretty well...
445: * According to the packet driver, the minimum timeout
446: * should be .369 seconds.
447: */
448: for (i = 73800; i--; DELAY(5)) {
449: /* Read the command status */
450: off = IE_CMD_COMMON_STATUS(iecmdbuf);
451: bus_space_barrier(sc->bt, sc->bh, off, 2,
452: BUS_SPACE_BARRIER_READ);
453: status = (sc->ie_bus_read16)(sc, off);
454: if (status & mask) {
455: #ifdef I82596_DEBUG
456: if (sc->sc_debug & IED_CMDS)
457: printf("%s: cmd status %b\n",
458: sc->sc_dev.dv_xname,
459: status, IE_STAT_BITS);
460: #endif
461: return (0);
462: }
463: }
464:
465: } else {
466: /*
467: * Otherwise, just wait for the command to be accepted.
468: */
469: return (i82596_cmd_wait(sc));
470: }
471:
472: /* Timeout */
473: return (1);
474: }
475:
476: /*
477: * Transfer accumulated chip error counters to IF.
478: */
479: static __inline void
480: i82596_count_errors(struct ie_softc *sc)
481: {
482: int scb = sc->scb;
483:
484: sc->sc_arpcom.ac_if.if_ierrors +=
485: sc->ie_bus_read16(sc, IE_SCB_ERRCRC(scb)) +
486: sc->ie_bus_read16(sc, IE_SCB_ERRALN(scb)) +
487: sc->ie_bus_read16(sc, IE_SCB_ERRRES(scb)) +
488: sc->ie_bus_read16(sc, IE_SCB_ERROVR(scb));
489:
490: /* Clear error counters */
491: sc->ie_bus_write16(sc, IE_SCB_ERRCRC(scb), 0);
492: sc->ie_bus_write16(sc, IE_SCB_ERRALN(scb), 0);
493: sc->ie_bus_write16(sc, IE_SCB_ERRRES(scb), 0);
494: sc->ie_bus_write16(sc, IE_SCB_ERROVR(scb), 0);
495: }
496:
497: static __inline void
498: i82596_rx_errors(struct ie_softc *sc, int fn, int status)
499: {
500: log(LOG_ERR, "%s: rx error (frame# %d): %b\n", sc->sc_dev.dv_xname, fn,
501: status, IE_FD_STATUSBITS);
502: }
503:
504: /*
505: * i82596 interrupt entry point.
506: */
507: int
508: i82596_intr(v)
509: void *v;
510: {
511: register struct ie_softc *sc = v;
512: register u_int status;
513: register int off;
514:
515: off = IE_SCB_STATUS(sc->scb);
516: bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_READ);
517: status = sc->ie_bus_read16(sc, off) /* & IE_ST_WHENCE */;
518:
519: if ((status & IE_ST_WHENCE) == 0) {
520: if (sc->intrhook)
521: (sc->intrhook)(sc, IE_INTR_EXIT);
522:
523: return (0);
524: }
525:
526: loop:
527: /* Ack interrupts FIRST in case we receive more during the ISR. */
528: i82596_start_cmd(sc, status & IE_ST_WHENCE, 0, 0, 1);
529:
530: if (status & (IE_ST_FR | IE_ST_RNR)) {
531: if (sc->intrhook)
532: (sc->intrhook)(sc, IE_INTR_ENRCV);
533:
534: if (i82596_rint(sc, status) != 0)
535: goto reset;
536: }
537:
538: if (status & IE_ST_CX) {
539: if (sc->intrhook)
540: (sc->intrhook)(sc, IE_INTR_ENSND);
541:
542: if (i82596_tint(sc, status) != 0)
543: goto reset;
544: }
545:
546: #ifdef I82596_DEBUG
547: if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA))
548: printf("%s: cna; status=%b\n", sc->sc_dev.dv_xname,
549: status, IE_ST_BITS);
550: #endif
551: if (sc->intrhook)
552: (sc->intrhook)(sc, IE_INTR_LOOP);
553:
554: /*
555: * Interrupt ACK was posted asynchronously; wait for
556: * completion here before reading SCB status again.
557: *
558: * If ACK fails, try to reset the chip, in hopes that
559: * it helps.
560: */
561: if (i82596_cmd_wait(sc))
562: goto reset;
563:
564: bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_READ);
565: status = sc->ie_bus_read16(sc, off);
566: if ((status & IE_ST_WHENCE) != 0)
567: goto loop;
568:
569: out:
570: if (sc->intrhook)
571: (sc->intrhook)(sc, IE_INTR_EXIT);
572: return (1);
573:
574: reset:
575: i82596_cmd_wait(sc);
576: i82596_reset(sc, 1);
577: goto out;
578: }
579:
580: /*
581: * Process a received-frame interrupt.
582: */
583: int
584: i82596_rint(sc, scbstatus)
585: struct ie_softc *sc;
586: int scbstatus;
587: {
588: static int timesthru = 1024;
589: register int i, status, off;
590:
591: #ifdef I82596_DEBUG
592: if (sc->sc_debug & IED_RINT)
593: printf("%s: rint: status %b\n",
594: sc->sc_dev.dv_xname, scbstatus, IE_ST_BITS);
595: #endif
596:
597: for (;;) {
598: register int drop = 0;
599:
600: i = sc->rfhead;
601: off = IE_RFRAME_STATUS(sc->rframes, i);
602: bus_space_barrier(sc->bt, sc->bh, off, 2,
603: BUS_SPACE_BARRIER_READ);
604: status = sc->ie_bus_read16(sc, off);
605:
606: #ifdef I82596_DEBUG
607: if (sc->sc_debug & IED_RINT)
608: printf("%s: rint: frame(%d) status %b\n",
609: sc->sc_dev.dv_xname, i, status, IE_ST_BITS);
610: #endif
611: if ((status & IE_FD_COMPLETE) == 0) {
612: if ((status & IE_FD_OK) != 0) {
613: printf("%s: rint: weird: ",
614: sc->sc_dev.dv_xname);
615: i82596_rx_errors(sc, i, status);
616: break;
617: }
618: if (--timesthru == 0) {
619: /* Account the accumulated errors */
620: i82596_count_errors(sc);
621: timesthru = 1024;
622: }
623: break;
624: } else if ((status & IE_FD_OK) == 0) {
625: /*
626: * If the chip is configured to automatically
627: * discard bad frames, the only reason we can
628: * get here is an "out-of-resource" condition.
629: */
630: i82596_rx_errors(sc, i, status);
631: drop = 1;
632: }
633:
634: #ifdef I82596_DEBUG
635: if ((status & IE_FD_BUSY) != 0)
636: printf("%s: rint: frame(%d) busy; status=%x\n",
637: sc->sc_dev.dv_xname, i, status, IE_ST_BITS);
638: #endif
639:
640: /*
641: * Advance the RFD list, since we're done with
642: * this descriptor.
643: */
644:
645: /* Clear frame status */
646: sc->ie_bus_write16(sc, off, 0);
647:
648: /* Put fence at this frame (the head) */
649: off = IE_RFRAME_LAST(sc->rframes, i);
650: sc->ie_bus_write16(sc, off, IE_FD_EOL|IE_FD_SUSP);
651:
652: /* and clear RBD field */
653: off = IE_RFRAME_BUFDESC(sc->rframes, i);
654: sc->ie_bus_write16(sc, off, 0xffff);
655:
656: /* Remove fence from current tail */
657: off = IE_RFRAME_LAST(sc->rframes, sc->rftail);
658: sc->ie_bus_write16(sc, off, 0);
659:
660: if (++sc->rftail == sc->nframes)
661: sc->rftail = 0;
662: if (++sc->rfhead == sc->nframes)
663: sc->rfhead = 0;
664:
665: /* Pull the frame off the board */
666: if (drop) {
667: i82596_drop_frames(sc);
668: if ((status & IE_FD_RNR) != 0)
669: sc->rnr_expect = 1;
670: sc->sc_arpcom.ac_if.if_ierrors++;
671: } else if (i82596_readframe(sc, i) != 0)
672: return (1);
673: }
674:
675: if ((scbstatus & IE_ST_RNR) != 0) {
676:
677: /*
678: * Receiver went "Not Ready". We try to figure out
679: * whether this was an expected event based on past
680: * frame status values.
681: */
682:
683: if ((scbstatus & IE_RUS_SUSPEND) != 0) {
684: /*
685: * We use the "suspend on last frame" flag.
686: * Send a RU RESUME command in response, since
687: * we should have dealt with all completed frames
688: * by now.
689: */
690: printf("RINT: SUSPENDED; scbstatus=%b\n",
691: scbstatus, IE_ST_BITS);
692: if (i82596_start_cmd(sc, IE_RUC_RESUME, 0, 0, 0) == 0)
693: return (0);
694: printf("%s: RU RESUME command timed out\n",
695: sc->sc_dev.dv_xname);
696: return (1); /* Ask for a reset */
697: }
698:
699: if (sc->rnr_expect != 0) {
700: /*
701: * The RNR condition was announced in the previously
702: * completed frame. Assume the receive ring is Ok,
703: * so restart the receiver without further delay.
704: */
705: i82596_start_transceiver(sc);
706: sc->rnr_expect = 0;
707: return (0);
708:
709: } else if ((scbstatus & IE_RUS_NOSPACE) != 0) {
710: /*
711: * We saw no previous IF_FD_RNR flag.
712: * We check our ring invariants and, if ok,
713: * just restart the receiver at the current
714: * point in the ring.
715: */
716: if (i82596_chk_rx_ring(sc) != 0)
717: return (1);
718:
719: i82596_start_transceiver(sc);
720: sc->sc_arpcom.ac_if.if_ierrors++;
721: return (0);
722: } else
723: printf("%s: receiver not ready; scbstatus=%b\n",
724: sc->sc_dev.dv_xname, scbstatus, IE_ST_BITS);
725:
726: sc->sc_arpcom.ac_if.if_ierrors++;
727: return (1); /* Ask for a reset */
728: }
729:
730: return (0);
731: }
732:
733: /*
734: * Process a command-complete interrupt. These are only generated by the
735: * transmission of frames. This routine is deceptively simple, since most
736: * of the real work is done by i82596_start().
737: */
738: int
739: i82596_tint(sc, scbstatus)
740: struct ie_softc *sc;
741: int scbstatus;
742: {
743: register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
744: register int off, status;
745:
746: ifp->if_timer = 0;
747: ifp->if_flags &= ~IFF_OACTIVE;
748:
749: #ifdef I82596_DEBUG
750: if (sc->xmit_busy <= 0) {
751: printf("%s: i82596_tint: WEIRD:"
752: "xmit_busy=%d, xctail=%d, xchead=%d\n",
753: sc->sc_dev.dv_xname,
754: sc->xmit_busy, sc->xctail, sc->xchead);
755: return (0);
756: }
757: #endif
758:
759: off = IE_CMD_XMIT_STATUS(sc->xmit_cmds, sc->xctail);
760: status = sc->ie_bus_read16(sc, off);
761:
762: #ifdef I82596_DEBUG
763: if (sc->sc_debug & IED_TINT)
764: printf("%s: tint: SCB status %b; xmit status %b\n",
765: sc->sc_dev.dv_xname, scbstatus, IE_ST_BITS,
766: status, IE_XS_BITS);
767: #endif
768:
769: if ((status & (IE_STAT_COMPL|IE_STAT_BUSY)) == IE_STAT_BUSY) {
770: printf("%s: i82596_tint: command still busy;"
771: "status=%b; tail=%d\n", sc->sc_dev.dv_xname,
772: status, IE_XS_BITS, sc->xctail);
773: printf("iestatus = %b\n", scbstatus, IE_ST_BITS);
774: }
775:
776: if (status & IE_STAT_OK) {
777: ifp->if_opackets++;
778: ifp->if_collisions += (status & IE_XS_MAXCOLL);
779: } else {
780: ifp->if_oerrors++;
781: /*
782: * Check SQE and DEFERRED?
783: * What if more than one bit is set?
784: */
785: if (status & IE_STAT_ABORT)
786: printf("%s: send aborted\n", sc->sc_dev.dv_xname);
787: else if (status & IE_XS_NOCARRIER)
788: printf("%s: no carrier\n", sc->sc_dev.dv_xname);
789: else if (status & IE_XS_LOSTCTS)
790: printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
791: else if (status & IE_XS_UNDERRUN)
792: printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
793: else if (status & IE_XS_EXCMAX) {
794: printf("%s: too many collisions\n",
795: sc->sc_dev.dv_xname);
796: sc->sc_arpcom.ac_if.if_collisions += 16;
797: }
798: }
799:
800: /*
801: * If multicast addresses were added or deleted while transmitting,
802: * ie_mc_reset() set the want_mcsetup flag indicating that we
803: * should do it.
804: */
805: if (sc->want_mcsetup) {
806: ie_mc_setup(sc, IE_XBUF_ADDR(sc, sc->xctail));
807: sc->want_mcsetup = 0;
808: }
809:
810: /* Done with the buffer. */
811: sc->xmit_busy--;
812: sc->xctail = (sc->xctail + 1) % NTXBUF;
813:
814: /* Start the next packet, if any, transmitting. */
815: if (sc->xmit_busy > 0)
816: i82596_xmit(sc);
817:
818: i82596_start(ifp);
819: return (0);
820: }
821:
822: /*
823: * Get a range of receive buffer descriptors that represent one packet.
824: */
825: int
826: i82596_get_rbd_list(sc, start, end, pktlen)
827: struct ie_softc *sc;
828: u_int16_t *start;
829: u_int16_t *end;
830: int *pktlen;
831: {
832: int off, rbbase = sc->rbds;
833: int rbindex, count = 0;
834: int plen = 0;
835: int rbdstatus;
836:
837: *start = rbindex = sc->rbhead;
838:
839: do {
840: off = IE_RBD_STATUS(rbbase, rbindex);
841: bus_space_barrier(sc->bt, sc->bh, off, 2,
842: BUS_SPACE_BARRIER_READ);
843: rbdstatus = sc->ie_bus_read16(sc, off);
844: if ((rbdstatus & IE_RBD_USED) == 0) {
845: /*
846: * This means we are somehow out of sync. So, we
847: * reset the adapter.
848: */
849: #ifdef I82596_DEBUG
850: print_rbd(sc, rbindex);
851: #endif
852: log(LOG_ERR,
853: "%s: receive descriptors out of sync at %d\n",
854: sc->sc_dev.dv_xname, rbindex);
855: return (0);
856: }
857: plen += (rbdstatus & IE_RBD_CNTMASK);
858:
859: if (++rbindex == sc->nrxbuf)
860: rbindex = 0;
861:
862: ++count;
863: } while ((rbdstatus & IE_RBD_LAST) == 0);
864: *end = rbindex;
865: *pktlen = plen;
866: return (count);
867: }
868:
869:
870: /*
871: * Release a range of receive buffer descriptors after we've copied the packet.
872: */
873: void
874: i82596_release_rbd_list(sc, start, end)
875: struct ie_softc *sc;
876: u_int16_t start;
877: u_int16_t end;
878: {
879: register int off, rbbase = sc->rbds;
880: register int rbindex = start;
881:
882: do {
883: /* Clear buffer status */
884: off = IE_RBD_STATUS(rbbase, rbindex);
885: sc->ie_bus_write16(sc, off, 0);
886: if (++rbindex == sc->nrxbuf)
887: rbindex = 0;
888: } while (rbindex != end);
889:
890: /* Mark EOL at new tail */
891: rbindex = ((rbindex == 0) ? sc->nrxbuf : rbindex) - 1;
892: off = IE_RBD_BUFLEN(rbbase, rbindex);
893: sc->ie_bus_write16(sc, off, IE_RBUF_SIZE|IE_RBD_EOL);
894:
895: /* Remove EOL from current tail */
896: off = IE_RBD_BUFLEN(rbbase, sc->rbtail);
897: sc->ie_bus_write16(sc, off, IE_RBUF_SIZE);
898:
899: /* New head & tail pointer */
900: /* hmm, why have both? head is always (tail + 1) % NRXBUF */
901: sc->rbhead = end;
902: sc->rbtail = rbindex;
903: }
904:
905: /*
906: * Drop the packet at the head of the RX buffer ring.
907: * Called if the frame descriptor reports an error on this packet.
908: * Returns 1 if the buffer descriptor ring appears to be corrupt;
909: * and 0 otherwise.
910: */
911: int
912: i82596_drop_frames(sc)
913: struct ie_softc *sc;
914: {
915: u_int16_t bstart, bend;
916: int pktlen;
917:
918: if (!i82596_get_rbd_list(sc, &bstart, &bend, &pktlen))
919: return (1);
920: i82596_release_rbd_list(sc, bstart, bend);
921: return (0);
922: }
923:
924: /*
925: * Check the RX frame & buffer descriptor lists for our invariants,
926: * i.e.: EOL bit set iff. it is pointed at by the r*tail pointer.
927: *
928: * Called when the receive unit has stopped unexpectedly.
929: * Returns 1 if an inconsistency is detected; 0 otherwise.
930: *
931: * The Receive Unit is expected to be NOT RUNNING.
932: */
933: int
934: i82596_chk_rx_ring(sc)
935: struct ie_softc *sc;
936: {
937: int n, off, val;
938:
939: for (n = 0; n < sc->nrxbuf; n++) {
940: off = IE_RBD_BUFLEN(sc->rbds, n);
941: val = sc->ie_bus_read16(sc, off);
942: if ((n == sc->rbtail) ^ ((val & IE_RBD_EOL) != 0)) {
943: /* `rbtail' and EOL flag out of sync */
944: log(LOG_ERR,
945: "%s: rx buffer descriptors out of sync at %d\n",
946: sc->sc_dev.dv_xname, n);
947: return (1);
948: }
949:
950: /* Take the opportunity to clear the status fields here ? */
951: }
952:
953: for (n = 0; n < sc->nframes; n++) {
954: off = IE_RFRAME_LAST(sc->rframes, n);
955: val = sc->ie_bus_read16(sc, off);
956: if ((n == sc->rftail) ^ ((val & (IE_FD_EOL|IE_FD_SUSP)) != 0)) {
957: /* `rftail' and EOL flag out of sync */
958: log(LOG_ERR,
959: "%s: rx frame list out of sync at %d\n",
960: sc->sc_dev.dv_xname, n);
961: return (1);
962: }
963: }
964:
965: return (0);
966: }
967:
968: /*
969: * Read data off the interface, and turn it into an mbuf chain.
970: *
971: * This code is DRAMATICALLY different from the previous version; this
972: * version tries to allocate the entire mbuf chain up front, given the
973: * length of the data available. This enables us to allocate mbuf
974: * clusters in many situations where before we would have had a long
975: * chain of partially-full mbufs. This should help to speed up the
976: * operation considerably. (Provided that it works, of course.)
977: */
978: static __inline__ struct mbuf *
979: i82596_get(struct ie_softc *sc, int head, int totlen)
980: {
981: struct mbuf *m, *m0, *newm;
982: int off, len, resid;
983: int thisrboff, thismboff;
984: struct ether_header eh;
985:
986: /*
987: * Snarf the Ethernet header.
988: */
989: (sc->memcopyin)(sc, &eh, IE_RBUF_ADDR(sc, head),
990: sizeof(struct ether_header));
991:
992: resid = totlen;
993:
994: MGETHDR(m0, M_DONTWAIT, MT_DATA);
995: if (m0 == 0)
996: return (0);
997: m0->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
998: m0->m_pkthdr.len = totlen;
999: len = MHLEN;
1000: m = m0;
1001:
1002: /*
1003: * This loop goes through and allocates mbufs for all the data we will
1004: * be copying in. It does not actually do the copying yet.
1005: */
1006: while (totlen > 0) {
1007: if (totlen >= MINCLSIZE) {
1008: MCLGET(m, M_DONTWAIT);
1009: if ((m->m_flags & M_EXT) == 0)
1010: goto bad;
1011: len = MCLBYTES;
1012: }
1013:
1014: if (m == m0) {
1015: caddr_t newdata = (caddr_t)
1016: ALIGN(m->m_data + sizeof(struct ether_header)) -
1017: sizeof(struct ether_header);
1018: len -= newdata - m->m_data;
1019: m->m_data = newdata;
1020: }
1021:
1022: m->m_len = len = min(totlen, len);
1023:
1024: totlen -= len;
1025: if (totlen > 0) {
1026: MGET(newm, M_DONTWAIT, MT_DATA);
1027: if (newm == 0)
1028: goto bad;
1029: len = MLEN;
1030: m = m->m_next = newm;
1031: }
1032: }
1033:
1034: m = m0;
1035: thismboff = 0;
1036:
1037: /*
1038: * Copy the Ethernet header into the mbuf chain.
1039: */
1040: bcopy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
1041: thismboff = sizeof(struct ether_header);
1042: thisrboff = sizeof(struct ether_header);
1043: resid -= sizeof(struct ether_header);
1044:
1045: /*
1046: * Now we take the mbuf chain (hopefully only one mbuf most of the
1047: * time) and stuff the data into it. There are no possible failures
1048: * at or after this point.
1049: */
1050: while (resid > 0) {
1051: int thisrblen = IE_RBUF_SIZE - thisrboff,
1052: thismblen = m->m_len - thismboff;
1053: len = min(thisrblen, thismblen);
1054:
1055: off = IE_RBUF_ADDR(sc,head) + thisrboff;
1056: (sc->memcopyin)(sc, mtod(m, caddr_t) + thismboff, off, len);
1057: resid -= len;
1058:
1059: if (len == thismblen) {
1060: m = m->m_next;
1061: thismboff = 0;
1062: } else
1063: thismboff += len;
1064:
1065: if (len == thisrblen) {
1066: if (++head == sc->nrxbuf)
1067: head = 0;
1068: thisrboff = 0;
1069: } else
1070: thisrboff += len;
1071: }
1072:
1073: /*
1074: * Unless something changed strangely while we were doing the copy,
1075: * we have now copied everything in from the shared memory.
1076: * This means that we are done.
1077: */
1078: return (m0);
1079:
1080: bad:
1081: m_freem(m0);
1082: return (NULL);
1083: }
1084:
1085: /*
1086: * Read frame NUM from unit UNIT (pre-cached as IE).
1087: *
1088: * This routine reads the RFD at NUM, and copies in the buffers from the list
1089: * of RBD, then rotates the RBD list so that the receiver doesn't start
1090: * complaining. Trailers are DROPPED---there's no point in wasting time
1091: * on confusing code to deal with them. Hopefully, this machine will
1092: * never ARP for trailers anyway.
1093: */
1094: int
1095: i82596_readframe(sc, num)
1096: struct ie_softc *sc;
1097: int num; /* frame number to read */
1098: {
1099: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1100: struct mbuf *m;
1101: u_int16_t bstart, bend;
1102: int pktlen;
1103:
1104: if (i82596_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) {
1105: ifp->if_ierrors++;
1106: return (1);
1107: }
1108:
1109: m = i82596_get(sc, bstart, pktlen);
1110: i82596_release_rbd_list(sc, bstart, bend);
1111:
1112: if (m == 0) {
1113: sc->sc_arpcom.ac_if.if_ierrors++;
1114: return (0);
1115: }
1116:
1117: #ifdef I82596_DEBUG
1118: if (sc->sc_debug & IED_READFRAME) {
1119: struct ether_header *eh = mtod(m, struct ether_header *);
1120:
1121: printf("%s: frame from ether %s type 0x%x len %d\n",
1122: sc->sc_dev.dv_xname, ether_sprintf(eh->ether_shost),
1123: (u_int)eh->ether_type, pktlen);
1124: }
1125: #endif
1126:
1127: #if NBPFILTER > 0
1128: /* Check for a BPF filter; if so, hand it up. */
1129: if (ifp->if_bpf)
1130: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1131: #endif /* NBPFILTER > 0 */
1132:
1133: /*
1134: * Finally pass this packet up to higher layers.
1135: */
1136: ether_input_mbuf(ifp, m);
1137: ifp->if_ipackets++;
1138: return (0);
1139: }
1140:
1141:
1142: /*
1143: * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
1144: * command to the chip to be executed.
1145: */
1146: void
1147: i82596_xmit(sc)
1148: struct ie_softc *sc;
1149: {
1150: int off, cur, prev;
1151:
1152: cur = sc->xctail;
1153:
1154: #ifdef I82596_DEBUG
1155: if (sc->sc_debug & IED_XMIT)
1156: printf("%s: xmit buffer %d\n", sc->sc_dev.dv_xname, cur);
1157: #endif
1158:
1159: /*
1160: * Setup the transmit command.
1161: */
1162: sc->ie_bus_write16(sc, IE_CMD_XMIT_DESC(sc->xmit_cmds, cur),
1163: IE_XBD_ADDR(sc->xbds, cur));
1164:
1165: sc->ie_bus_write16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, cur), 0);
1166:
1167: if (sc->do_xmitnopchain) {
1168: /*
1169: * Gate this XMIT command to the following NOP
1170: */
1171: sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur),
1172: IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
1173: sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
1174: IE_CMD_XMIT | IE_CMD_INTR);
1175:
1176: /*
1177: * Loopback at following NOP
1178: */
1179: sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, cur), 0);
1180: sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, cur),
1181: IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
1182:
1183: /*
1184: * Gate preceding NOP to this XMIT command
1185: */
1186: prev = (cur + NTXBUF - 1) % NTXBUF;
1187: sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, prev), 0);
1188: sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, prev),
1189: IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
1190:
1191: off = IE_SCB_STATUS(sc->scb);
1192: bus_space_barrier(sc->bt, sc->bh, off, 2,
1193: BUS_SPACE_BARRIER_READ);
1194: if ((sc->ie_bus_read16(sc, off) & IE_CUS_ACTIVE) == 0) {
1195: printf("i82596_xmit: CU not active\n");
1196: i82596_start_transceiver(sc);
1197: }
1198: } else {
1199: sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds,cur),
1200: 0xffff);
1201:
1202: sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
1203: IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST);
1204:
1205: off = IE_SCB_CMDLST(sc->scb);
1206: sc->ie_bus_write16(sc, off, IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
1207: bus_space_barrier(sc->bt, sc->bh, off, 2,
1208: BUS_SPACE_BARRIER_WRITE);
1209:
1210: if (i82596_start_cmd(sc, IE_CUC_START, 0, 0, 1)) {
1211: #ifdef I82596_DEBUG
1212: if (sc->sc_debug & IED_XMIT)
1213: printf("%s: i82596_xmit: "
1214: "start xmit command timed out\n",
1215: sc->sc_dev.dv_xname);
1216: #endif
1217: }
1218: }
1219:
1220: sc->sc_arpcom.ac_if.if_timer = 5;
1221: }
1222:
1223:
1224: /*
1225: * Start transmission on an interface.
1226: */
1227: void
1228: i82596_start(ifp)
1229: struct ifnet *ifp;
1230: {
1231: struct ie_softc *sc = ifp->if_softc;
1232: struct mbuf *m0, *m;
1233: int buffer, head, xbase;
1234: u_short len;
1235:
1236: #ifdef I82596_DEBUG
1237: if (sc->sc_debug & IED_ENQ)
1238: printf("i82596_start(%p)\n", ifp);
1239: #endif
1240:
1241: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1242: return;
1243:
1244: for (;;) {
1245: if (sc->xmit_busy == NTXBUF) {
1246: ifp->if_flags |= IFF_OACTIVE;
1247: break;
1248: }
1249:
1250: IFQ_DEQUEUE(&ifp->if_snd, m0);
1251: if (m0 == 0)
1252: break;
1253:
1254: /* We need to use m->m_pkthdr.len, so require the header */
1255: if ((m0->m_flags & M_PKTHDR) == 0)
1256: panic("i82596_start: no header mbuf");
1257:
1258: #if NBPFILTER > 0
1259: /* Tap off here if there is a BPF listener. */
1260: if (ifp->if_bpf)
1261: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
1262: #endif
1263:
1264: if (m0->m_pkthdr.len > IE_TBUF_SIZE)
1265: printf("%s: tbuf overflow\n", sc->sc_dev.dv_xname);
1266:
1267: head = sc->xchead;
1268: sc->xchead = (head + 1) % NTXBUF;
1269: buffer = IE_XBUF_ADDR(sc, head);
1270:
1271: #ifdef I82596_DEBUG
1272: if (sc->sc_debug & IED_ENQ)
1273: printf("%s: fill buffer %d offset %x",
1274: sc->sc_dev.dv_xname, head, buffer);
1275: #endif
1276:
1277: for (m = m0; m != 0; m = m->m_next) {
1278: #ifdef I82596_DEBUG
1279: if (sc->sc_debug & IED_ENQ) {
1280: u_int8_t *e, *p = mtod(m, u_int8_t *);
1281: static int i;
1282: if (m == m0)
1283: i = 0;
1284: for (e = p + m->m_len; p < e; i++, p += 2) {
1285: if (!(i % 8))
1286: printf("\n%s:",
1287: sc->sc_dev.dv_xname);
1288: printf(" %02x%02x", p[0], p[1]);
1289: }
1290: }
1291: #endif
1292: (sc->memcopyout)(sc, mtod(m,caddr_t), buffer, m->m_len);
1293: buffer += m->m_len;
1294: }
1295:
1296: len = m0->m_pkthdr.len;
1297: if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
1298: (sc->memcopyout)(sc, padbuf, buffer,
1299: ETHER_MIN_LEN - ETHER_CRC_LEN - len);
1300: buffer += ETHER_MIN_LEN - ETHER_CRC_LEN - len;
1301: len = ETHER_MIN_LEN - ETHER_CRC_LEN;
1302: }
1303:
1304: #ifdef I82596_DEBUG
1305: if (sc->sc_debug & IED_ENQ)
1306: printf("\n");
1307: #endif
1308:
1309: m_freem(m0);
1310:
1311: /*
1312: * Setup the transmit buffer descriptor here, while we
1313: * know the packet's length.
1314: */
1315: xbase = sc->xbds;
1316: sc->ie_bus_write16(sc, IE_XBD_FLAGS(xbase, head),
1317: len | IE_TBD_EOL);
1318: sc->ie_bus_write16(sc, IE_XBD_NEXT(xbase, head), 0xffff);
1319: sc->ie_bus_write24(sc, IE_XBD_BUF(xbase, head),
1320: sc->sc_maddr + IE_XBUF_ADDR(sc, head));
1321:
1322: /* Start the first packet transmitting. */
1323: if (sc->xmit_busy++ == 0)
1324: i82596_xmit(sc);
1325: }
1326: }
1327:
1328: /*
1329: * Probe IE's ram setup [ Move all this into MD front-end!? ]
1330: * Use only if SCP and ISCP represent offsets into shared ram space.
1331: */
1332: int
1333: i82596_proberam(sc)
1334: struct ie_softc *sc;
1335: {
1336: int result, off;
1337:
1338: /* Put in 16-bit mode */
1339: off = IE_SCP_BUS_USE(sc->scp);
1340: (sc->ie_bus_write16)(sc, off, 0);
1341: bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_WRITE);
1342:
1343: /* Set the ISCP `busy' bit */
1344: off = IE_ISCP_BUSY(sc->iscp);
1345: (sc->ie_bus_write16)(sc, off, 1);
1346: bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_WRITE);
1347:
1348: if (sc->hwreset)
1349: (sc->hwreset)(sc, IE_CHIP_PROBE);
1350:
1351: (sc->chan_attn) (sc);
1352:
1353: DELAY(100); /* wait a while... */
1354:
1355: /* Read back the ISCP `busy' bit; it should be clear by now */
1356: off = IE_ISCP_BUSY(sc->iscp);
1357: bus_space_barrier(sc->bt, sc->bh, off, 1, BUS_SPACE_BARRIER_READ);
1358: result = (sc->ie_bus_read16)(sc, off) == 0;
1359:
1360: /* Acknowledge any interrupts we may have caused. */
1361: ie_ack(sc, IE_ST_WHENCE);
1362:
1363: return (result);
1364: }
1365:
1366: void
1367: i82596_reset(sc, hard)
1368: struct ie_softc *sc;
1369: int hard;
1370: {
1371: int s = splnet();
1372:
1373: #ifdef I82596_DEBUG
1374: if (hard)
1375: printf("%s: reset\n", sc->sc_dev.dv_xname);
1376: #endif
1377:
1378: /* Clear OACTIVE in case we're called from watchdog (frozen xmit). */
1379: sc->sc_arpcom.ac_if.if_timer = 0;
1380: sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
1381:
1382: /*
1383: * Stop i82596 dead in its tracks.
1384: */
1385: if (i82596_start_cmd(sc, IE_RUC_ABORT | IE_CUC_ABORT, 0, 0, 0)) {
1386: #ifdef I82596_DEBUG
1387: printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
1388: #endif
1389: }
1390:
1391: /*
1392: * This can really slow down the i82596_reset() on some cards, but it's
1393: * necessary to unwedge other ones (eg, the Sun VME ones) from certain
1394: * lockups.
1395: */
1396: if (hard && sc->hwreset)
1397: (sc->hwreset)(sc, IE_CARD_RESET);
1398:
1399: DELAY(100);
1400: ie_ack(sc, IE_ST_WHENCE);
1401:
1402: if ((sc->sc_arpcom.ac_if.if_flags & IFF_UP) != 0) {
1403: int retries=0; /* XXX - find out why init sometimes fails */
1404: while (retries++ < 2)
1405: if (i82596_init(sc) == 1)
1406: break;
1407: }
1408:
1409: splx(s);
1410: }
1411:
1412: void
1413: i82596_simple_command(sc, cmd, cmdbuf)
1414: struct ie_softc *sc;
1415: int cmd;
1416: int cmdbuf;
1417: {
1418: /* Setup a simple command */
1419: sc->ie_bus_write16(sc, IE_CMD_COMMON_STATUS(cmdbuf), 0);
1420: sc->ie_bus_write16(sc, IE_CMD_COMMON_CMD(cmdbuf), cmd | IE_CMD_LAST);
1421: sc->ie_bus_write16(sc, IE_CMD_COMMON_LINK(cmdbuf), 0xffff);
1422:
1423: /* Assign the command buffer to the SCB command list */
1424: sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), cmdbuf);
1425: }
1426:
1427: /*
1428: * Run the time-domain reflectometer.
1429: */
1430: void
1431: ie_run_tdr(sc, cmd)
1432: struct ie_softc *sc;
1433: int cmd;
1434: {
1435: int result, clocks;
1436:
1437: i82596_simple_command(sc, IE_CMD_TDR, cmd);
1438: (sc->ie_bus_write16)(sc, IE_CMD_TDR_TIME(cmd), 0);
1439:
1440: if (i82596_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0) ||
1441: !(sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)) & IE_STAT_OK))
1442: result = 0x10000; /* XXX */
1443: else
1444: result = sc->ie_bus_read16(sc, IE_CMD_TDR_TIME(cmd));
1445:
1446: /* Squash any pending interrupts */
1447: ie_ack(sc, IE_ST_WHENCE);
1448:
1449: if (result & IE_TDR_SUCCESS)
1450: return;
1451:
1452: clocks = result & IE_TDR_TIME;
1453: if (result & 0x10000)
1454: printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
1455: else if (result & IE_TDR_XCVR)
1456: printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
1457: else if (result & IE_TDR_OPEN)
1458: printf("%s: TDR detected an open %d clock%s away\n",
1459: sc->sc_dev.dv_xname, clocks, clocks == 1? "":"s");
1460: else if (result & IE_TDR_SHORT)
1461: printf("%s: TDR detected a short %d clock%s away\n",
1462: sc->sc_dev.dv_xname, clocks, clocks == 1? "":"s");
1463: else
1464: printf("%s: TDR returned unknown status 0x%x\n",
1465: sc->sc_dev.dv_xname, result);
1466: }
1467:
1468: /*
1469: * i82596_setup_bufs: set up the buffers
1470: *
1471: * We have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
1472: * this is to be used for the buffers. The chip indexs its control data
1473: * structures with 16 bit offsets, and it indexes actual buffers with
1474: * 24 bit addresses. So we should allocate control buffers first so that
1475: * we don't overflow the 16 bit offset field. The number of transmit
1476: * buffers is fixed at compile time.
1477: *
1478: */
1479: void
1480: i82596_setup_bufs(sc)
1481: struct ie_softc *sc;
1482: {
1483: int n, r, ptr = sc->buf_area; /* memory pool */
1484: int cl = 32;
1485:
1486: /*
1487: * step 0: zero memory and figure out how many recv buffers and
1488: * frames we can have.
1489: */
1490: ptr = (ptr + cl - 1) & ~(cl - 1); /* set alignment and stick with it */
1491:
1492: /*
1493: * step 1: lay out data structures in the shared-memory area
1494: */
1495:
1496: /* The no-op commands; used if "nop-chaining" is in effect */
1497: ptr += cl;
1498: sc->nop_cmds = ptr - 2;
1499: ptr += NTXBUF * 32;
1500:
1501: /* The transmit commands */
1502: ptr += cl;
1503: sc->xmit_cmds = ptr - 2;
1504: ptr += NTXBUF * 32;
1505:
1506: /* The transmit buffers descriptors */
1507: ptr += cl;
1508: sc->xbds = ptr - 2;
1509: ptr += NTXBUF * 32;
1510:
1511: /* The transmit buffers */
1512: sc->xbufs = ptr;
1513: ptr += NTXBUF * IE_TBUF_SIZE;
1514:
1515: ptr = (ptr + cl - 1) & ~(cl - 1); /* re-align.. just in case */
1516:
1517: /* Compute free space for RECV stuff */
1518: n = sc->buf_area_sz - (ptr - sc->buf_area);
1519:
1520: /* Compute size of one RECV frame */
1521: r = 64 + ((32 + IE_RBUF_SIZE) * B_PER_F);
1522:
1523: sc->nframes = n / r;
1524:
1525: if (sc->nframes <= 8)
1526: panic("ie: bogus buffer calc");
1527:
1528: sc->nrxbuf = sc->nframes * B_PER_F;
1529:
1530: /* The receive frame descriptors */
1531: ptr += cl;
1532: sc->rframes = ptr - 2;
1533: ptr += sc->nframes * 64;
1534:
1535: /* The receive buffer descriptors */
1536: ptr += cl;
1537: sc->rbds = ptr - 2;
1538: ptr += sc->nrxbuf * 32;
1539:
1540: /* The receive buffers */
1541: sc->rbufs = ptr;
1542: ptr += sc->nrxbuf * IE_RBUF_SIZE;
1543:
1544: #ifdef I82596_DEBUG
1545: printf("%s: %d frames %d bufs\n", sc->sc_dev.dv_xname, sc->nframes,
1546: sc->nrxbuf);
1547: #endif
1548:
1549: /*
1550: * step 2: link together the recv frames and set EOL on last one
1551: */
1552: for (n = 0; n < sc->nframes; n++) {
1553: int m = (n == sc->nframes - 1) ? 0 : n + 1;
1554:
1555: /* Clear status */
1556: sc->ie_bus_write16(sc, IE_RFRAME_STATUS(sc->rframes,n), 0);
1557:
1558: /* RBD link = NULL */
1559: sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,n),
1560: 0xffff);
1561:
1562: /* Make a circular list */
1563: sc->ie_bus_write16(sc, IE_RFRAME_NEXT(sc->rframes,n),
1564: IE_RFRAME_ADDR(sc->rframes,m));
1565:
1566: /* Mark last as EOL */
1567: sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes,n),
1568: ((m==0)? (IE_FD_EOL|IE_FD_SUSP) : 0));
1569: }
1570:
1571: /*
1572: * step 3: link the RBDs and set EOL on last one
1573: */
1574: for (n = 0; n < sc->nrxbuf; n++) {
1575: int m = (n == sc->nrxbuf - 1) ? 0 : n + 1;
1576:
1577: /* Clear status */
1578: sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds,n), 0);
1579:
1580: /* Make a circular list */
1581: sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds,n),
1582: IE_RBD_ADDR(sc->rbds,m));
1583:
1584: /* Link to data buffers */
1585: sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n),
1586: sc->sc_maddr + IE_RBUF_ADDR(sc, n));
1587: sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds,n),
1588: IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0));
1589: }
1590:
1591: /*
1592: * step 4: all xmit no-op commands loopback onto themselves
1593: */
1594: for (n = 0; n < NTXBUF; n++) {
1595: (sc->ie_bus_write16)(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0);
1596:
1597: (sc->ie_bus_write16)(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n),
1598: IE_CMD_NOP);
1599:
1600: (sc->ie_bus_write16)(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n),
1601: IE_CMD_NOP_ADDR(sc->nop_cmds, n));
1602: }
1603:
1604:
1605: /*
1606: * step 6: set the head and tail pointers on receive to keep track of
1607: * the order in which RFDs and RBDs are used.
1608: */
1609:
1610: /* Pointers to last packet sent and next available transmit buffer. */
1611: sc->xchead = sc->xctail = 0;
1612:
1613: /* Clear transmit-busy flag and set number of free transmit buffers. */
1614: sc->xmit_busy = 0;
1615:
1616: /*
1617: * Pointers to first and last receive frame.
1618: * The RFD pointed to by rftail is the only one that has EOL set.
1619: */
1620: sc->rfhead = 0;
1621: sc->rftail = sc->nframes - 1;
1622:
1623: /*
1624: * Pointers to first and last receive descriptor buffer.
1625: * The RBD pointed to by rbtail is the only one that has EOL set.
1626: */
1627: sc->rbhead = 0;
1628: sc->rbtail = sc->nrxbuf - 1;
1629:
1630: /* link in recv frames * and buffer into the scb. */
1631: #ifdef I82596_DEBUG
1632: printf("%s: reserved %d bytes\n",
1633: sc->sc_dev.dv_xname, ptr - sc->buf_area);
1634: #endif
1635: }
1636:
1637: int
1638: ie_cfg_setup(sc, cmd, promiscuous, manchester)
1639: struct ie_softc *sc;
1640: int cmd;
1641: int promiscuous, manchester;
1642: {
1643: int cmdresult, status;
1644:
1645: i82596_simple_command(sc, IE_CMD_CONFIG, cmd);
1646: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_CNT(cmd), 0x0c);
1647: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_FIFO(cmd), 8);
1648: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SAVEBAD(cmd), 0x40);
1649: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_ADDRLEN(cmd), 0x2e);
1650: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_PRIORITY(cmd), 0);
1651: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_IFS(cmd), 0x60);
1652: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SLOT_LOW(cmd), 0);
1653: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SLOT_HIGH(cmd), 0xf2);
1654: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_PROMISC(cmd),
1655: !!promiscuous | manchester << 2);
1656: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_CRSCDT(cmd), 0);
1657: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_MINLEN(cmd), 64);
1658: bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_JUNK(cmd), 0xff);
1659: bus_space_barrier(sc->bt, sc->bh, cmd, IE_CMD_CFG_SZ,
1660: BUS_SPACE_BARRIER_WRITE);
1661:
1662: cmdresult = i82596_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0);
1663: status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd));
1664: if (cmdresult != 0) {
1665: printf("%s: configure command timed out; status %b\n",
1666: sc->sc_dev.dv_xname, status, IE_STAT_BITS);
1667: return (0);
1668: }
1669: if ((status & IE_STAT_OK) == 0) {
1670: printf("%s: configure command failed; status %b\n",
1671: sc->sc_dev.dv_xname, status, IE_STAT_BITS);
1672: return (0);
1673: }
1674:
1675: /* Squash any pending interrupts */
1676: ie_ack(sc, IE_ST_WHENCE);
1677: return (1);
1678: }
1679:
1680: int
1681: ie_ia_setup(sc, cmdbuf)
1682: struct ie_softc *sc;
1683: int cmdbuf;
1684: {
1685: int cmdresult, status;
1686:
1687: i82596_simple_command(sc, IE_CMD_IASETUP, cmdbuf);
1688:
1689: (sc->memcopyout)(sc, sc->sc_arpcom.ac_enaddr,
1690: IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN);
1691:
1692: cmdresult = i82596_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
1693: status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
1694: if (cmdresult != 0) {
1695: printf("%s: individual address command timed out; status %b\n",
1696: sc->sc_dev.dv_xname, status, IE_STAT_BITS);
1697: return (0);
1698: }
1699: if ((status & IE_STAT_OK) == 0) {
1700: printf("%s: individual address command failed; status %b\n",
1701: sc->sc_dev.dv_xname, status, IE_STAT_BITS);
1702: return (0);
1703: }
1704:
1705: /* Squash any pending interrupts */
1706: ie_ack(sc, IE_ST_WHENCE);
1707: return (1);
1708: }
1709:
1710: /*
1711: * Run the multicast setup command.
1712: * Called at splnet().
1713: */
1714: int
1715: ie_mc_setup(sc, cmdbuf)
1716: struct ie_softc *sc;
1717: int cmdbuf;
1718: {
1719: int cmdresult, status;
1720:
1721: if (sc->mcast_count == 0)
1722: return (1);
1723:
1724: i82596_simple_command(sc, IE_CMD_MCAST, cmdbuf);
1725:
1726: (sc->memcopyout)(sc, (caddr_t)sc->mcast_addrs,
1727: IE_CMD_MCAST_MADDR(cmdbuf),
1728: sc->mcast_count * ETHER_ADDR_LEN);
1729:
1730: sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf),
1731: sc->mcast_count * ETHER_ADDR_LEN);
1732:
1733: /* Start the command */
1734: cmdresult = i82596_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
1735: status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
1736: if (cmdresult != 0) {
1737: printf("%s: multicast setup command timed out; status %b\n",
1738: sc->sc_dev.dv_xname, status, IE_STAT_BITS);
1739: return (0);
1740: }
1741: if ((status & IE_STAT_OK) == 0) {
1742: printf("%s: multicast setup command failed; status %b\n",
1743: sc->sc_dev.dv_xname, status, IE_STAT_BITS);
1744: return (0);
1745: }
1746:
1747: /* Squash any pending interrupts */
1748: ie_ack(sc, IE_ST_WHENCE);
1749: return (1);
1750: }
1751:
1752: /*
1753: * This routine takes the environment generated by check_ie_present() and adds
1754: * to it all the other structures we need to operate the adapter. This
1755: * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting
1756: * the receiver unit, and clearing interrupts.
1757: *
1758: * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
1759: */
1760: int
1761: i82596_init(sc)
1762: struct ie_softc *sc;
1763: {
1764: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1765: int cmd;
1766:
1767: sc->async_cmd_inprogress = 0;
1768:
1769: cmd = sc->buf_area;
1770:
1771: /*
1772: * Send the configure command first.
1773: */
1774: if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0)
1775: return (0);
1776:
1777: /*
1778: * Send the Individual Address Setup command.
1779: */
1780: if (ie_ia_setup(sc, cmd) == 0)
1781: return (0);
1782:
1783: /*
1784: * Run the time-domain reflectometer.
1785: */
1786: ie_run_tdr(sc, cmd);
1787:
1788: /*
1789: * Set the multi-cast filter, if any
1790: */
1791: if (ie_mc_setup(sc, cmd) == 0)
1792: return (0);
1793:
1794: /*
1795: * Acknowledge any interrupts we have generated thus far.
1796: */
1797: ie_ack(sc, IE_ST_WHENCE);
1798:
1799: /*
1800: * Set up the transmit and recv buffers.
1801: */
1802: i82596_setup_bufs(sc);
1803:
1804: if (sc->hwinit)
1805: (sc->hwinit)(sc);
1806:
1807: ifp->if_flags |= IFF_RUNNING;
1808: ifp->if_flags &= ~IFF_OACTIVE;
1809:
1810: if (NTXBUF < 2)
1811: sc->do_xmitnopchain = 0;
1812:
1813: i82596_start_transceiver(sc);
1814: return (1);
1815: }
1816:
1817: /*
1818: * Start the RU and possibly the CU unit
1819: */
1820: void
1821: i82596_start_transceiver(sc)
1822: struct ie_softc *sc;
1823: {
1824:
1825: /*
1826: * Start RU at current position in frame & RBD lists.
1827: */
1828: sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,sc->rfhead),
1829: IE_RBD_ADDR(sc->rbds, sc->rbhead));
1830:
1831: sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb),
1832: IE_RFRAME_ADDR(sc->rframes,sc->rfhead));
1833:
1834: if (sc->do_xmitnopchain) {
1835: /* Stop transmit command chain */
1836: if (i82596_start_cmd(sc, IE_CUC_SUSPEND|IE_RUC_SUSPEND, 0, 0, 0))
1837: printf("%s: CU/RU stop command timed out\n",
1838: sc->sc_dev.dv_xname);
1839:
1840: /* Start the receiver & transmitter chain */
1841: /* sc->scb->ie_command_list =
1842: IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/
1843: sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb),
1844: IE_CMD_NOP_ADDR(
1845: sc->nop_cmds,
1846: (sc->xctail + NTXBUF - 1) % NTXBUF));
1847:
1848: if (i82596_start_cmd(sc, IE_CUC_START|IE_RUC_START, 0, 0, 0))
1849: printf("%s: CU/RU command timed out\n",
1850: sc->sc_dev.dv_xname);
1851: } else {
1852: if (i82596_start_cmd(sc, IE_RUC_START, 0, 0, 0))
1853: printf("%s: RU command timed out\n",
1854: sc->sc_dev.dv_xname);
1855: }
1856: }
1857:
1858: void
1859: i82596_stop(sc)
1860: struct ie_softc *sc;
1861: {
1862:
1863: if (i82596_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0))
1864: printf("%s: i82596_stop: disable commands timed out\n",
1865: sc->sc_dev.dv_xname);
1866: }
1867:
1868: int
1869: i82596_ioctl(ifp, cmd, data)
1870: register struct ifnet *ifp;
1871: u_long cmd;
1872: caddr_t data;
1873: {
1874: struct ie_softc *sc = ifp->if_softc;
1875: struct ifaddr *ifa = (struct ifaddr *)data;
1876: struct ifreq *ifr = (struct ifreq *)data;
1877: int s, error = 0;
1878:
1879: s = splnet();
1880:
1881: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
1882: splx(s);
1883: return error;
1884: }
1885:
1886: switch(cmd) {
1887:
1888: case SIOCSIFADDR:
1889: ifp->if_flags |= IFF_UP;
1890:
1891: switch(ifa->ifa_addr->sa_family) {
1892: #ifdef INET
1893: case AF_INET:
1894: i82596_init(sc);
1895: arp_ifinit(&sc->sc_arpcom, ifa);
1896: break;
1897: #endif
1898: default:
1899: i82596_init(sc);
1900: break;
1901: }
1902: break;
1903:
1904: case SIOCSIFFLAGS:
1905: sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
1906: if ((ifp->if_flags & IFF_UP) == 0 &&
1907: (ifp->if_flags & IFF_RUNNING) != 0) {
1908: /*
1909: * If interface is marked down and it is running, then
1910: * stop it.
1911: */
1912: i82596_stop(sc);
1913: ifp->if_flags &= ~IFF_RUNNING;
1914: } else if ((ifp->if_flags & IFF_UP) != 0 &&
1915: (ifp->if_flags & IFF_RUNNING) == 0) {
1916: /*
1917: * If interface is marked up and it is stopped, then
1918: * start it.
1919: */
1920: i82596_init(sc);
1921: } else {
1922: /*
1923: * Reset the interface to pick up changes in any other
1924: * flags that affect hardware registers.
1925: */
1926: i82596_stop(sc);
1927: i82596_init(sc);
1928: }
1929: #ifdef I82596_DEBUG
1930: if (ifp->if_flags & IFF_DEBUG)
1931: sc->sc_debug = IED_ALL;
1932: else
1933: sc->sc_debug = 0;
1934: #endif
1935: break;
1936:
1937: case SIOCADDMULTI:
1938: case SIOCDELMULTI:
1939: error = (cmd == SIOCADDMULTI) ?
1940: ether_addmulti(ifr, &sc->sc_arpcom):
1941: ether_delmulti(ifr, &sc->sc_arpcom);
1942:
1943: if (error == ENETRESET) {
1944: /*
1945: * Multicast list has changed; set the hardware filter
1946: * accordingly.
1947: */
1948: if (ifp->if_flags & IFF_RUNNING)
1949: ie_mc_reset(sc);
1950: error = 0;
1951: }
1952: break;
1953:
1954: case SIOCGIFMEDIA:
1955: case SIOCSIFMEDIA:
1956: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1957: break;
1958:
1959: default:
1960: error = EINVAL;
1961: }
1962: splx(s);
1963: return (error);
1964: }
1965:
1966: void
1967: ie_mc_reset(sc)
1968: struct ie_softc *sc;
1969: {
1970: struct ether_multi *enm;
1971: struct ether_multistep step;
1972: int size;
1973:
1974: /*
1975: * Step through the list of addresses.
1976: */
1977: again:
1978: size = 0;
1979: sc->mcast_count = 0;
1980: ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
1981: while (enm) {
1982: size += 6;
1983: if (sc->mcast_count >= IE_MAXMCAST ||
1984: bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
1985: sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
1986: i82596_ioctl(&sc->sc_arpcom.ac_if,
1987: SIOCSIFFLAGS, (void *)0);
1988: return;
1989: }
1990: ETHER_NEXT_MULTI(step, enm);
1991: }
1992:
1993: if (size > sc->mcast_addrs_size) {
1994: /* Need to allocate more space */
1995: if (sc->mcast_addrs_size)
1996: free(sc->mcast_addrs, M_IFMADDR);
1997: sc->mcast_addrs = (char *)
1998: malloc(size, M_IFMADDR, M_WAITOK);
1999: sc->mcast_addrs_size = size;
2000: }
2001:
2002: /*
2003: * We've got the space; now copy the addresses
2004: */
2005: ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
2006: while (enm) {
2007: if (sc->mcast_count >= IE_MAXMCAST)
2008: goto again; /* Just in case */
2009:
2010: bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
2011: sc->mcast_count++;
2012: ETHER_NEXT_MULTI(step, enm);
2013: }
2014: sc->want_mcsetup = 1;
2015: }
2016:
2017: /*
2018: * Media change callback.
2019: */
2020: int
2021: i82596_mediachange(ifp)
2022: struct ifnet *ifp;
2023: {
2024: struct ie_softc *sc = ifp->if_softc;
2025:
2026: if (sc->sc_mediachange)
2027: return ((*sc->sc_mediachange)(sc));
2028: return (EINVAL);
2029: }
2030:
2031: /*
2032: * Media status callback.
2033: */
2034: void
2035: i82596_mediastatus(ifp, ifmr)
2036: struct ifnet *ifp;
2037: struct ifmediareq *ifmr;
2038: {
2039: struct ie_softc *sc = ifp->if_softc;
2040:
2041: if (sc->sc_mediastatus)
2042: (*sc->sc_mediastatus)(sc, ifmr);
2043: }
2044:
2045: #ifdef I82596_DEBUG
2046: void
2047: print_rbd(sc, n)
2048: struct ie_softc *sc;
2049: int n;
2050: {
2051:
2052: printf("RBD at %08x:\n status %b, next %04x, buffer %lx\n"
2053: "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds,n),
2054: sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds,n)), IE_STAT_BITS,
2055: sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds,n)),
2056: (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */
2057: sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds,n)));
2058: }
2059: #endif
CVSweb