Annotation of src/sys/dev/isa/if_iy.c, Revision 1.6
1.5 is 1: /* $NetBSD: if_iy.c,v 1.4 1996/05/12 23:52:53 mycroft Exp $ */
1.1 is 2: /* #define IYDEBUG */
3: /* #define IYMEMDEBUG */
4: /*-
5: * Copyright (c) 1996 Ignatios Souvatzis.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product contains software developed by Ignatios Souvatzis for
19: * the NetBSD project.
20: * 4. The names of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #include "bpfilter.h"
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/mbuf.h>
41: #include <sys/buf.h>
42: #include <sys/protosw.h>
43: #include <sys/socket.h>
44: #include <sys/ioctl.h>
45: #include <sys/errno.h>
46: #include <sys/syslog.h>
47: #include <sys/device.h>
48:
49: #include <net/if.h>
50: #include <net/if_types.h>
51: #include <net/if_dl.h>
52: #include <net/netisr.h>
53: #include <net/route.h>
54:
55: #if NBPFILTER > 0
56: #include <net/bpf.h>
57: #include <net/bpfdesc.h>
58: #endif
59:
60: #ifdef INET
61: #include <netinet/in.h>
62: #include <netinet/in_systm.h>
63: #include <netinet/in_var.h>
64: #include <netinet/ip.h>
65: #include <netinet/if_ether.h>
66: #endif
67:
68: #ifdef NS
69: #include <netns/ns.h>
70: #include <netns/ns_if.h>
71: #endif
72:
73: #include <vm/vm.h>
74:
75: #include <machine/cpu.h>
1.6 ! is 76: #include <machine/bus.h>
1.4 mycroft 77: #include <machine/intr.h>
1.1 is 78:
79: #include <dev/isa/isareg.h>
80: #include <dev/isa/isavar.h>
81: #include <dev/ic/i82595reg.h>
82:
83: #define ETHER_MIN_LEN 64
84: #define ETHER_MAX_LEN 1518
85:
86: /*
87: * Ethernet status, per interface.
88: */
89: struct iy_softc {
90: struct device sc_dev;
91: void *sc_ih;
92:
1.6 ! is 93: bus_chipset_tag_t sc_bc;
! 94: bus_io_handle_t sc_ioh;
! 95:
1.1 is 96: struct arpcom sc_arpcom;
97:
98: #define MAX_MBS 8
99: struct mbuf *mb[MAX_MBS];
100: int next_mb, last_mb;
101:
102: int mappedirq;
103:
104: int hard_vers;
105:
106: int promisc;
107:
108: int sram, tx_size, rx_size;
109:
110: int tx_start, tx_end, tx_last;
111: int rx_start;
112:
113: #ifdef IYDEBUG
114: int sc_debug;
115: #endif
116: };
117:
1.2 thorpej 118: void iywatchdog __P((struct ifnet *));
1.1 is 119: int iyioctl __P((struct ifnet *, u_long, caddr_t));
120: int iyintr __P((void *));
121: void iyinit __P((struct iy_softc *));
122: void iystop __P((struct iy_softc *));
123: void iystart __P((struct ifnet *));
124:
125: void iy_intr_rx __P((struct iy_softc *));
126: void iy_intr_tx __P((struct iy_softc *));
127: void eepro_reset_595 __P((struct iy_softc *));
128: int eepro_probe __P((struct iy_softc *, struct isa_attach_args *));
129: u_short eepro_read_eeprom __P((struct iy_softc *, int));
130:
131: void iyreset __P((struct iy_softc *));
132: void iy_readframe __P((struct iy_softc *, int));
133: void iy_drop_packet_buffer __P((struct iy_softc *));
134: void iy_find_mem_size __P((struct iy_softc *));
135: void iyrint __P((struct iy_softc *));
136: void iytint __P((struct iy_softc *));
137: void iyxmit __P((struct iy_softc *));
1.6 ! is 138: void iyget __P((struct iy_softc *, bus_chipset_tag_t, bus_io_handle_t, int));
1.1 is 139: void iymbuffill __P((void *));
140: void iymbufempty __P((void *));
141: void iyprobemem __P((struct iy_softc *));
142:
143: /*
144: * void iymeminit __P((void *, struct iy_softc *));
145: * static int iy_mc_setup __P((struct iy_softc *, void *));
146: * static void iy_mc_reset __P((struct iy_softc *));
147: */
148: #ifdef IYDEBUGX
149: void print_rbd __P((volatile struct iy_recv_buf_desc *));
150:
151: int in_ifrint = 0;
152: int in_iftint = 0;
153: #endif
154:
155: int iyprobe __P((struct device *, void *, void *));
156: void iyattach __P((struct device *, struct device *, void *));
157:
1.6 ! is 158: static u_int16_t eepromread __P((bus_chipset_tag_t, bus_io_handle_t,
! 159: bus_io_size_t, int));
1.1 is 160:
161: struct cfattach iy_ca = {
162: sizeof(struct iy_softc), iyprobe, iyattach
163: };
164:
165: struct cfdriver iy_cd = {
166: NULL, "iy", DV_IFNET
167: };
168:
169: static u_int8_t eepro_irqmap[] = EEPP_INTMAP;
170: static u_int8_t eepro_revirqmap[] = EEPP_RINTMAP;
171:
172: int
173: iyprobe(parent, match, aux)
174: struct device *parent;
175: void *match, *aux;
176: {
177: struct iy_softc *sc = match;
178: struct isa_attach_args *ia = aux;
179:
180: u_int16_t eaddr[8];
1.6 ! is 181:
! 182: bus_chipset_tag_t bc;
! 183: bus_io_handle_t ioh;
! 184:
1.1 is 185: int i;
186:
187: u_int16_t checksum = 0;
188: u_int16_t eepromtmp;
189: u_int8_t c, d;
190:
1.6 ! is 191: bc = ia->ia_bc;
1.1 is 192:
1.6 ! is 193: if (bus_io_map(bc, ia->ia_iobase, 16, &ioh))
! 194: goto out;
! 195:
! 196: /* check here for addresses already given to other devices */
1.1 is 197:
198:
199: /* try to find the round robin sig: */
200:
1.6 ! is 201: c = bus_io_read_1(bc, ioh, ID_REG);
1.1 is 202: if (c & ID_REG_MASK != ID_REG_SIG)
1.6 ! is 203: goto out;
1.1 is 204:
1.6 ! is 205: d = bus_io_read_1(bc, ioh, ID_REG);
1.1 is 206: if (d & ID_REG_MASK != ID_REG_SIG)
1.6 ! is 207: goto out;
1.1 is 208:
209: if (((d-c) & R_ROBIN_BITS) != 0x40)
1.6 ! is 210: goto out;
1.1 is 211:
1.6 ! is 212: d = bus_io_read_1(bc, ioh, ID_REG);
1.1 is 213: if (d & ID_REG_MASK != ID_REG_SIG)
1.6 ! is 214: goto out;
1.1 is 215:
216: if (((d-c) & R_ROBIN_BITS) != 0x80)
1.6 ! is 217: goto out;
1.1 is 218:
1.6 ! is 219: d = bus_io_read_1(bc, ioh, ID_REG);
1.1 is 220: if (d & ID_REG_MASK != ID_REG_SIG)
1.6 ! is 221: goto out;
1.1 is 222:
223: if (((d-c) & R_ROBIN_BITS) != 0xC0)
1.6 ! is 224: goto out;
1.1 is 225:
1.6 ! is 226: d = bus_io_read_1(bc, ioh, ID_REG);
1.1 is 227: if (d & ID_REG_MASK != ID_REG_SIG)
1.6 ! is 228: goto out;
1.1 is 229:
230: if (((d-c) & R_ROBIN_BITS) != 0x00)
1.6 ! is 231: goto out;
1.1 is 232:
233: #ifdef IYDEBUG
234: printf("eepro_probe verified working ID reg.\n");
235: #endif
236:
237: for (i=0; i<64; ++i) {
1.6 ! is 238: eepromtmp = eepromread(bc, ioh, EEPROM_REG, i);
1.1 is 239: checksum += eepromtmp;
240: if (i<(sizeof(eaddr)/sizeof(*eaddr)))
241: eaddr[i] = eepromtmp;
242: }
243: if (checksum != EEPP_CHKSUM)
244: printf("wrong EEPROM checksum 0x%x should be 0x%x\n",
245: checksum, EEPP_CHKSUM);
246:
247:
1.6 ! is 248: if ((eaddr[EEPPEther0] != eepromread(bc, ioh, EEPROM_REG, EEPPEther0a)) &&
! 249: (eaddr[EEPPEther1] != eepromread(bc, ioh, EEPROM_REG, EEPPEther1a)) &&
! 250: (eaddr[EEPPEther2] != eepromread(bc, ioh, EEPROM_REG, EEPPEther2a)))
1.1 is 251: printf("EEPROM Ethernet address differs from copy\n");
252:
253: sc->sc_arpcom.ac_enaddr[1] = eaddr[EEPPEther0] & 0xFF;
254: sc->sc_arpcom.ac_enaddr[0] = eaddr[EEPPEther0] >> 8;
255: sc->sc_arpcom.ac_enaddr[3] = eaddr[EEPPEther1] & 0xFF;
256: sc->sc_arpcom.ac_enaddr[2] = eaddr[EEPPEther1] >> 8;
257: sc->sc_arpcom.ac_enaddr[5] = eaddr[EEPPEther2] & 0xFF;
258: sc->sc_arpcom.ac_enaddr[4] = eaddr[EEPPEther2] >> 8;
259:
260: if (ia->ia_irq == IRQUNK)
261: ia->ia_irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
262:
263: if (ia->ia_irq >= sizeof(eepro_revirqmap))
1.6 ! is 264: goto out;
1.1 is 265:
266: if ((sc->mappedirq = eepro_revirqmap[ia->ia_irq]) == -1)
1.6 ! is 267: goto out;
1.1 is 268:
269: sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev;
270:
271: /* now lets reset the chip */
272:
1.6 ! is 273: bus_io_write_1(bc, ioh, COMMAND_REG, RESET_CMD);
1.1 is 274: delay(200);
275:
1.6 ! is 276: /*
! 277: * XXX Sould always unmap, but we can't yet.
! 278: * XXX Need to squish "indirect" first.
! 279: */
1.1 is 280: ia->ia_iosize = 16;
1.6 ! is 281:
! 282: sc->sc_bc = bc;
! 283: sc->sc_ioh = ioh;
1.1 is 284: return 1; /* found */
1.6 ! is 285: out:
! 286: bus_io_unmap(bc, ioh, 16);
! 287: return 0;
1.1 is 288: }
289:
290: void
291: iyattach(parent, self, aux)
292: struct device *parent, *self;
293: void *aux;
294: {
295: struct iy_softc *sc = (void *)self;
296: struct isa_attach_args *ia = aux;
297: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1.6 ! is 298: bus_chipset_tag_t bc;
! 299: bus_io_handle_t ioh;
! 300:
! 301: /*
! 302: * XXX Should re-map io and mem, but can't
! 303: * XXX until we squish "indirect" brokenness.
! 304: */
! 305: bc = sc->sc_bc; /* XXX */
! 306: ioh = sc->sc_ioh; /* XXX */
1.1 is 307:
1.2 thorpej 308: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
309: ifp->if_softc = sc;
1.1 is 310: ifp->if_start = iystart;
311: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
312: /* XXX todo: | IFF_MULTICAST */
313:
314: iyprobemem(sc);
315:
316: ifp->if_ioctl = iyioctl;
317: ifp->if_watchdog = iywatchdog;
318:
319: /* Attach the interface. */
320: if_attach(ifp);
321: ether_ifattach(ifp);
322: printf(": address %s, chip rev. %d, %d kB SRAM\n",
323: ether_sprintf(sc->sc_arpcom.ac_enaddr),
324: sc->hard_vers, sc->sram/1024);
325: #if NBPFILTER > 0
326: bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
327: sizeof(struct ether_header));
328: #endif
329:
330: sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
331: IPL_NET, iyintr, sc);
332: }
333:
334: void
335: iystop(sc)
336: struct iy_softc *sc;
337: {
1.6 ! is 338: bus_chipset_tag_t bc;
! 339: bus_io_handle_t ioh;
1.1 is 340: #ifdef IYDEBUG
341: u_int p, v;
342: #endif
343:
1.6 ! is 344: bc = sc->sc_bc;
! 345: ioh = sc->sc_ioh;
1.1 is 346:
1.6 ! is 347: bus_io_write_1(bc, ioh, COMMAND_REG, RCV_DISABLE_CMD);
1.1 is 348:
1.6 ! is 349: bus_io_write_1(bc, ioh, INT_MASK_REG, ALL_INTS);
! 350: bus_io_write_1(bc, ioh, STATUS_REG, ALL_INTS);
1.1 is 351:
1.6 ! is 352: bus_io_write_1(bc, ioh, COMMAND_REG, RESET_CMD);
1.1 is 353: delay(200);
354: #ifdef IYDEBUG
355: printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n",
356: sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
357: p = sc->tx_last;
358: if (!p)
359: p = sc->tx_start;
360: do {
1.6 ! is 361: bus_io_write_2(bc, ioh, HOST_ADDR_REG, p);
! 362: v = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 363: printf("0x%04x: %b ", p, v, "\020\006Ab\010Dn");
1.6 ! is 364: v = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 365: printf("0x%b", v, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL");
1.6 ! is 366: p = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 367: printf(" 0x%04x", p);
1.6 ! is 368: v = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 369: printf(" 0x%b\n", v, "\020\020Ch");
370:
371: } while (v & 0x8000);
372: #endif
373: sc->tx_start = sc->tx_end = sc->rx_size;
374: sc->tx_last = 0;
375: sc->sc_arpcom.ac_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
376:
377: iymbufempty((void *)sc);
378: }
379:
380: void
381: iyreset(sc)
382: struct iy_softc *sc;
383: {
384: int s;
385: s = splimp();
386: iystop(sc);
387: iyinit(sc);
388: splx(s);
389: }
390:
391: void
392: iyinit(sc)
393: struct iy_softc *sc;
394: {
395: int i;
396: unsigned temp;
397: struct ifnet *ifp;
1.6 ! is 398: bus_chipset_tag_t bc;
! 399: bus_io_handle_t ioh;
! 400:
! 401: bc = sc->sc_bc;
! 402: ioh = sc->sc_ioh;
1.1 is 403:
404: ifp = &sc->sc_arpcom.ac_if;
405: #ifdef IYDEBUG
406: printf("ifp is %p\n", ifp);
407: #endif
408:
1.6 ! is 409: bus_io_write_1(bc, ioh, 0, BANK_SEL(2));
1.1 is 410:
1.6 ! is 411: temp = bus_io_read_1(bc, ioh, EEPROM_REG);
1.1 is 412: if (temp & 0x10)
1.6 ! is 413: bus_io_write_1(bc, ioh, EEPROM_REG, temp & ~0x10);
1.1 is 414:
415: for (i=0; i<6; ++i) {
1.6 ! is 416: bus_io_write_1(bc, ioh, I_ADD(i), sc->sc_arpcom.ac_enaddr[i]);
1.1 is 417: }
418:
1.6 ! is 419: temp = bus_io_read_1(bc, ioh, REG1);
! 420: bus_io_write_1(bc, ioh, REG1, temp | XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP |
1.1 is 421: RCV_DISCARD_BAD);
422:
1.6 ! is 423: temp = bus_io_read_1(bc, ioh, RECV_MODES_REG);
! 424: bus_io_write_1(bc, ioh, RECV_MODES_REG, temp | MATCH_BRDCST);
1.1 is 425: #ifdef IYDEBUG
426: printf("%s: RECV_MODES were %b set to %b\n",
427: sc->sc_dev.dv_xname,
428: temp, "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA",
429: temp|MATCH_BRDCST,
430: "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA");
431: #endif
432:
433:
434: DELAY(500000); /* for the hardware to test for the connector */
435:
1.6 ! is 436: temp = bus_io_read_1(bc, ioh, MEDIA_SELECT);
1.1 is 437: #ifdef IYDEBUG
1.5 is 438: printf("%s: media select was 0x%b ", sc->sc_dev.dv_xname,
1.1 is 439: temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC");
440: #endif
1.5 is 441: temp = (temp & TEST_MODE_MASK);
1.6 ! is 442:
1.5 is 443: switch(ifp->if_flags & (IFF_LINK0 | IFF_LINK1)) {
444: case IFF_LINK0:
1.6 ! is 445: temp &= ~ (BNC_BIT | TPE_BIT);
! 446: break;
1.5 is 447:
448: case IFF_LINK1:
1.6 ! is 449: temp = temp & ~TPE_BIT | BNC_BIT;
! 450: break;
! 451:
1.5 is 452: case IFF_LINK0|IFF_LINK1:
1.6 ! is 453: temp = temp & ~BNC_BIT | TPE_BIT;
! 454: break;
1.5 is 455: default:
1.6 ! is 456: /* nothing; leave as it is */
1.5 is 457: }
458:
1.6 ! is 459:
! 460: bus_io_write_1(bc, ioh, MEDIA_SELECT, temp);
1.1 is 461: #ifdef IYDEBUG
462: printf("changed to 0x%b\n",
463: temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC");
464: #endif
465:
1.6 ! is 466: bus_io_write_1(bc, ioh, 0, BANK_SEL(1));
1.1 is 467:
1.6 ! is 468: temp = bus_io_read_1(bc, ioh, INT_NO_REG);
! 469: bus_io_write_1(bc, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
1.1 is 470:
471: #ifdef IYDEBUG
472: printf("%s: int no was %b\n", sc->sc_dev.dv_xname,
473: temp, "\020\4bad_irq\010flash/boot present");
1.6 ! is 474: temp = bus_io_read_1(bc, ioh, INT_NO_REG);
1.1 is 475: printf("%s: int no now 0x%02x\n", sc->sc_dev.dv_xname,
476: temp, "\020\4BAD IRQ\010flash/boot present");
477: #endif
478:
479:
1.6 ! is 480: bus_io_write_1(bc, ioh, RCV_LOWER_LIMIT_REG, 0);
! 481: bus_io_write_1(bc, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size - 2) >> 8);
! 482: bus_io_write_1(bc, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >> 8);
! 483: bus_io_write_1(bc, ioh, XMT_UPPER_LIMIT_REG, sc->sram >> 8);
1.1 is 484:
1.6 ! is 485: temp = bus_io_read_1(bc, ioh, REG1);
1.1 is 486: #ifdef IYDEBUG
487: printf("%s: HW access is %b\n", sc->sc_dev.dv_xname,
488: temp, "\020\2WORD_WIDTH\010INT_ENABLE");
489: #endif
1.6 ! is 490: bus_io_write_1(bc, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */
1.1 is 491:
492: #ifdef IYDEBUG
1.6 ! is 493: temp = bus_io_read_1(bc, ioh, REG1);
1.1 is 494: printf("%s: HW access is %b\n", sc->sc_dev.dv_xname,
495: temp, "\020\2WORD_WIDTH\010INT_ENABLE");
496: #endif
497:
1.6 ! is 498: bus_io_write_1(bc, ioh, 0, BANK_SEL(0));
1.1 is 499:
1.6 ! is 500: bus_io_write_1(bc, ioh, INT_MASK_REG, ALL_INTS & ~(RX_BIT|TX_BIT));
! 501: bus_io_write_1(bc, ioh, STATUS_REG, ALL_INTS); /* clear ints */
1.1 is 502:
1.6 ! is 503: bus_io_write_2(bc, ioh, RCV_START_LOW, 0);
! 504: bus_io_write_2(bc, ioh, RCV_STOP_LOW, sc->rx_size - 2);
1.1 is 505: sc->rx_start = 0;
506:
1.6 ! is 507: bus_io_write_1(bc, ioh, 0, SEL_RESET_CMD);
1.1 is 508: DELAY(200);
509:
1.6 ! is 510: bus_io_write_2(bc, ioh, XMT_ADDR_REG, sc->rx_size);
1.1 is 511:
512: sc->tx_start = sc->tx_end = sc->rx_size;
513: sc->tx_last = 0;
514:
1.6 ! is 515: bus_io_write_1(bc, ioh, 0, RCV_ENABLE_CMD);
1.1 is 516:
517: ifp->if_flags |= IFF_RUNNING;
518: ifp->if_flags &= ~IFF_OACTIVE;
519: }
520:
521: void
522: iystart(ifp)
523: struct ifnet *ifp;
524: {
525: struct iy_softc *sc;
1.6 ! is 526:
1.1 is 527:
528: struct mbuf *m0, *m;
529: u_int len, pad, last, end;
530: u_int llen, residual;
531: int avail;
532: caddr_t data;
533: u_int16_t resval, stat;
1.6 ! is 534: bus_chipset_tag_t bc;
! 535: bus_io_handle_t ioh;
1.1 is 536:
537: #ifdef IYDEBUG
538: printf("iystart called\n");
539: #endif
540: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
541: return;
542:
1.2 thorpej 543: sc = ifp->if_softc;
1.6 ! is 544: bc = sc->sc_bc;
! 545: ioh = sc->sc_ioh;
1.1 is 546:
547: while ((m0 = ifp->if_snd.ifq_head) != NULL) {
548: #ifdef IYDEBUG
549: printf("%s: trying to write another packet to the hardware\n",
550: sc->sc_dev.dv_xname);
551: #endif
552:
553: /* We need to use m->m_pkthdr.len, so require the header */
554: if ((m0->m_flags & M_PKTHDR) == 0)
555: panic("iystart: no header mbuf");
556:
557: len = m0->m_pkthdr.len;
558: pad = len & 1;
559:
560: #ifdef IYDEBUG
561: printf("%s: length is %d.\n", sc->sc_dev.dv_xname, len);
562: #endif
563: if (len < ETHER_MIN_LEN) {
564: pad = ETHER_MIN_LEN - len;
565: }
566:
567: if (len + pad > ETHER_MAX_LEN) {
568: /* packet is obviously too large: toss it */
569: ++ifp->if_oerrors;
570: IF_DEQUEUE(&ifp->if_snd, m0);
571: m_freem(m0);
572: continue;
573: }
574:
575: #if NBPFILTER > 0
576: if (ifp->if_bpf)
577: bpf_mtap(ifp->if_bpf, m0);
578: #endif
579:
580: avail = sc->tx_start - sc->tx_end;
581: if (avail <= 0)
582: avail += sc->tx_size;
583:
584: #ifdef IYDEBUG
585: printf("%s: avail is %d.\n", sc->sc_dev.dv_xname, avail);
586: #endif
587: /*
588: * we MUST RUN at splnet here ---
589: * XXX todo: or even turn off the boards ints ??? hm...
590: */
591:
592: /* See if there is room to put another packet in the buffer. */
593:
594: if ((len+pad+2*I595_XMT_HDRLEN) > avail) {
595: printf("%s: len = %d, avail = %d, setting OACTIVE\n",
596: sc->sc_dev.dv_xname, len, avail);
597: ifp->if_flags |= IFF_OACTIVE;
598: return;
599: }
600:
601: /* we know it fits in the hardware now, so dequeue it */
602: IF_DEQUEUE(&ifp->if_snd, m0);
603:
604: last = sc->tx_end;
605: end = last + pad + len + I595_XMT_HDRLEN;
606:
607: if (end >= sc->sram) {
608: if ((sc->sram - last) <= I595_XMT_HDRLEN) {
609: /* keep header in one piece */
610: last = sc->rx_size;
611: end = last + pad + len + I595_XMT_HDRLEN;
612: } else
613: end -= sc->tx_size;
614: }
615:
1.6 ! is 616: bus_io_write_2(bc, ioh, HOST_ADDR_REG, last);
! 617: bus_io_write_2(bc, ioh, MEM_PORT_REG, XMT_CMD);
! 618: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
! 619: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
! 620: bus_io_write_2(bc, ioh, MEM_PORT_REG, len + pad);
1.1 is 621:
622: residual = resval = 0;
623:
624: while ((m = m0)!=0) {
625: data = mtod(m, caddr_t);
626: llen = m->m_len;
627: if (residual) {
628: #ifdef IYDEBUG
629: printf("%s: merging residual with next mbuf.\n",
630: sc->sc_dev.dv_xname);
631: #endif
632: resval |= *data << 8;
1.6 ! is 633: bus_io_write_2(bc, ioh, MEM_PORT_REG, resval);
1.1 is 634: --llen;
635: ++data;
636: }
637: if (llen > 1)
1.6 ! is 638: bus_io_write_multi_2(bc, ioh, MEM_PORT_REG,
! 639: data, llen>>1);
1.1 is 640: residual = llen & 1;
641: if (residual) {
642: resval = *(data + llen - 1);
643: #ifdef IYDEBUG
644: printf("%s: got odd mbuf to send.\n",
645: sc->sc_dev.dv_xname);
646: #endif
647: }
648:
649: MFREE(m, m0);
650: }
651:
652: if (residual)
1.6 ! is 653: bus_io_write_2(bc, ioh, MEM_PORT_REG, resval);
1.1 is 654:
655: pad >>= 1;
656: while (pad-- > 0)
1.6 ! is 657: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
1.1 is 658:
659: #ifdef IYDEBUG
660: printf("%s: new last = 0x%x, end = 0x%x.\n",
661: sc->sc_dev.dv_xname, last, end);
662: printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n",
663: sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
664: #endif
665:
666: if (sc->tx_start != sc->tx_end) {
1.6 ! is 667: bus_io_write_2(bc, ioh, HOST_ADDR_REG, sc->tx_last + XMT_COUNT);
! 668: stat = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 669:
1.6 ! is 670: bus_io_write_2(bc, ioh, HOST_ADDR_REG, sc->tx_last + XMT_CHAIN);
! 671: bus_io_write_2(bc, ioh, MEM_PORT_REG, last);
! 672: bus_io_write_2(bc, ioh, MEM_PORT_REG, stat | CHAIN);
1.1 is 673: #ifdef IYDEBUG
674: printf("%s: setting 0x%x to 0x%x\n",
675: sc->sc_dev.dv_xname, sc->tx_last + XMT_COUNT,
676: stat | CHAIN);
677: #endif
678: }
1.6 ! is 679: stat = bus_io_read_2(bc, ioh, MEM_PORT_REG); /* dummy read */
1.1 is 680:
681: /* XXX todo: enable ints here if disabled */
682:
683: ++ifp->if_opackets;
684:
685: if (sc->tx_start == sc->tx_end) {
1.6 ! is 686: bus_io_write_2(bc, ioh, XMT_ADDR_REG, last);
! 687: bus_io_write_1(bc, ioh, 0, XMT_CMD);
1.1 is 688: sc->tx_start = last;
689: #ifdef IYDEBUG
690: printf("%s: writing 0x%x to XAR and giving XCMD\n",
691: sc->sc_dev.dv_xname, last);
692: #endif
693: } else {
1.6 ! is 694: bus_io_write_1(bc, ioh, 0, RESUME_XMT_CMD);
1.1 is 695: #ifdef IYDEBUG
696: printf("%s: giving RESUME_XCMD\n",
697: sc->sc_dev.dv_xname);
698: #endif
699: }
700: sc->tx_last = last;
701: sc->tx_end = end;
702: }
703: }
704:
705:
706: static __inline void
1.6 ! is 707: eepromwritebit(bc, ioh, ioff, what)
! 708: bus_chipset_tag_t bc;
! 709: bus_io_handle_t ioh;
! 710: bus_io_size_t ioff;
! 711: int what;
1.1 is 712: {
1.6 ! is 713: bus_io_write_1(bc, ioh, ioff, what);
1.1 is 714: delay(1);
1.6 ! is 715: bus_io_write_1(bc, ioh, ioff, what|EESK);
1.1 is 716: delay(1);
1.6 ! is 717: bus_io_write_1(bc, ioh, ioff, what);
1.1 is 718: delay(1);
719: }
720:
721: static __inline int
1.6 ! is 722: eepromreadbit(bc, ioh, ioff)
! 723: bus_chipset_tag_t bc;
! 724: bus_io_handle_t ioh;
! 725: bus_io_size_t ioff;
1.1 is 726: {
727: int b;
728:
1.6 ! is 729: bus_io_write_1(bc, ioh, ioff, EECS|EESK);
1.1 is 730: delay(1);
1.6 ! is 731: b = bus_io_read_1(bc, ioh, ioff);
! 732: bus_io_write_1(bc, ioh, ioff, EECS);
1.1 is 733: delay(1);
734:
735: return ((b & EEDO) != 0);
736: }
737:
738: static u_int16_t
1.6 ! is 739: eepromread(bc, ioh, ioff, offset)
! 740: bus_chipset_tag_t bc;
! 741: bus_io_handle_t ioh;
! 742: bus_io_size_t ioff;
! 743: int offset;
1.1 is 744: {
745: volatile int i;
746: volatile int j;
747: volatile u_int16_t readval;
748:
1.6 ! is 749: bus_io_write_1(bc, ioh, 0, BANK_SEL(2));
1.1 is 750: delay(1);
1.6 ! is 751: bus_io_write_1(bc, ioh, ioff, EECS); /* XXXX??? */
1.1 is 752: delay(1);
753:
1.6 ! is 754: eepromwritebit(bc, ioh, ioff, EECS|EEDI);
! 755: eepromwritebit(bc, ioh, ioff, EECS|EEDI);
! 756: eepromwritebit(bc, ioh, ioff, EECS);
1.1 is 757:
758: for (j=5; j>=0; --j) {
759: if ((offset>>j) & 1)
1.6 ! is 760: eepromwritebit(bc, ioh, ioff, EECS|EEDI);
1.1 is 761: else
1.6 ! is 762: eepromwritebit(bc, ioh, ioff, EECS);
1.1 is 763: }
764:
765: for (readval=0, i=0; i<16; ++i) {
766: readval<<=1;
1.6 ! is 767: readval |= eepromreadbit(bc, ioh, ioff);
1.1 is 768: }
769:
1.6 ! is 770: bus_io_write_1(bc, ioh, ioff, 0|EESK);
1.1 is 771: delay(1);
1.6 ! is 772: bus_io_write_1(bc, ioh, ioff, 0);
1.1 is 773:
1.6 ! is 774: bus_io_write_1(bc, ioh, ioff, BANK_SEL(0));
1.1 is 775:
776: return readval;
777: }
778:
779: /*
780: * Device timeout/watchdog routine. Entered if the device neglects to generate
781: * an interrupt after a transmit has been started on it.
782: */
783: void
1.2 thorpej 784: iywatchdog(ifp)
1.3 is 785: struct ifnet *ifp;
1.1 is 786: {
1.2 thorpej 787: struct iy_softc *sc = ifp->if_softc;
1.1 is 788:
789: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
790: ++sc->sc_arpcom.ac_if.if_oerrors;
791: iyreset(sc);
792: }
793:
794: /*
795: * What to do upon receipt of an interrupt.
796: */
797: int
798: iyintr(arg)
799: void *arg;
800: {
801: struct iy_softc *sc = arg;
1.6 ! is 802: bus_chipset_tag_t bc;
! 803: bus_io_handle_t ioh;
! 804:
1.1 is 805: register u_short status;
806:
1.6 ! is 807: bc = sc->sc_bc;
! 808: ioh = sc->sc_ioh;
! 809:
! 810: status = bus_io_read_1(bc, ioh, STATUS_REG);
1.1 is 811: #ifdef IYDEBUG
812: if (status & ALL_INTS) {
813: printf("%s: got interupt %b", sc->sc_dev.dv_xname, status,
814: "\020\1RX_STP\2RX\3TX\4EXEC");
815: if (status & EXEC_INT)
1.6 ! is 816: printf(" event %b\n", bus_io_read_1(bc, ioh, 0),
1.1 is 817: "\020\6ABORT");
818: else
819: printf("\n");
820: }
821: #endif
822: if ((status & (RX_INT | TX_INT) == 0))
823: return 0;
824:
825: if (status & RX_INT) {
826: iy_intr_rx(sc);
1.6 ! is 827: bus_io_write_1(bc, ioh, STATUS_REG, RX_INT);
1.1 is 828: } else if (status & TX_INT) {
829: iy_intr_tx(sc);
1.6 ! is 830: bus_io_write_1(bc, ioh, STATUS_REG, TX_INT);
1.1 is 831: }
832: return 1;
833: }
834:
835: void
1.6 ! is 836: iyget(sc, bc, ioh, rxlen)
! 837: struct iy_softc *sc;
! 838: bus_chipset_tag_t bc;
! 839: bus_io_handle_t ioh;
! 840: int rxlen;
1.1 is 841: {
842: struct mbuf *m, *top, **mp;
843: struct ether_header *eh;
844: struct ifnet *ifp;
845: int len;
846:
847: ifp = &sc->sc_arpcom.ac_if;
848:
849: m = sc->mb[sc->next_mb];
850: sc->mb[sc->next_mb] = 0;
851: if (m == 0) {
852: MGETHDR(m, M_DONTWAIT, MT_DATA);
853: if (m == 0)
854: goto dropped;
855: } else {
856: if (sc->last_mb == sc->next_mb)
857: timeout(iymbuffill, sc, 1);
858: sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
859: m->m_data = m->m_pktdat;
860: m->m_flags = M_PKTHDR;
861: }
862: m->m_pkthdr.rcvif = ifp;
863: m->m_pkthdr.len = rxlen;
864: len = MHLEN;
865: top = 0;
866: mp = ⊤
867:
868: while (rxlen > 0) {
869: if (top) {
870: m = sc->mb[sc->next_mb];
871: sc->mb[sc->next_mb] = 0;
872: if (m == 0) {
873: MGET(m, M_DONTWAIT, MT_DATA);
874: if (m == 0) {
875: m_freem(top);
876: goto dropped;
877: }
878: } else {
879: sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
880: }
881: len = MLEN;
882: }
883: if (rxlen >= MINCLSIZE) {
884: MCLGET(m, M_DONTWAIT);
885: if (m->m_flags & M_EXT)
886: len = MCLBYTES;
887: }
888: len = min(rxlen, len);
889: if (len > 1) {
890: len &= ~1;
1.6 ! is 891:
! 892: bus_io_read_multi_2(bc, ioh, MEM_PORT_REG,
! 893: mtod(m, caddr_t), len/2);
1.1 is 894: } else {
895: #ifdef IYDEBUG
896: printf("%s: received odd mbuf\n", sc->sc_dev.dv_xname);
897: #endif
1.6 ! is 898: *(mtod(m, caddr_t)) = bus_io_read_2(bc, ioh,
! 899: MEM_PORT_REG);
1.1 is 900: }
901: m->m_len = len;
902: rxlen -= len;
903: *mp = m;
904: mp = &m->m_next;
905: }
906: /* XXX receive the top here */
907: ++ifp->if_ipackets;
908:
909: eh = mtod(top, struct ether_header *);
910:
911: #if NBPFILTER > 0
912: if (ifp->if_bpf) {
913: bpf_mtap(ifp->if_bpf, top);
914: if ((ifp->if_flags & IFF_PROMISC) &&
915: (eh->ether_dhost[0] & 1) == 0 &&
916: bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
917: sizeof(eh->ether_dhost)) != 0) {
918: m_freem(top);
919: return;
920: }
921: }
922: #endif
923: m_adj(top, sizeof(struct ether_header));
924: ether_input(ifp, eh, top);
925: return;
926:
927: dropped:
928: ++ifp->if_ierrors;
929: return;
930: }
931: void
932: iy_intr_rx(sc)
933: struct iy_softc *sc;
934: {
935: struct ifnet *ifp;
1.6 ! is 936: bus_chipset_tag_t bc;
! 937: bus_io_handle_t ioh;
! 938:
1.1 is 939: u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen;
940:
1.6 ! is 941: bc = sc->sc_bc;
! 942: ioh = sc->sc_ioh;
1.1 is 943: ifp = &sc->sc_arpcom.ac_if;
944:
945: rxadrs = sc->rx_start;
1.6 ! is 946: bus_io_write_2(bc, ioh, HOST_ADDR_REG, rxadrs);
! 947: rxevnt = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 948: rxnext = 0;
949:
950: while (rxevnt == RCV_DONE) {
1.6 ! is 951: rxstatus = bus_io_read_2(bc, ioh, MEM_PORT_REG);
! 952: rxnext = bus_io_read_2(bc, ioh, MEM_PORT_REG);
! 953: rxlen = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 954: #ifdef IYDEBUG
955: printf("%s: pck at 0x%04x stat %b next 0x%x len 0x%x\n",
956: sc->sc_dev.dv_xname, rxadrs, rxstatus,
957: "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR"
958: "\014CRCERR\015LENERR\016RCVOK\020TYP",
959: rxnext, rxlen);
960: #endif
1.6 ! is 961: iyget(sc, bc, ioh, rxlen);
1.1 is 962:
963: /* move stop address */
1.6 ! is 964: bus_io_write_2(bc, ioh, RCV_STOP_LOW,
1.1 is 965: rxnext == 0 ? sc->rx_size - 2 : rxnext - 2);
966:
1.6 ! is 967: bus_io_write_2(bc, ioh, HOST_ADDR_REG, rxnext);
1.1 is 968: rxadrs = rxnext;
1.6 ! is 969: rxevnt = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 970: }
971: sc->rx_start = rxnext;
972: }
973:
974: void
975: iy_intr_tx(sc)
976: struct iy_softc *sc;
977: {
1.6 ! is 978: bus_chipset_tag_t bc;
! 979: bus_io_handle_t ioh;
1.1 is 980: struct ifnet *ifp;
981: u_int txstatus, txstat2, txlen, txnext;
982:
983: ifp = &sc->sc_arpcom.ac_if;
1.6 ! is 984: bc = sc->sc_bc;
! 985: ioh = sc->sc_ioh;
! 986:
1.1 is 987: while (sc->tx_start != sc->tx_end) {
1.6 ! is 988: bus_io_write_2(bc, ioh, HOST_ADDR_REG, sc->tx_start);
! 989: txstatus = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 990: if ((txstatus & (TX_DONE|CMD_MASK)) != (TX_DONE|XMT_CMD))
991: break;
992:
1.6 ! is 993: txstat2 = bus_io_read_2(bc, ioh, MEM_PORT_REG);
! 994: txnext = bus_io_read_2(bc, ioh, MEM_PORT_REG);
! 995: txlen = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1 is 996: #ifdef IYDEBUG
997: printf("txstat 0x%x stat2 0x%b next 0x%x len 0x%x\n",
998: txstatus, txstat2, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF"
999: "\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL",
1000: txnext, txlen);
1001: #endif
1002: if (txlen & CHAIN)
1003: sc->tx_start = txnext;
1004: else
1005: sc->tx_start = sc->tx_end;
1006: ifp->if_flags &= ~IFF_OACTIVE;
1007:
1008: if ((txstat2 & 0x2000) == 0)
1009: ++ifp->if_oerrors;
1010: if (txstat2 & 0x000f)
1011: ifp->if_oerrors += txstat2 & 0x000f;
1012: }
1013: ifp->if_flags &= ~IFF_OACTIVE;
1014: }
1015:
1016: #if 0
1017: /*
1018: * Compare two Ether/802 addresses for equality, inlined and unrolled for
1019: * speed. I'd love to have an inline assembler version of this...
1020: */
1021: static inline int
1022: ether_equal(one, two)
1023: u_char *one, *two;
1024: {
1025:
1026: if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] ||
1027: one[3] != two[3] || one[4] != two[4] || one[5] != two[5])
1028: return 0;
1029: return 1;
1030: }
1031:
1032: /*
1033: * Check for a valid address. to_bpf is filled in with one of the following:
1034: * 0 -> BPF doesn't get this packet
1035: * 1 -> BPF does get this packet
1036: * 2 -> BPF does get this packet, but we don't
1037: * Return value is true if the packet is for us, and false otherwise.
1038: *
1039: * This routine is a mess, but it's also critical that it be as fast
1040: * as possible. It could be made cleaner if we can assume that the
1041: * only client which will fiddle with IFF_PROMISC is BPF. This is
1042: * probably a good assumption, but we do not make it here. (Yet.)
1043: */
1044: static inline int
1045: check_eh(sc, eh, to_bpf)
1046: struct iy_softc *sc;
1047: struct ether_header *eh;
1048: int *to_bpf;
1049: {
1050: int i;
1051:
1052: switch (sc->promisc) {
1053: case IFF_ALLMULTI:
1054: /*
1055: * Receiving all multicasts, but no unicasts except those
1056: * destined for us.
1057: */
1058: #if NBPFILTER > 0
1059: *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); /* BPF gets this packet if anybody cares */
1060: #endif
1061: if (eh->ether_dhost[0] & 1)
1062: return 1;
1063: if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
1064: return 1;
1065: return 0;
1066:
1067: case IFF_PROMISC:
1068: /*
1069: * Receiving all packets. These need to be passed on to BPF.
1070: */
1071: #if NBPFILTER > 0
1072: *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
1073: #endif
1074: /* If for us, accept and hand up to BPF */
1075: if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
1076: return 1;
1077:
1078: #if NBPFILTER > 0
1079: if (*to_bpf)
1080: *to_bpf = 2; /* we don't need to see it */
1081: #endif
1082:
1083: /*
1084: * Not a multicast, so BPF wants to see it but we don't.
1085: */
1086: if (!(eh->ether_dhost[0] & 1))
1087: return 1;
1088:
1089: /*
1090: * If it's one of our multicast groups, accept it and pass it
1091: * up.
1092: */
1093: for (i = 0; i < sc->mcast_count; i++) {
1094: if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) {
1095: #if NBPFILTER > 0
1096: if (*to_bpf)
1097: *to_bpf = 1;
1098: #endif
1099: return 1;
1100: }
1101: }
1102: return 1;
1103:
1104: case IFF_ALLMULTI | IFF_PROMISC:
1105: /*
1106: * Acting as a multicast router, and BPF running at the same
1107: * time. Whew! (Hope this is a fast machine...)
1108: */
1109: #if NBPFILTER > 0
1110: *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
1111: #endif
1112: /* We want to see multicasts. */
1113: if (eh->ether_dhost[0] & 1)
1114: return 1;
1115:
1116: /* We want to see our own packets */
1117: if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
1118: return 1;
1119:
1120: /* Anything else goes to BPF but nothing else. */
1121: #if NBPFILTER > 0
1122: if (*to_bpf)
1123: *to_bpf = 2;
1124: #endif
1125: return 1;
1126:
1127: case 0:
1128: /*
1129: * Only accept unicast packets destined for us, or multicasts
1130: * for groups that we belong to. For now, we assume that the
1131: * '586 will only return packets that we asked it for. This
1132: * isn't strictly true (it uses hashing for the multicast
1133: * filter), but it will do in this case, and we want to get out
1134: * of here as quickly as possible.
1135: */
1136: #if NBPFILTER > 0
1137: *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
1138: #endif
1139: return 1;
1140: }
1141:
1142: #ifdef DIAGNOSTIC
1143: panic("check_eh: impossible");
1144: #endif
1145: }
1146: #endif
1147:
1148: int
1149: iyioctl(ifp, cmd, data)
1150: register struct ifnet *ifp;
1151: u_long cmd;
1152: caddr_t data;
1153: {
1154: struct iy_softc *sc;
1155: struct ifaddr *ifa;
1156: struct ifreq *ifr;
1157: int s, error = 0;
1158:
1.2 thorpej 1159: sc = ifp->if_softc;
1.1 is 1160: ifa = (struct ifaddr *)data;
1161: ifr = (struct ifreq *)data;
1162:
1163: #ifdef IYDEBUG
1.2 thorpej 1164: printf("iyioctl called with ifp 0x%p (%s) cmd 0x%x data 0x%p\n",
1165: ifp, ifp->if_xname, cmd, data);
1.1 is 1166: #endif
1167:
1168: s = splimp();
1169:
1170: switch (cmd) {
1171:
1172: case SIOCSIFADDR:
1173: ifp->if_flags |= IFF_UP;
1174:
1175: switch (ifa->ifa_addr->sa_family) {
1176: #ifdef INET
1177: case AF_INET:
1178: iyinit(sc);
1179: arp_ifinit(&sc->sc_arpcom, ifa);
1180: break;
1181: #endif
1182: #ifdef NS
1183: /* XXX - This code is probably wrong. */
1184: case AF_NS:
1185: {
1186: struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1187:
1188: if (ns_nullhost(*ina))
1189: ina->x_host =
1190: *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
1191: else
1192: bcopy(ina->x_host.c_host,
1193: sc->sc_arpcom.ac_enaddr,
1194: sizeof(sc->sc_arpcom.ac_enaddr));
1195: /* Set new address. */
1196: iyinit(sc);
1197: break;
1198: }
1199: #endif /* NS */
1200: default:
1201: iyinit(sc);
1202: break;
1203: }
1204: break;
1205:
1206: case SIOCSIFFLAGS:
1207: sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
1208: if ((ifp->if_flags & IFF_UP) == 0 &&
1209: (ifp->if_flags & IFF_RUNNING) != 0) {
1210: /*
1211: * If interface is marked down and it is running, then
1212: * stop it.
1213: */
1214: iystop(sc);
1215: ifp->if_flags &= ~IFF_RUNNING;
1216: } else if ((ifp->if_flags & IFF_UP) != 0 &&
1217: (ifp->if_flags & IFF_RUNNING) == 0) {
1218: /*
1219: * If interface is marked up and it is stopped, then
1220: * start it.
1221: */
1222: iyinit(sc);
1223: } else {
1224: /*
1225: * Reset the interface to pick up changes in any other
1226: * flags that affect hardware registers.
1227: */
1228: iystop(sc);
1229: iyinit(sc);
1230: }
1231: #ifdef IYDEBUGX
1232: if (ifp->if_flags & IFF_DEBUG)
1233: sc->sc_debug = IFY_ALL;
1234: else
1235: sc->sc_debug = 0;
1236: #endif
1237: break;
1238:
1239: #if 0 /* XXX */
1240: case SIOCADDMULTI:
1241: case SIOCDELMULTI:
1242: error = (cmd == SIOCADDMULTI) ?
1243: ether_addmulti(ifr, &sc->sc_arpcom):
1244: ether_delmulti(ifr, &sc->sc_arpcom);
1245:
1246: if (error == ENETRESET) {
1247: /*
1248: * Multicast list has changed; set the hardware filter
1249: * accordingly.
1250: */
1251: iy_mc_reset(sc); /* XXX */
1252: error = 0;
1253: }
1254: break;
1255: #endif
1256: default:
1257: error = EINVAL;
1258: }
1259: splx(s);
1260: return error;
1261: }
1262:
1263: #if 0
1264: static void
1265: iy_mc_reset(sc)
1266: struct iy_softc *sc;
1267: {
1268: struct ether_multi *enm;
1269: struct ether_multistep step;
1270:
1271: /*
1272: * Step through the list of addresses.
1273: */
1274: sc->mcast_count = 0;
1275: ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
1276: while (enm) {
1277: if (sc->mcast_count >= MAXMCAST ||
1278: bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
1279: sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
1280: iyioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
1281: goto setflag;
1282: }
1283:
1284: bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
1285: sc->mcast_count++;
1286: ETHER_NEXT_MULTI(step, enm);
1287: }
1288: setflag:
1289: sc->want_mcsetup = 1;
1290: }
1291:
1292: #ifdef IYDEBUG
1293: void
1294: print_rbd(rbd)
1295: volatile struct ie_recv_buf_desc *rbd;
1296: {
1297:
1298: printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
1299: "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
1300: rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
1301: rbd->mbz);
1302: }
1303: #endif
1304: #endif
1305:
1306: void
1307: iymbuffill(arg)
1308: void *arg;
1309: {
1310: struct iy_softc *sc = (struct iy_softc *)arg;
1311: int s, i;
1312:
1313: s = splimp();
1314: i = sc->last_mb;
1315: do {
1316: if (sc->mb[i] == NULL)
1317: MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1318: if (sc->mb[i] == NULL)
1319: break;
1320: i = (i + 1) % MAX_MBS;
1321: } while (i != sc->next_mb);
1322: sc->last_mb = i;
1323: /* If the queue was not filled, try again. */
1324: if (sc->last_mb != sc->next_mb)
1325: timeout(iymbuffill, sc, 1);
1326: splx(s);
1327: }
1328:
1329:
1330: void
1331: iymbufempty(arg)
1332: void *arg;
1333: {
1334: struct iy_softc *sc = (struct iy_softc *)arg;
1335: int s, i;
1336:
1337: s = splimp();
1338: for (i = 0; i<MAX_MBS; i++) {
1339: if (sc->mb[i]) {
1340: m_freem(sc->mb[i]);
1341: sc->mb[i] = NULL;
1342: }
1343: }
1344: sc->last_mb = sc->next_mb = 0;
1345: untimeout(iymbuffill, sc);
1346: splx(s);
1347: }
1348:
1349: void
1350: iyprobemem(sc)
1351: struct iy_softc *sc;
1352: {
1.6 ! is 1353: bus_chipset_tag_t bc;
! 1354: bus_io_handle_t ioh;
1.1 is 1355: int testing;
1356:
1.6 ! is 1357: bc = sc->sc_bc;
! 1358: ioh = sc->sc_ioh;
1.1 is 1359:
1.6 ! is 1360: bus_io_write_2(bc, ioh, HOST_ADDR_REG, 4096-2);
! 1361: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
1.1 is 1362:
1363: for (testing=65536; testing >= 4096; testing >>= 1) {
1.6 ! is 1364: bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
! 1365: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0xdead);
! 1366: bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
! 1367: if (bus_io_read_2(bc, ioh, MEM_PORT_REG) != 0xdead) {
1.1 is 1368: #ifdef IYMEMDEBUG
1369: printf("%s: Didn't keep 0xdead at 0x%x\n",
1370: sc->sc_dev.dv_xname, testing-2);
1371: #endif
1372: continue;
1373: }
1374:
1.6 ! is 1375: bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
! 1376: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0xbeef);
! 1377: bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
! 1378: if (bus_io_read_2(bc, ioh, MEM_PORT_REG) != 0xbeef) {
1.1 is 1379: #ifdef IYMEMDEBUG
1380: printf("%s: Didn't keep 0xbeef at 0x%x\n",
1381: sc->sc_dev.dv_xname, testing-2);
1382: #endif
1383: continue;
1384: }
1385:
1.6 ! is 1386: bus_io_write_2(bc, ioh, HOST_ADDR_REG, 0);
! 1387: bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
! 1388: bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing >> 1);
! 1389: bus_io_write_2(bc, ioh, MEM_PORT_REG, testing >> 1);
! 1390: bus_io_write_2(bc, ioh, HOST_ADDR_REG, 0);
! 1391: if (bus_io_read_2(bc, ioh, MEM_PORT_REG) == (testing >> 1)) {
1.1 is 1392: #ifdef IYMEMDEBUG
1393: printf("%s: 0x%x alias of 0x0\n",
1394: sc->sc_dev.dv_xname, testing >> 1);
1395: #endif
1396: continue;
1397: }
1398:
1399: break;
1400: }
1401:
1402: sc->sram = testing;
1403:
1404: switch(testing) {
1405: case 65536:
1406: /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */
1407: sc->rx_size = 44*1024;
1408: break;
1409:
1410: case 32768:
1411: /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */
1412: sc->rx_size = 22*1024;
1413: break;
1414:
1415: case 16384:
1416: /* 1 NFS packet + overhead RX, 4 big packets TX */
1417: sc->rx_size = 10*1024;
1418: break;
1419: default:
1420: sc->rx_size = testing/2;
1421: break;
1422: }
1423: sc->tx_size = testing - sc->rx_size;
1424: }
CVSweb <webmaster@jp.NetBSD.org>