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