if_iy.c revision 1.112 1 /* $NetBSD: if_iy.c,v 1.112 2020/01/06 07:15:03 msaitoh Exp $ */
2 /* #define IYDEBUG */
3 /* #define IYMEMDEBUG */
4
5 /*-
6 * Copyright (c) 1996,2001 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Ignatios Souvatzis.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Supported hardware:
36 *
37 * - Intel EtherExpress Pro/10.
38 * - possibly other boards using the i82595 chip and no special tweaks.
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: if_iy.c,v 1.112 2020/01/06 07:15:03 msaitoh Exp $");
43
44 #include "opt_inet.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/mbuf.h>
49 #include <sys/buf.h>
50 #include <sys/protosw.h>
51 #include <sys/socket.h>
52 #include <sys/ioctl.h>
53 #include <sys/errno.h>
54 #include <sys/syslog.h>
55 #include <sys/device.h>
56 #include <sys/endian.h>
57 #include <sys/rndsource.h>
58
59 #include <net/if.h>
60 #include <net/if_types.h>
61 #include <net/if_dl.h>
62 #include <net/bpf.h>
63 #include <net/if_ether.h>
64 #include <net/if_media.h>
65
66 #ifdef INET
67 #include <netinet/in.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/in_var.h>
70 #include <netinet/ip.h>
71 #include <netinet/if_inarp.h>
72 #endif
73
74
75 #include <sys/cpu.h>
76 #include <sys/bus.h>
77 #include <sys/intr.h>
78
79 #include <dev/isa/isareg.h>
80 #include <dev/isa/isavar.h>
81 #include <dev/ic/i82595reg.h>
82
83 /* XXX why isn't this centralized? */
84 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
85 #define bus_space_write_stream_2 bus_space_write_2
86 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
87 #define bus_space_read_stream_2 bus_space_read_2
88 #define bus_space_read_multi_stream_2 bus_space_read_multi_2
89 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
90
91 /*
92 * Ethernet status, per interface.
93 */
94 struct iy_softc {
95 device_t sc_dev;
96 void *sc_ih;
97
98 bus_space_tag_t sc_iot;
99 bus_space_handle_t sc_ioh;
100
101 struct ethercom sc_ethercom;
102
103 struct ifmedia iy_ifmedia;
104 int iy_media;
105
106 int mappedirq;
107
108 int hard_vers;
109
110 u_short promisc;
111
112 int sram, tx_size, rx_size;
113
114 int tx_start, tx_end, tx_last;
115 int rx_start;
116
117 int doing_mc_setup;
118 #ifdef IYDEBUG
119 int sc_debug;
120 #endif
121
122 krndsource_t rnd_source;
123 };
124
125 void iywatchdog(struct ifnet *);
126 int iyioctl(struct ifnet *, u_long, void *);
127 int iyintr(void *);
128 void iyinit(struct iy_softc *);
129 void iystop(struct iy_softc *);
130 void iystart(struct ifnet *);
131
132 void iy_intr_rx(struct iy_softc *);
133 void iy_intr_tx(struct iy_softc *);
134
135 void iyreset(struct iy_softc *);
136 void iy_readframe(struct iy_softc *, int);
137 void iy_drop_packet_buffer(struct iy_softc *);
138 void iy_find_mem_size(struct iy_softc *);
139 void iyrint(struct iy_softc *);
140 void iytint(struct iy_softc *);
141 void iyxmit(struct iy_softc *);
142 static void iy_mc_setup(struct iy_softc *);
143 static void iy_mc_reset(struct iy_softc *);
144 void iyget(struct iy_softc *, bus_space_tag_t, bus_space_handle_t, int);
145 void iyprobemem(struct iy_softc *);
146 static inline void eepromwritebit(bus_space_tag_t, bus_space_handle_t, int);
147 static inline int eepromreadbit(bus_space_tag_t, bus_space_handle_t);
148
149 #ifdef IYDEBUGX
150 void print_rbd(volatile struct iy_recv_buf_desc *);
151
152 int in_ifrint = 0;
153 int in_iftint = 0;
154 #endif
155
156 int iy_mediachange(struct ifnet *);
157 void iy_mediastatus(struct ifnet *, struct ifmediareq *);
158
159 int iyprobe(device_t, cfdata_t, void *);
160 void iyattach(device_t, device_t, void *);
161
162 static uint16_t eepromread(bus_space_tag_t, bus_space_handle_t, int);
163
164 static int eepromreadall(bus_space_tag_t, bus_space_handle_t, uint16_t *,
165 int);
166
167 CFATTACH_DECL_NEW(iy, sizeof(struct iy_softc),
168 iyprobe, iyattach, NULL, NULL);
169
170 static uint8_t eepro_irqmap[] = EEPP_INTMAP;
171 static uint8_t eepro_revirqmap[] = EEPP_RINTMAP;
172
173 int
174 iyprobe(device_t parent, cfdata_t match, void *aux)
175 {
176 struct isa_attach_args *ia = aux;
177 uint16_t eaddr[8];
178 bus_space_tag_t iot;
179 bus_space_handle_t ioh;
180 uint8_t c, d;
181 int irq;
182
183 if (ia->ia_nio < 1)
184 return 0;
185 if (ia->ia_nirq < 1)
186 return 0;
187
188 if (ISA_DIRECT_CONFIG(ia))
189 return 0;
190
191 iot = ia->ia_iot;
192
193 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
194 return 0;
195
196 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh))
197 return 0;
198
199 /* try to find the round robin sig: */
200
201 c = bus_space_read_1(iot, ioh, ID_REG);
202 if ((c & ID_REG_MASK) != ID_REG_SIG)
203 goto out;
204
205 d = bus_space_read_1(iot, ioh, ID_REG);
206 if ((d & ID_REG_MASK) != ID_REG_SIG)
207 goto out;
208
209 if (((d-c) & R_ROBIN_BITS) != 0x40)
210 goto out;
211
212 d = bus_space_read_1(iot, ioh, ID_REG);
213 if ((d & ID_REG_MASK) != ID_REG_SIG)
214 goto out;
215
216 if (((d-c) & R_ROBIN_BITS) != 0x80)
217 goto out;
218
219 d = bus_space_read_1(iot, ioh, ID_REG);
220 if ((d & ID_REG_MASK) != ID_REG_SIG)
221 goto out;
222
223 if (((d-c) & R_ROBIN_BITS) != 0xC0)
224 goto out;
225
226 d = bus_space_read_1(iot, ioh, ID_REG);
227 if ((d & ID_REG_MASK) != ID_REG_SIG)
228 goto out;
229
230 if (((d-c) & R_ROBIN_BITS) != 0x00)
231 goto out;
232
233 #ifdef IYDEBUG
234 printf("iyprobe verified working ID reg.\n");
235 #endif
236
237 if (eepromreadall(iot, ioh, eaddr, 8))
238 goto out;
239
240 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ)
241 irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
242 else
243 irq = ia->ia_irq[0].ir_irq;
244
245 if (irq >= sizeof(eepro_revirqmap))
246 goto out;
247
248 if (eepro_revirqmap[irq] == 0xff)
249 goto out;
250
251 /* now lets reset the chip */
252
253 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD);
254 delay(200);
255
256 ia->ia_nio = 1;
257 ia->ia_io[0].ir_size = 16;
258
259 ia->ia_nirq = 1;
260 ia->ia_irq[0].ir_irq = irq;
261
262 ia->ia_niomem = 0;
263 ia->ia_ndrq = 0;
264
265 bus_space_unmap(iot, ioh, 16);
266 return 1; /* found */
267 out:
268 bus_space_unmap(iot, ioh, 16);
269 return 0;
270 }
271
272 void
273 iyattach(device_t parent, device_t self, void *aux)
274 {
275 struct iy_softc *sc = device_private(self);
276 struct isa_attach_args *ia = aux;
277 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
278 bus_space_tag_t iot;
279 bus_space_handle_t ioh;
280 unsigned temp;
281 uint16_t eaddr[8];
282 uint8_t myaddr[ETHER_ADDR_LEN];
283 int eirq;
284
285 sc->sc_dev = self;
286 iot = ia->ia_iot;
287
288 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) {
289 aprint_error(": can't map i/o space\n");
290 return;
291 }
292
293 sc->sc_iot = iot;
294 sc->sc_ioh = ioh;
295
296 sc->mappedirq = eepro_revirqmap[ia->ia_irq[0].ir_irq];
297
298 /* now let's reset the chip */
299
300 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD);
301 delay(200);
302
303 iyprobemem(sc);
304
305 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
306 ifp->if_softc = sc;
307 ifp->if_start = iystart;
308 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
309
310 sc->doing_mc_setup = 0;
311
312 ifp->if_ioctl = iyioctl;
313 ifp->if_watchdog = iywatchdog;
314
315 IFQ_SET_READY(&ifp->if_snd);
316
317 (void)eepromreadall(iot, ioh, eaddr, 8);
318 sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev;
319
320 #ifdef DIAGNOSTICS
321 if ((eaddr[EEPPEther0] !=
322 eepromread(iot, ioh, EEPPEther0a)) &&
323 (eaddr[EEPPEther1] !=
324 eepromread(iot, ioh, EEPPEther1a)) &&
325 (eaddr[EEPPEther2] !=
326 eepromread(iot, ioh, EEPPEther2a)))
327
328 aprint_error("EEPROM Ethernet address differs from copy\n");
329 #endif
330
331 myaddr[1] = eaddr[EEPPEther0] & 0xFF;
332 myaddr[0] = eaddr[EEPPEther0] >> 8;
333 myaddr[3] = eaddr[EEPPEther1] & 0xFF;
334 myaddr[2] = eaddr[EEPPEther1] >> 8;
335 myaddr[5] = eaddr[EEPPEther2] & 0xFF;
336 myaddr[4] = eaddr[EEPPEther2] >> 8;
337
338 /* Initialize ifmedia structures. */
339 sc->sc_ethercom.ec_ifmedia = &sc->iy_ifmedia;
340 ifmedia_init(&sc->iy_ifmedia, 0, iy_mediachange, iy_mediastatus);
341 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_2, 0, NULL);
342 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_5, 0, NULL);
343 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
344 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
345 ifmedia_set(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO);
346 /* Attach the interface. */
347 if_attach(ifp);
348 ether_ifattach(ifp, myaddr);
349 aprint_normal(": address %s, rev. %d, %d kB\n",
350 ether_sprintf(myaddr),
351 sc->hard_vers, sc->sram/1024);
352
353 eirq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
354 if (eirq != ia->ia_irq[0].ir_irq)
355 aprint_error("%s: EEPROM irq setting %d ignored\n",
356 device_xname(sc->sc_dev), eirq);
357
358 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
359 IST_EDGE, IPL_NET, iyintr, sc);
360
361 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
362 RND_TYPE_NET, RND_FLAG_DEFAULT);
363
364 temp = bus_space_read_1(iot, ioh, INT_NO_REG);
365 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
366 }
367
368 void
369 iystop(struct iy_softc *sc)
370 {
371 bus_space_tag_t iot;
372 bus_space_handle_t ioh;
373 #ifdef IYDEBUG
374 u_int p, v;
375 #endif
376
377 iot = sc->sc_iot;
378 ioh = sc->sc_ioh;
379
380 bus_space_write_1(iot, ioh, COMMAND_REG, RCV_DISABLE_CMD);
381
382 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS);
383 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS);
384
385 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD);
386 delay(200);
387 #ifdef IYDEBUG
388 printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n",
389 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, sc->tx_last);
390 p = sc->tx_last;
391 if (!p)
392 p = sc->tx_start;
393 do {
394 char sbuf[128];
395
396 bus_space_write_2(iot, ioh, HOST_ADDR_REG, p);
397
398 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
399 snprintb(sbuf, sizeof(sbuf), "\020\006Ab\010Dn", v);
400 printf("0x%04x: %s ", p, sbuf);
401
402 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
403 snprintb(sbuf, sizeof(sbuf),
404 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN"
405 "\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL", v);
406 printf("%s", sbuf);
407
408 p = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
409 printf(" 0x%04x", p);
410
411 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
412 snprintb(sbuf, sizeof(sbuf), "\020\020Ch", v);
413 printf(" %s\n", sbuf);
414
415 } while (v & 0x8000);
416 #endif
417 sc->tx_start = sc->tx_end = sc->rx_size;
418 sc->tx_last = 0;
419 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
420 }
421
422 void
423 iyreset(struct iy_softc *sc)
424 {
425 int s;
426 s = splnet();
427 iystop(sc);
428 iyinit(sc);
429 splx(s);
430 }
431
432 void
433 iyinit(struct iy_softc *sc)
434 {
435 int i;
436 unsigned temp;
437 struct ifnet *ifp;
438 bus_space_tag_t iot;
439 bus_space_handle_t ioh;
440
441 iot = sc->sc_iot;
442 ioh = sc->sc_ioh;
443
444 ifp = &sc->sc_ethercom.ec_if;
445 #ifdef IYDEBUG
446 printf("ifp is %p\n", ifp);
447 #endif
448
449 bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
450
451 temp = bus_space_read_1(iot, ioh, EEPROM_REG);
452 if (temp & 0x10)
453 bus_space_write_1(iot, ioh, EEPROM_REG, temp & ~0x10);
454
455 for (i=0; i<6; ++i) {
456 bus_space_write_1(iot, ioh, I_ADD(i), CLLADDR(ifp->if_sadl)[i]);
457 }
458
459 temp = bus_space_read_1(iot, ioh, REG1);
460 bus_space_write_1(iot, ioh, REG1,
461 temp | /* XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | */ RCV_DISCARD_BAD);
462
463 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
464 temp = MATCH_ALL;
465 else
466 temp = MATCH_BRDCST;
467
468 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp);
469
470 #ifdef IYDEBUG
471 {
472 char sbuf[128];
473
474 snprintb(sbuf, sizeof(sbuf),
475 "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA",
476 temp);
477
478 printf("%s: RECV_MODES set to %s\n", device_xname(sc->sc_dev),
479 sbuf);
480 }
481 #endif
482 /* XXX VOODOO */
483 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
484 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
485 /* XXX END OF VOODOO */
486
487
488 delay(500000); /* for the hardware to test for the connector */
489
490 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
491 #ifdef IYDEBUG
492 {
493 char sbuf[128];
494
495 snprintb(sbuf, sizeof(sbuf),
496 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC",
497 temp);
498 printf("%s: media select was %s ", device_xname(sc->sc_dev),
499 sbuf);
500 }
501 #endif
502 temp = (temp & TEST_MODE_MASK);
503
504 switch (IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) {
505 case IFM_10_5:
506 temp &= ~ (BNC_BIT | TPE_BIT);
507 break;
508
509 case IFM_10_2:
510 temp = (temp & ~TPE_BIT) | BNC_BIT;
511 break;
512
513 case IFM_10_T:
514 temp = (temp & ~BNC_BIT) | TPE_BIT;
515 break;
516 default:
517 ;
518 /* nothing; leave as it is */
519 }
520 switch (temp & (BNC_BIT | TPE_BIT)) {
521 case BNC_BIT:
522 sc->iy_media = IFM_ETHER | IFM_10_2;
523 break;
524 case TPE_BIT:
525 sc->iy_media = IFM_ETHER | IFM_10_T;
526 break;
527 default:
528 sc->iy_media = IFM_ETHER | IFM_10_5;
529 }
530
531 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
532 #ifdef IYDEBUG
533 {
534 char sbuf[128];
535
536 snprintb(sbuf, sizeof(sbuf),
537 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC",
538 temp);
539 printf("changed to %s\n", sbuf);
540 }
541 #endif
542
543 bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
544 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS);
545 bus_space_write_1(iot, ioh, 0, BANK_SEL(1));
546
547 temp = bus_space_read_1(iot, ioh, INT_NO_REG);
548 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
549
550 #ifdef IYDEBUG
551 {
552 char sbuf[128];
553
554 snprintb(sbuf, sizeof(sbuf),
555 "\020\4bad_irq\010flash/boot present", temp);
556
557 printf("%s: int no was %s\n", device_xname(sc->sc_dev), sbuf);
558
559 temp = bus_space_read_1(iot, ioh, INT_NO_REG);
560 snprintb(sbuf, sizeof(sbuf),
561 "\020\4bad_irq\010flash/boot present", temp);
562 printf("%s: int no now %s\n", device_xname(sc->sc_dev), sbuf);
563 }
564 #endif
565
566 bus_space_write_1(iot, ioh, RCV_LOWER_LIMIT_REG, 0);
567 bus_space_write_1(iot, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size -2) >>8);
568 bus_space_write_1(iot, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >>8);
569 bus_space_write_1(iot, ioh, XMT_UPPER_LIMIT_REG, (sc->sram - 2) >>8);
570
571 temp = bus_space_read_1(iot, ioh, REG1);
572 #ifdef IYDEBUG
573 {
574 char sbuf[128];
575
576 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE",
577 temp);
578
579 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf);
580 }
581 #endif
582 bus_space_write_1(iot, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */
583
584 #ifdef IYDEBUG
585 {
586 char sbuf[128];
587
588 temp = bus_space_read_1(iot, ioh, REG1);
589 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE",
590 temp);
591 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf);
592 }
593 #endif
594
595 bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
596
597 bus_space_write_1(iot, ioh, INT_MASK_REG,
598 ALL_INTS & ~(RX_BIT | TX_BIT));
599 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); /* clear ints */
600
601 bus_space_write_1(iot, ioh, RCV_COPY_THRESHOLD, 0);
602
603 bus_space_write_2(iot, ioh, RCV_START_LOW, 0);
604 bus_space_write_2(iot, ioh, RCV_STOP_LOW, sc->rx_size - 2);
605 sc->rx_start = 0;
606
607 bus_space_write_1(iot, ioh, 0, SEL_RESET_CMD);
608 delay(200);
609
610 bus_space_write_2(iot, ioh, XMT_ADDR_REG, sc->rx_size);
611
612 sc->tx_start = sc->tx_end = sc->rx_size;
613 sc->tx_last = 0;
614
615 bus_space_write_1(iot, ioh, 0, RCV_ENABLE_CMD);
616
617 ifp->if_flags |= IFF_RUNNING;
618 ifp->if_flags &= ~IFF_OACTIVE;
619 }
620
621 void
622 iystart(struct ifnet *ifp)
623 {
624 struct iy_softc *sc;
625
626
627 struct mbuf *m0, *m;
628 u_int len, pad, last, end;
629 u_int llen, residual;
630 int avail;
631 char *data;
632 unsigned temp;
633 uint16_t resval, stat;
634 bus_space_tag_t iot;
635 bus_space_handle_t ioh;
636
637 #ifdef IYDEBUG
638 printf("iystart called\n");
639 #endif
640 sc = ifp->if_softc;
641
642 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
643 return;
644
645 iy_intr_tx(sc);
646
647 iot = sc->sc_iot;
648 ioh = sc->sc_ioh;
649
650 for (;;) {
651 IFQ_POLL(&ifp->if_snd, m0);
652 if (m0 == NULL)
653 break;
654 #ifdef IYDEBUG
655 printf("%s: trying to write another packet to the hardware\n",
656 device_xname(sc->sc_dev));
657 #endif
658
659 /* We need to use m->m_pkthdr.len, so require the header */
660 if ((m0->m_flags & M_PKTHDR) == 0)
661 panic("iystart: no header mbuf");
662
663 len = m0->m_pkthdr.len;
664 pad = len & 1;
665
666 #ifdef IYDEBUG
667 printf("%s: length is %d.\n", device_xname(sc->sc_dev), len);
668 #endif
669 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
670 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
671 }
672
673 if (len + pad > ETHER_MAX_LEN) {
674 /* packet is obviously too large: toss it */
675 ++ifp->if_oerrors;
676 IFQ_DEQUEUE(&ifp->if_snd, m0);
677 m_freem(m0);
678 continue;
679 }
680
681 bpf_mtap(ifp, m0, BPF_D_OUT);
682
683 avail = sc->tx_start - sc->tx_end;
684 if (avail <= 0)
685 avail += sc->tx_size;
686
687 #ifdef IYDEBUG
688 printf("%s: avail is %d.\n", device_xname(sc->sc_dev), avail);
689 #endif
690 /*
691 * we MUST RUN at splnet here ---
692 * XXX todo: or even turn off the boards ints ??? hm...
693 */
694
695 /* See if there is room to put another packet in the buffer. */
696
697 if ((len+pad+2*I595_XMT_HDRLEN) > avail) {
698 #ifdef IYDEBUG
699 printf("%s: len = %d, avail = %d, setting OACTIVE\n",
700 device_xname(sc->sc_dev), len, avail);
701 #endif
702 /* mark interface as full ... */
703 ifp->if_flags |= IFF_OACTIVE;
704
705 /* and wait for any transmission result */
706 bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
707
708 temp = bus_space_read_1(iot, ioh, REG1);
709 bus_space_write_1(iot, ioh, REG1,
710 temp & ~XMT_CHAIN_INT);
711
712 bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
713
714 return;
715 }
716
717 /* we know it fits in the hardware now, so dequeue it */
718 IFQ_DEQUEUE(&ifp->if_snd, m0);
719
720 last = sc->tx_end;
721 end = last + pad + len + I595_XMT_HDRLEN;
722
723 if (end >= sc->sram) {
724 if ((sc->sram - last) <= I595_XMT_HDRLEN) {
725 /* keep header in one piece */
726 last = sc->rx_size;
727 end = last + pad + len + I595_XMT_HDRLEN;
728 } else
729 end -= sc->tx_size;
730 }
731
732 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last);
733 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
734 htole16(XMT_CMD));
735
736 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
737 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
738
739 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
740 htole16(len + pad));
741
742 residual = resval = 0;
743
744 while ((m = m0)!=0) {
745 data = mtod(m, void *);
746 llen = m->m_len;
747 if (residual) {
748 #ifdef IYDEBUG
749 printf("%s: merging residual with next mbuf.\n",
750 device_xname(sc->sc_dev));
751 #endif
752 resval |= *data << 8;
753 bus_space_write_stream_2(iot, ioh,
754 MEM_PORT_REG, resval);
755 --llen;
756 ++data;
757 }
758 /*
759 * XXX ALIGNMENT LOSSAGE HERE.
760 */
761 if (llen > 1)
762 bus_space_write_multi_stream_2(iot, ioh,
763 MEM_PORT_REG, (uint16_t *) data,
764 llen>>1);
765 residual = llen & 1;
766 if (residual) {
767 resval = *(data + llen - 1);
768 #ifdef IYDEBUG
769 printf("%s: got odd mbuf to send.\n",
770 device_xname(sc->sc_dev));
771 #endif
772 }
773
774 m0 = m_free(m);
775 }
776
777 if (residual)
778 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
779 resval);
780
781 pad >>= 1;
782 while (pad-- > 0)
783 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 0);
784
785 #ifdef IYDEBUG
786 printf("%s: new last = 0x%x, end = 0x%x.\n",
787 device_xname(sc->sc_dev), last, end);
788 printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n",
789 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end,
790 sc->tx_last);
791 #endif
792
793 if (sc->tx_start != sc->tx_end) {
794 bus_space_write_2(iot, ioh, HOST_ADDR_REG,
795 sc->tx_last + XMT_COUNT);
796
797 /*
798 * XXX We keep stat in le order, to potentially save
799 * a byte swap.
800 */
801 stat = bus_space_read_stream_2(iot, ioh, MEM_PORT_REG);
802
803 bus_space_write_2(iot, ioh, HOST_ADDR_REG,
804 sc->tx_last + XMT_CHAIN);
805
806 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
807 htole16(last));
808
809 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
810 stat | htole16(CHAIN));
811 #ifdef IYDEBUG
812 printf("%s: setting 0x%x to 0x%x\n",
813 device_xname(sc->sc_dev), sc->tx_last + XMT_COUNT,
814 le16toh(stat) | CHAIN);
815 #endif
816 }
817 /* dummy read */
818 stat = bus_space_read_2(iot, ioh, MEM_PORT_REG);
819
820 /* XXX todo: enable ints here if disabled */
821
822 ++ifp->if_opackets;
823
824 if (sc->tx_start == sc->tx_end) {
825 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last);
826 bus_space_write_1(iot, ioh, 0, XMT_CMD);
827 sc->tx_start = last;
828 #ifdef IYDEBUG
829 printf("%s: writing 0x%x to XAR and giving XCMD\n",
830 device_xname(sc->sc_dev), last);
831 #endif
832 } else {
833 bus_space_write_1(iot, ioh, 0, RESUME_XMT_CMD);
834 #ifdef IYDEBUG
835 printf("%s: giving RESUME_XCMD\n",
836 device_xname(sc->sc_dev));
837 #endif
838 }
839 sc->tx_last = last;
840 sc->tx_end = end;
841 }
842 /* and wait only for end of transmission chain */
843 bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
844
845 temp = bus_space_read_1(iot, ioh, REG1);
846 bus_space_write_1(iot, ioh, REG1, temp | XMT_CHAIN_INT);
847
848 bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
849 }
850
851
852 static inline void
853 eepromwritebit(bus_space_tag_t iot, bus_space_handle_t ioh, int what)
854 {
855 bus_space_write_1(iot, ioh, EEPROM_REG, what);
856 delay(1);
857 bus_space_write_1(iot, ioh, EEPROM_REG, what | EESK);
858 delay(1);
859 bus_space_write_1(iot, ioh, EEPROM_REG, what);
860 delay(1);
861 }
862
863 static inline int
864 eepromreadbit(bus_space_tag_t iot, bus_space_handle_t ioh)
865 {
866 int b;
867
868 bus_space_write_1(iot, ioh, EEPROM_REG, EECS | EESK);
869 delay(1);
870 b = bus_space_read_1(iot, ioh, EEPROM_REG);
871 bus_space_write_1(iot, ioh, EEPROM_REG, EECS);
872 delay(1);
873
874 return ((b & EEDO) != 0);
875 }
876
877 static uint16_t
878 eepromread(bus_space_tag_t iot, bus_space_handle_t ioh, int offset)
879 {
880 volatile int i;
881 volatile int j;
882 volatile uint16_t readval;
883
884 bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
885 delay(1);
886 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); /* XXXX??? */
887 delay(1);
888
889 eepromwritebit(iot, ioh, EECS | EEDI);
890 eepromwritebit(iot, ioh, EECS | EEDI);
891 eepromwritebit(iot, ioh, EECS);
892
893 for (j=5; j>=0; --j) {
894 if ((offset>>j) & 1)
895 eepromwritebit(iot, ioh, EECS | EEDI);
896 else
897 eepromwritebit(iot, ioh, EECS);
898 }
899
900 for (readval=0, i=0; i<16; ++i) {
901 readval<<=1;
902 readval |= eepromreadbit(iot, ioh);
903 }
904
905 bus_space_write_1(iot, ioh, EEPROM_REG, 0 | EESK);
906 delay(1);
907 bus_space_write_1(iot, ioh, EEPROM_REG, 0);
908
909 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0));
910
911 return readval;
912 }
913
914 /*
915 * Device timeout/watchdog routine. Entered if the device neglects to generate
916 * an interrupt after a transmit has been started on it.
917 */
918 void
919 iywatchdog(struct ifnet *ifp)
920 {
921 struct iy_softc *sc = ifp->if_softc;
922
923 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
924 ++sc->sc_ethercom.ec_if.if_oerrors;
925 iyreset(sc);
926 }
927
928 /*
929 * What to do upon receipt of an interrupt.
930 */
931 int
932 iyintr(void *arg)
933 {
934 struct iy_softc *sc;
935 struct ifnet *ifp;
936 bus_space_tag_t iot;
937 bus_space_handle_t ioh;
938
939 u_short status;
940
941 sc = arg;
942 iot = sc->sc_iot;
943 ioh = sc->sc_ioh;
944
945 ifp = &sc->sc_ethercom.ec_if;
946
947 status = bus_space_read_1(iot, ioh, STATUS_REG);
948 #ifdef IYDEBUG
949 if (status & ALL_INTS) {
950 char sbuf[128];
951
952 snprintb(sbuf, sizeof(sbuf), "\020\1RX_STP\2RX\3TX\4EXEC",
953 status);
954 printf("%s: got interrupt %s", device_xname(sc->sc_dev), sbuf);
955
956 if (status & EXEC_INT) {
957 snprintb(sbuf, sizeof(sbuf),
958 "\020\6ABORT", bus_space_read_1(iot, ioh, 0));
959 printf(" event %s\n", sbuf);
960 } else
961 printf("\n");
962 }
963 #endif
964 if ((status & (RX_INT | TX_INT)) == 0)
965 return 0;
966
967 if (status & RX_INT) {
968 iy_intr_rx(sc);
969 bus_space_write_1(iot, ioh, STATUS_REG, RX_INT);
970 }
971 if (status & TX_INT) {
972 /* Tell feeders we may be able to accept more data... */
973 ifp->if_flags &= ~IFF_OACTIVE;
974 /* and get more data. */
975 iystart(ifp);
976 bus_space_write_1(iot, ioh, STATUS_REG, TX_INT);
977 }
978
979 rnd_add_uint32(&sc->rnd_source, status);
980
981 return 1;
982 }
983
984 void
985 iyget(struct iy_softc *sc, bus_space_tag_t iot, bus_space_handle_t ioh,
986 int rxlen)
987 {
988 struct mbuf *m, *top, **mp;
989 struct ifnet *ifp;
990 int len;
991
992 ifp = &sc->sc_ethercom.ec_if;
993
994 MGETHDR(m, M_DONTWAIT, MT_DATA);
995 if (m == 0)
996 goto dropped;
997 m_set_rcvif(m, ifp);
998 m->m_pkthdr.len = rxlen;
999 len = MHLEN;
1000 top = 0;
1001 mp = ⊤
1002
1003 while (rxlen > 0) {
1004 if (top) {
1005 MGET(m, M_DONTWAIT, MT_DATA);
1006 if (m == 0) {
1007 m_freem(top);
1008 goto dropped;
1009 }
1010 len = MLEN;
1011 }
1012 if (rxlen >= MINCLSIZE) {
1013 MCLGET(m, M_DONTWAIT);
1014 if ((m->m_flags & M_EXT) == 0) {
1015 m_free(m);
1016 m_freem(top);
1017 goto dropped;
1018 }
1019 len = MCLBYTES;
1020 }
1021 len = uimin(rxlen, len);
1022 /*
1023 * XXX ALIGNMENT LOSSAGE HERE.
1024 */
1025 if (len > 1) {
1026 len &= ~1;
1027
1028 bus_space_read_multi_stream_2(iot, ioh, MEM_PORT_REG,
1029 mtod(m, uint16_t *), len / 2);
1030 } else {
1031 #ifdef IYDEBUG
1032 printf("%s: received odd mbuf\n",
1033 device_xname(sc->sc_dev));
1034 #endif
1035 *(mtod(m, char *)) = bus_space_read_stream_2(iot, ioh,
1036 MEM_PORT_REG);
1037 }
1038 m->m_len = len;
1039 rxlen -= len;
1040 *mp = m;
1041 mp = &m->m_next;
1042 }
1043
1044 if (top == NULL)
1045 return;
1046
1047 if_percpuq_enqueue(ifp->if_percpuq, top);
1048 return;
1049
1050 dropped:
1051 ++ifp->if_ierrors;
1052 return;
1053 }
1054
1055 void
1056 iy_intr_rx(struct iy_softc *sc)
1057 {
1058 bus_space_tag_t iot;
1059 bus_space_handle_t ioh;
1060
1061 u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen;
1062
1063 iot = sc->sc_iot;
1064 ioh = sc->sc_ioh;
1065
1066 rxadrs = sc->rx_start;
1067 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxadrs);
1068 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
1069 rxnext = 0;
1070
1071 while (rxevnt == RCV_DONE) {
1072 rxstatus = le16toh(bus_space_read_stream_2(iot, ioh,
1073 MEM_PORT_REG));
1074 rxnext = le16toh(bus_space_read_stream_2(iot, ioh,
1075 MEM_PORT_REG));
1076 rxlen = le16toh(bus_space_read_stream_2(iot, ioh,
1077 MEM_PORT_REG));
1078 #ifdef IYDEBUG
1079 {
1080 char sbuf[128];
1081
1082 snprintb(sbuf, sizeof(sbuf),
1083 "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR"
1084 "\014CRCERR\015LENERR\016RCVOK\020TYP", rxstatus);
1085
1086 printf("%s: pck at 0x%04x stat %s next 0x%x len 0x%x\n",
1087 device_xname(sc->sc_dev), rxadrs, sbuf, rxnext,
1088 rxlen);
1089 }
1090 #else
1091 __USE(rxstatus);
1092 #endif
1093 iyget(sc, iot, ioh, rxlen);
1094
1095 /* move stop address */
1096 bus_space_write_2(iot, ioh, RCV_STOP_LOW,
1097 rxnext == 0 ? sc->rx_size - 2 : rxnext - 2);
1098
1099 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxnext);
1100 rxadrs = rxnext;
1101 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh,
1102 MEM_PORT_REG));
1103 }
1104 sc->rx_start = rxnext;
1105 }
1106
1107 void
1108 iy_intr_tx(struct iy_softc *sc)
1109 {
1110 bus_space_tag_t iot;
1111 bus_space_handle_t ioh;
1112 struct ifnet *ifp;
1113 u_int txstatus, txstat2, txlen, txnext;
1114
1115 ifp = &sc->sc_ethercom.ec_if;
1116 iot = sc->sc_iot;
1117 ioh = sc->sc_ioh;
1118
1119 while (sc->tx_start != sc->tx_end) {
1120 bus_space_write_2(iot, ioh, HOST_ADDR_REG, sc->tx_start);
1121 txstatus = le16toh(bus_space_read_stream_2(iot, ioh,
1122 MEM_PORT_REG));
1123
1124 if ((txstatus & (TX_DONE | CMD_MASK)) != (TX_DONE | XMT_CMD))
1125 break;
1126
1127 txstat2 = le16toh(bus_space_read_stream_2(iot, ioh,
1128 MEM_PORT_REG));
1129 txnext = le16toh(bus_space_read_stream_2(iot, ioh,
1130 MEM_PORT_REG));
1131 txlen = le16toh(bus_space_read_stream_2(iot, ioh,
1132 MEM_PORT_REG));
1133 #ifdef IYDEBUG
1134 {
1135 char sbuf[128];
1136
1137 snprintb(sbuf, sizeof(sbuf),
1138 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF"
1139 "\011UND_RUN\012JERR\013LST_CRS"
1140 "\014LTCOL\016TX_OK\020COLL", txstat2);
1141
1142 printf("txstat 0x%x stat2 %s next 0x%x len 0x%x\n",
1143 txstatus, sbuf, txnext, txlen);
1144 }
1145 #endif
1146 if (txlen & CHAIN)
1147 sc->tx_start = txnext;
1148 else
1149 sc->tx_start = sc->tx_end;
1150 ifp->if_flags &= ~IFF_OACTIVE;
1151
1152 if (txstat2 & 0x0020)
1153 ifp->if_collisions += 16;
1154 else
1155 ifp->if_collisions += txstat2 & 0x000f;
1156
1157 if ((txstat2 & 0x2000) == 0)
1158 ++ifp->if_oerrors;
1159 }
1160 }
1161
1162 int
1163 iyioctl(struct ifnet *ifp, u_long cmd, void *data)
1164 {
1165 struct iy_softc *sc;
1166 struct ifaddr *ifa;
1167 int s, error = 0;
1168
1169 sc = ifp->if_softc;
1170 ifa = (struct ifaddr *)data;
1171
1172 #ifdef IYDEBUG
1173 printf("iyioctl called with ifp %p (%s) cmd 0x%lx data %p\n",
1174 ifp, ifp->if_xname, cmd, data);
1175 #endif
1176
1177 s = splnet();
1178
1179 switch (cmd) {
1180
1181 case SIOCINITIFADDR:
1182 ifp->if_flags |= IFF_UP;
1183
1184 iyinit(sc);
1185 switch (ifa->ifa_addr->sa_family) {
1186 #ifdef INET
1187 case AF_INET:
1188 arp_ifinit(ifp, ifa);
1189 break;
1190 #endif
1191 default:
1192 break;
1193 }
1194 break;
1195
1196 case SIOCSIFFLAGS:
1197 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
1198 break;
1199 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
1200 /* XXX re-use ether_ioctl() */
1201 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1202 case IFF_RUNNING:
1203 /*
1204 * If interface is marked down and it is running, then
1205 * stop it.
1206 */
1207 iystop(sc);
1208 ifp->if_flags &= ~IFF_RUNNING;
1209 break;
1210 case IFF_UP:
1211 /*
1212 * If interface is marked up and it is stopped, then
1213 * start it.
1214 */
1215 iyinit(sc);
1216 break;
1217 default:
1218 /*
1219 * Reset the interface to pick up changes in any other
1220 * flags that affect hardware registers.
1221 */
1222 iystop(sc);
1223 iyinit(sc);
1224 break;
1225 }
1226 #ifdef IYDEBUGX
1227 if (ifp->if_flags & IFF_DEBUG)
1228 sc->sc_debug = IFY_ALL;
1229 else
1230 sc->sc_debug = 0;
1231 #endif
1232 break;
1233
1234 case SIOCADDMULTI:
1235 case SIOCDELMULTI:
1236 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
1237 /*
1238 * Multicast list has changed; set the hardware filter
1239 * accordingly.
1240 */
1241 if (ifp->if_flags & IFF_RUNNING) {
1242 /* XXX can't make it work otherwise */
1243 iyreset(sc);
1244 iy_mc_reset(sc);
1245 }
1246 error = 0;
1247 }
1248 break;
1249
1250 default:
1251 error = ether_ioctl(ifp, cmd, data);
1252 }
1253 splx(s);
1254 return error;
1255 }
1256
1257 int
1258 iy_mediachange(struct ifnet *ifp)
1259 {
1260 struct iy_softc *sc = ifp->if_softc;
1261
1262 if (IFM_TYPE(sc->iy_ifmedia.ifm_media) != IFM_ETHER)
1263 return EINVAL;
1264 switch (IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) {
1265 case IFM_10_5:
1266 case IFM_10_2:
1267 case IFM_10_T:
1268 case IFM_AUTO:
1269 iystop(sc);
1270 iyinit(sc);
1271 return 0;
1272 default:
1273 return EINVAL;
1274 }
1275 }
1276
1277 void
1278 iy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1279 {
1280 struct iy_softc *sc = ifp->if_softc;
1281
1282 ifmr->ifm_active = sc->iy_media;
1283 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
1284 }
1285
1286
1287 static void
1288 iy_mc_setup(struct iy_softc *sc)
1289 {
1290 struct ether_multi *enm;
1291 struct ether_multistep step;
1292 struct ethercom *ecp;
1293 struct ifnet *ifp;
1294 bus_space_tag_t iot;
1295 bus_space_handle_t ioh;
1296 int avail, last /*, end*/ , len;
1297 int timeout;
1298 volatile uint16_t dum;
1299 uint8_t temp;
1300
1301
1302 ecp = &sc->sc_ethercom;
1303 ifp = &ecp->ec_if;
1304
1305 iot = sc->sc_iot;
1306 ioh = sc->sc_ioh;
1307
1308 ETHER_LOCK(ecp);
1309 len = 6 * ecp->ec_multicnt;
1310
1311 avail = sc->tx_start - sc->tx_end;
1312 if (avail <= 0)
1313 avail += sc->tx_size;
1314 if (ifp->if_flags & IFF_DEBUG)
1315 printf("%s: iy_mc_setup called, %d addresses, "
1316 "%d/%d bytes needed/avail\n", ifp->if_xname,
1317 ecp->ec_multicnt, len + I595_XMT_HDRLEN, avail);
1318
1319 last = sc->rx_size;
1320
1321 bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
1322 bus_space_write_1(iot, ioh, RECV_MODES_REG, MATCH_BRDCST);
1323 /* XXX VOODOO */
1324 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
1325 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
1326 /* XXX END OF VOODOO */
1327 bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
1328 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last);
1329 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(MC_SETUP_CMD));
1330 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1331 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1332 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(len));
1333
1334 ETHER_FIRST_MULTI(step, ecp, enm);
1335 while (enm) {
1336 /*
1337 * XXX ALIGNMENT LOSSAGE HERE?
1338 */
1339 bus_space_write_multi_stream_2(iot, ioh, MEM_PORT_REG,
1340 (uint16_t *) enm->enm_addrlo, 3);
1341
1342 ETHER_NEXT_MULTI(step, enm);
1343 }
1344 ETHER_UNLOCK(ecp);
1345 dum = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */
1346 __USE(dum);
1347 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last);
1348 bus_space_write_1(iot, ioh, 0, MC_SETUP_CMD);
1349
1350
1351 sc->tx_start = sc->rx_size;
1352 sc->tx_end = sc->rx_size + I595_XMT_HDRLEN + len;
1353
1354 for (timeout=0; timeout<100; timeout++) {
1355 DELAY(2);
1356 if ((bus_space_read_1(iot, ioh, STATUS_REG) & EXEC_INT) == 0)
1357 continue;
1358
1359 temp = bus_space_read_1(iot, ioh, 0);
1360 bus_space_write_1(iot, ioh, STATUS_REG, EXEC_INT);
1361 #ifdef DIAGNOSTIC
1362 if (temp & 0x20) {
1363 aprint_error_dev(sc->sc_dev,
1364 "mc setup failed, %d usec\n", timeout * 2);
1365 } else if (((temp & 0x0f) == 0x03) &&
1366 (ifp->if_flags & IFF_DEBUG)) {
1367 printf("%s: mc setup done, %d usec\n",
1368 device_xname(sc->sc_dev), timeout * 2);
1369 }
1370 #endif
1371 break;
1372 }
1373 sc->tx_start = sc->tx_end;
1374 ifp->if_flags &= ~IFF_OACTIVE;
1375
1376 }
1377
1378 static void
1379 iy_mc_reset(struct iy_softc *sc)
1380 {
1381 struct ether_multi *enm;
1382 struct ether_multistep step;
1383 struct ethercom *ecp;
1384 struct ifnet *ifp;
1385 bus_space_tag_t iot;
1386 bus_space_handle_t ioh;
1387 uint16_t temp;
1388
1389 ecp = &sc->sc_ethercom;
1390 ifp = &ecp->ec_if;
1391
1392 iot = sc->sc_iot;
1393 ioh = sc->sc_ioh;
1394
1395 if (ecp->ec_multicnt > 63) {
1396 ifp->if_flags |= IFF_ALLMULTI;
1397
1398 } else if (ecp->ec_multicnt > 0) {
1399 /*
1400 * Step through the list of addresses.
1401 */
1402 ETHER_LOCK(ecp);
1403 ETHER_FIRST_MULTI(step, ecp, enm);
1404 while (enm) {
1405 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
1406 ifp->if_flags |= IFF_ALLMULTI;
1407 ETHER_UNLOCK(ecp);
1408 goto setupmulti;
1409 }
1410 ETHER_NEXT_MULTI(step, enm);
1411 }
1412 ETHER_UNLOCK(ecp);
1413 /* OK, we really need to do it now: */
1414 #if 0
1415 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE))
1416 != IFF_RUNNING) {
1417 ifp->if_flags |= IFF_OACTIVE;
1418 sc->want_mc_setup = 1;
1419 return;
1420 }
1421 #endif
1422 iy_mc_setup(sc);
1423 } else {
1424 ifp->if_flags &= ~IFF_ALLMULTI;
1425 }
1426
1427 setupmulti:
1428 bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
1429 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
1430 temp = MATCH_ALL;
1431 else
1432 temp = MATCH_BRDCST;
1433
1434 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp);
1435 /* XXX VOODOO */
1436 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
1437 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
1438 /* XXX END OF VOODOO */
1439
1440 /* XXX TBD: setup hardware for all multicasts */
1441 bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
1442 return;
1443 }
1444
1445 #ifdef IYDEBUGX
1446 void
1447 print_rbd(volatile struct ie_recv_buf_desc *rbd)
1448 {
1449 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
1450 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
1451 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
1452 rbd->mbz);
1453 }
1454 #endif
1455
1456 void
1457 iyprobemem(struct iy_softc *sc)
1458 {
1459 bus_space_tag_t iot;
1460 bus_space_handle_t ioh;
1461 int testing;
1462
1463 iot = sc->sc_iot;
1464 ioh = sc->sc_ioh;
1465
1466 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0));
1467 delay(1);
1468 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 4096-2);
1469 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1470
1471 for (testing=65536; testing >= 4096; testing >>= 1) {
1472 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
1473 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xdead);
1474 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
1475 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xdead) {
1476 #ifdef IYMEMDEBUG
1477 printf("%s: Didn't keep 0xdead at 0x%x\n",
1478 device_xname(sc->sc_dev), testing-2);
1479 #endif
1480 continue;
1481 }
1482
1483 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
1484 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xbeef);
1485 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
1486 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xbeef) {
1487 #ifdef IYMEMDEBUG
1488 printf("%s: Didn't keep 0xbeef at 0x%x\n",
1489 device_xname(sc->sc_dev), testing-2);
1490 #endif
1491 continue;
1492 }
1493
1494 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0);
1495 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1496 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing >> 1);
1497 bus_space_write_2(iot, ioh, MEM_PORT_REG, testing >> 1);
1498 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0);
1499 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) == (testing >> 1)) {
1500 #ifdef IYMEMDEBUG
1501 printf("%s: 0x%x alias of 0x0\n",
1502 device_xname(sc->sc_dev), testing >> 1);
1503 #endif
1504 continue;
1505 }
1506
1507 break;
1508 }
1509
1510 sc->sram = testing;
1511
1512 switch (testing) {
1513 case 65536:
1514 /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */
1515 sc->rx_size = 44*1024;
1516 break;
1517
1518 case 32768:
1519 /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */
1520 sc->rx_size = 22*1024;
1521 break;
1522
1523 case 16384:
1524 /* 1 NFS packet + overhead RX, 4 big packets TX */
1525 sc->rx_size = 10*1024;
1526 break;
1527 default:
1528 sc->rx_size = testing/2;
1529 break;
1530 }
1531 sc->tx_size = testing - sc->rx_size;
1532 }
1533
1534 static int
1535 eepromreadall(bus_space_tag_t iot, bus_space_handle_t ioh, uint16_t *wordp,
1536 int maxi)
1537 {
1538 int i;
1539 uint16_t checksum, tmp;
1540
1541 checksum = 0;
1542
1543 for (i=0; i<EEPP_LENGTH; ++i) {
1544 tmp = eepromread(iot, ioh, i);
1545 checksum += tmp;
1546 if (i<maxi)
1547 wordp[i] = tmp;
1548 }
1549
1550 if (checksum != EEPP_CHKSUM) {
1551 #ifdef IYDEBUG
1552 printf("wrong EEPROM checksum 0x%x should be 0x%x\n",
1553 checksum, EEPP_CHKSUM);
1554 #endif
1555 return 1;
1556 }
1557 return 0;
1558 }
1559