if_eg.c revision 1.98 1 /* $NetBSD: if_eg.c,v 1.98 2022/09/17 16:42:38 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1993 Dean Huxley <dean (at) fsa.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Dean Huxley.
18 * 4. The name of Dean Huxley may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * Support for 3Com 3c505 Etherlink+ card.
34 */
35
36 /*
37 * To do:
38 * - multicast
39 * - promiscuous
40 */
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: if_eg.c,v 1.98 2022/09/17 16:42:38 thorpej Exp $");
44
45 #include "opt_inet.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kmem.h>
50 #include <sys/mbuf.h>
51 #include <sys/socket.h>
52 #include <sys/ioctl.h>
53 #include <sys/errno.h>
54 #include <sys/syslog.h>
55 #include <sys/select.h>
56 #include <sys/device.h>
57 #include <sys/rndsource.h>
58
59 #include <net/if.h>
60 #include <net/if_dl.h>
61 #include <net/if_types.h>
62 #include <net/bpf.h>
63
64 #include <net/if_ether.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 #include <sys/cpu.h>
75 #include <sys/intr.h>
76 #include <sys/bus.h>
77
78 #include <dev/isa/isavar.h>
79 #include <dev/isa/if_egreg.h>
80 #include <dev/isa/elink.h>
81
82 /* for debugging convenience */
83 #ifdef EGDEBUG
84 #define DPRINTF(x) printf x
85 #else
86 #define DPRINTF(x)
87 #endif
88
89 #define EG_INLEN 10
90 #define EG_BUFLEN 0x0670
91
92 #define EG_PCBLEN 64
93
94 /*
95 * Ethernet software status per interface.
96 */
97 struct eg_softc {
98 device_t sc_dev;
99 void *sc_ih;
100 struct ethercom sc_ethercom; /* Ethernet common part */
101 bus_space_tag_t sc_iot; /* bus space identifier */
102 bus_space_handle_t sc_ioh; /* i/o handle */
103 u_int8_t eg_rom_major; /* Cards ROM version (major number) */
104 u_int8_t eg_rom_minor; /* Cards ROM version (minor number) */
105 short eg_ram; /* Amount of RAM on the card */
106 u_int8_t eg_pcb[EG_PCBLEN]; /* Primary Command Block buffer */
107 u_int8_t eg_incount; /* Number of buffers currently used */
108 void * eg_inbuf; /* Incoming packet buffer */
109 void * eg_outbuf; /* Outgoing packet buffer */
110
111 krndsource_t rnd_source;
112 };
113
114 int egprobe(device_t, cfdata_t, void *);
115 void egattach(device_t, device_t, void *);
116
117 CFATTACH_DECL_NEW(eg, sizeof(struct eg_softc),
118 egprobe, egattach, NULL, NULL);
119
120 int egintr(void *);
121 void eginit(struct eg_softc *);
122 int egioctl(struct ifnet *, u_long, void *);
123 void egrecv(struct eg_softc *);
124 void egstart(struct ifnet *);
125 void egwatchdog(struct ifnet *);
126 void egreset(struct eg_softc *);
127 void egread(struct eg_softc *, void *, int);
128 struct mbuf *egget(struct eg_softc *, void *, int);
129 void egstop(struct eg_softc *);
130
131 static inline void egprintpcb(u_int8_t *);
132 static int egoutPCB(bus_space_tag_t, bus_space_handle_t, u_int8_t);
133 static int egreadPCBstat(bus_space_tag_t, bus_space_handle_t, u_int8_t);
134 static int egreadPCBready(bus_space_tag_t, bus_space_handle_t);
135 static int egwritePCB(bus_space_tag_t, bus_space_handle_t, u_int8_t *);
136 static int egreadPCB(bus_space_tag_t, bus_space_handle_t, u_int8_t *);
137
138 /*
139 * Support stuff
140 */
141
142 static inline void
143 egprintpcb(u_int8_t *pcb)
144 {
145 int i;
146
147 for (i = 0; i < pcb[1] + 2; i++)
148 DPRINTF(("pcb[%2d] = %x\n", i, pcb[i]));
149 }
150
151 static int
152 egoutPCB(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t b)
153 {
154 int i;
155
156 for (i=0; i < 4000; i++) {
157 if (bus_space_read_1(iot, ioh, EG_STATUS) & EG_STAT_HCRE) {
158 bus_space_write_1(iot, ioh, EG_COMMAND, b);
159 return 0;
160 }
161 delay(10);
162 }
163 DPRINTF(("egoutPCB failed\n"));
164 return 1;
165 }
166
167 static int
168 egreadPCBstat(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t statb)
169 {
170 int i;
171
172 for (i=0; i < 5000; i++) {
173 if ((bus_space_read_1(iot, ioh, EG_STATUS) &
174 EG_PCB_STAT) != EG_PCB_NULL)
175 break;
176 delay(10);
177 }
178 if ((bus_space_read_1(iot, ioh, EG_STATUS) & EG_PCB_STAT) == statb)
179 return 0;
180 return 1;
181 }
182
183 static int
184 egreadPCBready(bus_space_tag_t iot, bus_space_handle_t ioh)
185 {
186 int i;
187
188 for (i=0; i < 10000; i++) {
189 if (bus_space_read_1(iot, ioh, EG_STATUS) & EG_STAT_ACRF)
190 return 0;
191 delay(5);
192 }
193 DPRINTF(("PCB read not ready\n"));
194 return 1;
195 }
196
197 static int
198 egwritePCB(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t *pcb)
199 {
200 int i;
201 u_int8_t len;
202
203 bus_space_write_1(iot, ioh, EG_CONTROL,
204 (bus_space_read_1(iot, ioh, EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_NULL);
205
206 len = pcb[1] + 2;
207 for (i = 0; i < len; i++)
208 egoutPCB(iot, ioh, pcb[i]);
209
210 for (i=0; i < 4000; i++) {
211 if (bus_space_read_1(iot, ioh, EG_STATUS) & EG_STAT_HCRE)
212 break;
213 delay(10);
214 }
215
216 bus_space_write_1(iot, ioh, EG_CONTROL,
217 (bus_space_read_1(iot, ioh, EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_DONE);
218
219 egoutPCB(iot, ioh, len);
220
221 if (egreadPCBstat(iot, ioh, EG_PCB_ACCEPT))
222 return 1;
223 return 0;
224 }
225
226 static int
227 egreadPCB(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t *pcb)
228 {
229 int i;
230
231 bus_space_write_1(iot, ioh, EG_CONTROL,
232 (bus_space_read_1(iot, ioh, EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_NULL);
233
234 memset(pcb, 0, EG_PCBLEN);
235
236 if (egreadPCBready(iot, ioh))
237 return 1;
238
239 pcb[0] = bus_space_read_1(iot, ioh, EG_COMMAND);
240
241 if (egreadPCBready(iot, ioh))
242 return 1;
243
244 pcb[1] = bus_space_read_1(iot, ioh, EG_COMMAND);
245
246 if (pcb[1] > 62) {
247 DPRINTF(("len %d too large\n", pcb[1]));
248 return 1;
249 }
250
251 for (i = 0; i < pcb[1]; i++) {
252 if (egreadPCBready(iot, ioh))
253 return 1;
254 pcb[2+i] = bus_space_read_1(iot, ioh, EG_COMMAND);
255 }
256 if (egreadPCBready(iot, ioh))
257 return 1;
258 if (egreadPCBstat(iot, ioh, EG_PCB_DONE))
259 return 1;
260 if (bus_space_read_1(iot, ioh, EG_COMMAND) != pcb[1] + 2) {
261 return 1;
262 }
263
264 bus_space_write_1(iot, ioh, EG_CONTROL,
265 (bus_space_read_1(iot, ioh, EG_CONTROL) &
266 ~EG_PCB_STAT) | EG_PCB_ACCEPT);
267
268 return 0;
269 }
270
271 /*
272 * Real stuff
273 */
274
275 int
276 egprobe(device_t parent, cfdata_t match, void *aux)
277 {
278 struct isa_attach_args *ia = aux;
279 bus_space_tag_t iot = ia->ia_iot;
280 bus_space_handle_t ioh;
281 int i, rval;
282 static u_int8_t pcb[EG_PCBLEN];
283
284 rval = 0;
285
286 /*
287 * XXX This probe is slow. If there are no ISA expansion slots,
288 * then skip it.
289 */
290 if (isa_get_slotcount() == 0)
291 return (0);
292
293 if (ia->ia_nio < 1)
294 return (0);
295 if (ia->ia_nirq < 1)
296 return (0);
297
298 if (ISA_DIRECT_CONFIG(ia))
299 return (0);
300
301 /* Disallow wildcarded i/o address. */
302 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
303 return (0);
304
305 /* Disallow wildcarded IRQ. */
306 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ)
307 return (0);
308
309 if ((ia->ia_io[0].ir_addr & ~0x07f0) != 0) {
310 DPRINTF(("Weird iobase %x\n", ia->ia_io[0].ir_addr));
311 return 0;
312 }
313
314 /* Map i/o space. */
315 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 0x08, 0, &ioh)) {
316 DPRINTF(("egprobe: can't map i/o space in probe\n"));
317 return 0;
318 }
319
320 /* hard reset card */
321 bus_space_write_1(iot, ioh, EG_CONTROL, EG_CTL_RESET);
322 bus_space_write_1(iot, ioh, EG_CONTROL, 0);
323 for (i = 0; i < 500; i++) {
324 delay(1000);
325 if ((bus_space_read_1(iot, ioh, EG_STATUS) &
326 EG_PCB_STAT) == EG_PCB_NULL)
327 break;
328 }
329 if ((bus_space_read_1(iot, ioh, EG_STATUS) & EG_PCB_STAT) != EG_PCB_NULL) {
330 DPRINTF(("egprobe: Reset failed\n"));
331 goto out;
332 }
333 pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
334 pcb[1] = 0;
335 if (egwritePCB(iot, ioh, pcb) != 0)
336 goto out;
337
338 if ((egreadPCB(iot, ioh, pcb) != 0) ||
339 pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
340 pcb[1] != 0x0a) {
341 egprintpcb(pcb);
342 goto out;
343 }
344
345 ia->ia_nio = 1;
346 ia->ia_io[0].ir_size = 0x08;
347
348 ia->ia_nirq = 1;
349
350 ia->ia_niomem = 0;
351 ia->ia_ndrq = 0;
352
353 rval = 1;
354
355 out:
356 bus_space_unmap(iot, ioh, 0x08);
357 return rval;
358 }
359
360 void
361 egattach(device_t parent, device_t self, void *aux)
362 {
363 struct eg_softc *sc = device_private(self);
364 struct isa_attach_args *ia = aux;
365 bus_space_tag_t iot = ia->ia_iot;
366 bus_space_handle_t ioh;
367 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
368 u_int8_t myaddr[ETHER_ADDR_LEN];
369
370 sc->sc_dev = self;
371
372 printf("\n");
373
374 /* Map i/o space. */
375 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 0x08, 0, &ioh)) {
376 aprint_error_dev(self, "can't map i/o space\n");
377 return;
378 }
379
380 sc->sc_iot = iot;
381 sc->sc_ioh = ioh;
382
383 sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
384 sc->eg_pcb[1] = 0;
385 if (egwritePCB(iot, ioh, sc->eg_pcb) != 0) {
386 aprint_error_dev(self, "error requesting adapter info\n");
387 return;
388 }
389 if (egreadPCB(iot, ioh, sc->eg_pcb) != 0) {
390 egprintpcb(sc->eg_pcb);
391 aprint_error_dev(self, "error reading adapter info\n");
392 return;
393 }
394
395 if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
396 sc->eg_pcb[1] != 0x0a) {
397 egprintpcb(sc->eg_pcb);
398 aprint_error_dev(self, "bogus adapter info\n");
399 return;
400 }
401
402 sc->eg_rom_major = sc->eg_pcb[3];
403 sc->eg_rom_minor = sc->eg_pcb[2];
404 sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
405
406 egstop(sc);
407
408 sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
409 sc->eg_pcb[1] = 0;
410 if (egwritePCB(iot, ioh, sc->eg_pcb) != 0) {
411 aprint_error_dev(self, "can't send Get Station Address\n");
412 return;
413 }
414 if (egreadPCB(iot, ioh, sc->eg_pcb) != 0) {
415 aprint_error_dev(self, "can't read station address\n");
416 egprintpcb(sc->eg_pcb);
417 return;
418 }
419
420 /* check Get station address response */
421 if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) {
422 aprint_error_dev(self, "card responded with garbage (1)\n");
423 egprintpcb(sc->eg_pcb);
424 return;
425 }
426 memcpy(myaddr, &sc->eg_pcb[2], ETHER_ADDR_LEN);
427
428 aprint_normal_dev(self, "ROM v%d.%02d %dk address %s\n",
429 sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram,
430 ether_sprintf(myaddr));
431
432 sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
433 if (egwritePCB(iot, ioh, sc->eg_pcb) != 0) {
434 aprint_error_dev(self, "can't send Set Station Address\n");
435 return;
436 }
437 if (egreadPCB(iot, ioh, sc->eg_pcb) != 0) {
438 aprint_error_dev(self,
439 "can't read Set Station Address status\n");
440 egprintpcb(sc->eg_pcb);
441 return;
442 }
443 if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
444 sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
445 aprint_error_dev(self, "card responded with garbage (2)\n");
446 egprintpcb(sc->eg_pcb);
447 return;
448 }
449
450 /* Initialize ifnet structure. */
451 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
452 ifp->if_softc = sc;
453 ifp->if_start = egstart;
454 ifp->if_ioctl = egioctl;
455 ifp->if_watchdog = egwatchdog;
456 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
457 IFQ_SET_READY(&ifp->if_snd);
458
459 /* Now we can attach the interface. */
460 if_attach(ifp);
461 ether_ifattach(ifp, myaddr);
462
463 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
464 IST_EDGE, IPL_NET, egintr, sc);
465
466 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
467 RND_TYPE_NET, RND_FLAG_DEFAULT);
468 }
469
470 void
471 eginit(struct eg_softc *sc)
472 {
473 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
474 bus_space_tag_t iot = sc->sc_iot;
475 bus_space_handle_t ioh = sc->sc_ioh;
476
477 /* soft reset the board */
478 bus_space_write_1(iot, ioh, EG_CONTROL, EG_CTL_FLSH);
479 delay(100);
480 bus_space_write_1(iot, ioh, EG_CONTROL, EG_CTL_ATTN);
481 delay(100);
482 bus_space_write_1(iot, ioh, EG_CONTROL, 0);
483 delay(200);
484
485 sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
486 sc->eg_pcb[1] = 2;
487 sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
488 sc->eg_pcb[3] = 0;
489 if (egwritePCB(iot, ioh, sc->eg_pcb) != 0)
490 aprint_error_dev(sc->sc_dev, "can't send Configure 82586\n");
491
492 if (egreadPCB(iot, ioh, sc->eg_pcb) != 0) {
493 aprint_error_dev(sc->sc_dev,
494 "can't read Configure 82586 status\n");
495 egprintpcb(sc->eg_pcb);
496 } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
497 aprint_error_dev(sc->sc_dev,"configure card command failed\n");
498
499 if (sc->eg_inbuf == NULL) {
500 sc->eg_inbuf = kmem_alloc(EG_BUFLEN, KM_NOSLEEP);
501 if (sc->eg_inbuf == NULL) {
502 aprint_error_dev(sc->sc_dev, "can't allocate inbuf\n");
503 panic("eginit");
504 }
505 }
506 sc->eg_incount = 0;
507
508 if (sc->eg_outbuf == NULL) {
509 sc->eg_outbuf = kmem_alloc(EG_BUFLEN, KM_NOSLEEP);
510 if (sc->eg_outbuf == NULL) {
511 aprint_error_dev(sc->sc_dev,"can't allocate outbuf\n");
512 panic("eginit");
513 }
514 }
515
516 bus_space_write_1(iot, ioh, EG_CONTROL, EG_CTL_CMDE);
517
518 sc->eg_incount = 0;
519 egrecv(sc);
520
521 /* Interface is now `running', with no output active. */
522 ifp->if_flags |= IFF_RUNNING;
523 ifp->if_flags &= ~IFF_OACTIVE;
524
525 /* Attempt to start output, if any. */
526 egstart(ifp);
527 }
528
529 void
530 egrecv(struct eg_softc *sc)
531 {
532
533 while (sc->eg_incount < EG_INLEN) {
534 sc->eg_pcb[0] = EG_CMD_RECVPACKET;
535 sc->eg_pcb[1] = 0x08;
536 sc->eg_pcb[2] = 0; /* address not used.. we send zero */
537 sc->eg_pcb[3] = 0;
538 sc->eg_pcb[4] = 0;
539 sc->eg_pcb[5] = 0;
540 sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
541 sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
542 sc->eg_pcb[8] = 0; /* timeout, 0 == none */
543 sc->eg_pcb[9] = 0;
544 if (egwritePCB(sc->sc_iot, sc->sc_ioh, sc->eg_pcb) != 0)
545 break;
546 sc->eg_incount++;
547 }
548 }
549
550 void
551 egstart(struct ifnet *ifp)
552 {
553 struct eg_softc *sc = ifp->if_softc;
554 bus_space_tag_t iot = sc->sc_iot;
555 bus_space_handle_t ioh = sc->sc_ioh;
556 struct mbuf *m0, *m;
557 char *buffer;
558 int len;
559 u_int16_t *ptr;
560
561 /* Don't transmit if interface is busy or not running */
562 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
563 return;
564
565 loop:
566 /* Dequeue the next datagram. */
567 IFQ_DEQUEUE(&ifp->if_snd, m0);
568 if (m0 == 0)
569 return;
570
571 ifp->if_flags |= IFF_OACTIVE;
572
573 /* We need to use m->m_pkthdr.len, so require the header */
574 if ((m0->m_flags & M_PKTHDR) == 0) {
575 aprint_error_dev(sc->sc_dev, "no header mbuf\n");
576 panic("egstart");
577 }
578 len = uimax(m0->m_pkthdr.len, ETHER_MIN_LEN - ETHER_CRC_LEN);
579
580 bpf_mtap(ifp, m0, BPF_D_OUT);
581
582 sc->eg_pcb[0] = EG_CMD_SENDPACKET;
583 sc->eg_pcb[1] = 0x06;
584 sc->eg_pcb[2] = 0; /* address not used, we send zero */
585 sc->eg_pcb[3] = 0;
586 sc->eg_pcb[4] = 0;
587 sc->eg_pcb[5] = 0;
588 sc->eg_pcb[6] = len; /* length of packet */
589 sc->eg_pcb[7] = len >> 8;
590 if (egwritePCB(iot, ioh, sc->eg_pcb) != 0) {
591 aprint_error_dev(sc->sc_dev,
592 "can't send Send Packet command\n");
593 if_statinc(ifp, if_oerrors);
594 ifp->if_flags &= ~IFF_OACTIVE;
595 m_freem(m0);
596 goto loop;
597 }
598
599 buffer = sc->eg_outbuf;
600 for (m = m0; m != 0; m = m->m_next) {
601 memcpy(buffer, mtod(m, void *), m->m_len);
602 buffer += m->m_len;
603 }
604 if (len > m0->m_pkthdr.len)
605 memset(buffer, 0, len - m0->m_pkthdr.len);
606
607 /* set direction bit: host -> adapter */
608 bus_space_write_1(iot, ioh, EG_CONTROL,
609 bus_space_read_1(iot, ioh, EG_CONTROL) & ~EG_CTL_DIR);
610
611 for (ptr = (u_int16_t *) sc->eg_outbuf; len > 0; len -= 2) {
612 bus_space_write_2(iot, ioh, EG_DATA, *ptr++);
613 while (!(bus_space_read_1(iot, ioh, EG_STATUS) & EG_STAT_HRDY))
614 ; /* XXX need timeout here */
615 }
616
617 m_freem(m0);
618 }
619
620 int
621 egintr(void *arg)
622 {
623 struct eg_softc *sc = arg;
624 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
625 bus_space_tag_t iot = sc->sc_iot;
626 bus_space_handle_t ioh = sc->sc_ioh;
627 int i, len, serviced;
628 u_int16_t *ptr;
629
630 serviced = 0;
631
632 while (bus_space_read_1(iot, ioh, EG_STATUS) & EG_STAT_ACRF) {
633 egreadPCB(iot, ioh, sc->eg_pcb);
634 switch (sc->eg_pcb[0]) {
635 case EG_RSP_RECVPACKET:
636 len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
637
638 /* Set direction bit : Adapter -> host */
639 bus_space_write_1(iot, ioh, EG_CONTROL,
640 bus_space_read_1(iot, ioh, EG_CONTROL) | EG_CTL_DIR);
641
642 for (ptr = (u_int16_t *) sc->eg_inbuf;
643 len > 0; len -= 2) {
644 while (!(bus_space_read_1(iot, ioh, EG_STATUS) &
645 EG_STAT_HRDY))
646 ;
647 *ptr++ = bus_space_read_2(iot, ioh, EG_DATA);
648 }
649
650 len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8);
651 egread(sc, sc->eg_inbuf, len);
652
653 sc->eg_incount--;
654 egrecv(sc);
655 serviced = 1;
656 break;
657
658 case EG_RSP_SENDPACKET:
659 if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
660 DPRINTF(("%s: packet dropped\n",
661 device_xname(sc->sc_dev)));
662 if_statinc(ifp, if_oerrors);
663 } else
664 if_statinc(ifp, if_opackets);
665 if (sc->eg_pcb[8] & 0xf)
666 if_statadd(ifp, if_collisions,
667 sc->eg_pcb[8] & 0xf);
668 sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
669 egstart(&sc->sc_ethercom.ec_if);
670 serviced = 1;
671 break;
672
673 /* XXX byte-order and type-size bugs here... */
674 case EG_RSP_GETSTATS:
675 DPRINTF(("%s: Card Statistics\n",
676 device_xname(sc->sc_dev)));
677 memcpy(&i, &sc->eg_pcb[2], sizeof(i));
678 DPRINTF(("Receive Packets %d\n", i));
679 memcpy(&i, &sc->eg_pcb[6], sizeof(i));
680 DPRINTF(("Transmit Packets %d\n", i));
681 DPRINTF(("CRC errors %d\n",
682 *(short *) &sc->eg_pcb[10]));
683 DPRINTF(("alignment errors %d\n",
684 *(short *) &sc->eg_pcb[12]));
685 DPRINTF(("no resources errors %d\n",
686 *(short *) &sc->eg_pcb[14]));
687 DPRINTF(("overrun errors %d\n",
688 *(short *) &sc->eg_pcb[16]));
689 serviced = 1;
690 break;
691
692 default:
693 printf("%s: egintr: Unknown response %x??\n",
694 device_xname(sc->sc_dev), sc->eg_pcb[0]);
695 egprintpcb(sc->eg_pcb);
696 break;
697 }
698
699 rnd_add_uint32(&sc->rnd_source, sc->eg_pcb[0]);
700 }
701
702 return serviced;
703 }
704
705 /*
706 * Pass a packet up to the higher levels.
707 */
708 void
709 egread(struct eg_softc *sc, void *buf, int len)
710 {
711 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
712 struct mbuf *m;
713
714 if (len <= sizeof(struct ether_header) ||
715 len > ETHER_MAX_LEN) {
716 aprint_error_dev(sc->sc_dev,
717 "invalid packet size %d; dropping\n", len);
718 if_statinc(ifp, if_ierrors);
719 return;
720 }
721
722 /* Pull packet off interface. */
723 m = egget(sc, buf, len);
724 if (m == 0) {
725 if_statinc(ifp, if_ierrors);
726 return;
727 }
728
729 if_percpuq_enqueue(ifp->if_percpuq, m);
730 }
731
732 /*
733 * convert buf into mbufs
734 */
735 struct mbuf *
736 egget(struct eg_softc *sc, void *buf, int totlen)
737 {
738 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
739 struct mbuf *m, *m0, *newm;
740 int len;
741
742 MGETHDR(m0, M_DONTWAIT, MT_DATA);
743 if (m0 == 0)
744 return (0);
745 m_set_rcvif(m0, ifp);
746 m0->m_pkthdr.len = totlen;
747 len = MHLEN;
748 m = m0;
749
750 while (totlen > 0) {
751 if (totlen >= MINCLSIZE) {
752 MCLGET(m, M_DONTWAIT);
753 if ((m->m_flags & M_EXT) == 0)
754 goto bad;
755 len = MCLBYTES;
756 }
757
758 m->m_len = len = uimin(totlen, len);
759 memcpy(mtod(m, void *), buf, len);
760 buf = (char *)buf + len;
761
762 totlen -= len;
763 if (totlen > 0) {
764 MGET(newm, M_DONTWAIT, MT_DATA);
765 if (newm == 0)
766 goto bad;
767 len = MLEN;
768 m = m->m_next = newm;
769 }
770 }
771
772 return (m0);
773
774 bad:
775 m_freem(m0);
776 return (0);
777 }
778
779 int
780 egioctl(struct ifnet *ifp, unsigned long cmd, void *data)
781 {
782 struct eg_softc *sc = ifp->if_softc;
783 struct ifaddr *ifa = (struct ifaddr *)data;
784 int s, error = 0;
785
786 s = splnet();
787
788 switch (cmd) {
789
790 case SIOCINITIFADDR:
791 ifp->if_flags |= IFF_UP;
792
793 eginit(sc);
794 switch (ifa->ifa_addr->sa_family) {
795 #ifdef INET
796 case AF_INET:
797 arp_ifinit(ifp, ifa);
798 break;
799 #endif
800 default:
801 break;
802 }
803 break;
804
805 case SIOCSIFFLAGS:
806 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
807 break;
808 /* XXX re-use ether_ioctl() */
809 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
810 case IFF_RUNNING:
811 /*
812 * If interface is marked down and it is running, then
813 * stop it.
814 */
815 egstop(sc);
816 ifp->if_flags &= ~IFF_RUNNING;
817 break;
818 case IFF_UP:
819 /*
820 * If interface is marked up and it is stopped, then
821 * start it.
822 */
823 eginit(sc);
824 break;
825 default:
826 sc->eg_pcb[0] = EG_CMD_GETSTATS;
827 sc->eg_pcb[1] = 0;
828 if (egwritePCB(sc->sc_iot, sc->sc_ioh, sc->eg_pcb) != 0) {
829 DPRINTF(("write error\n"));
830 }
831 /*
832 * XXX deal with flags changes:
833 * IFF_MULTICAST, IFF_PROMISC,
834 * IFF_LINK0, IFF_LINK1,
835 */
836 break;
837 }
838 break;
839
840 default:
841 error = ether_ioctl(ifp, cmd, data);
842 break;
843 }
844
845 splx(s);
846 return error;
847 }
848
849 void
850 egreset(struct eg_softc *sc)
851 {
852 int s;
853
854 DPRINTF(("%s: egreset()\n", device_xname(sc->sc_dev)));
855 s = splnet();
856 egstop(sc);
857 eginit(sc);
858 splx(s);
859 }
860
861 void
862 egwatchdog(struct ifnet *ifp)
863 {
864 struct eg_softc *sc = ifp->if_softc;
865
866 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
867 if_statinc(ifp, if_oerrors);
868
869 egreset(sc);
870 }
871
872 void
873 egstop(struct eg_softc *sc)
874 {
875
876 bus_space_write_1(sc->sc_iot, sc->sc_ioh, EG_CONTROL, 0);
877 }
878