1 /* $NetBSD: if_eg.c,v 1.79 2009/05/12 08:44:19 cegger Exp $ */
4 * Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
33 * Support for 3Com 3c505 Etherlink+ card.
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: if_eg.c,v 1.79 2009/05/12 08:44:19 cegger Exp $");
49 #include <sys/param.h>
50 #include <sys/systm.h>
52 #include <sys/socket.h>
53 #include <sys/ioctl.h>
54 #include <sys/errno.h>
55 #include <sys/syslog.h>
56 #include <sys/select.h>
57 #include <sys/device.h>
63 #include <net/if_dl.h>
64 #include <net/if_types.h>
66 #include <net/if_ether.h>
69 #include <netinet/in.h>
70 #include <netinet/in_systm.h>
71 #include <netinet/in_var.h>
72 #include <netinet/ip.h>
73 #include <netinet/if_inarp.h>
79 #include <net/bpfdesc.h>
86 #include <dev/isa/isavar.h>
87 #include <dev/isa/if_egreg.h>
88 #include <dev/isa/elink.h>
90 /* for debugging convenience */
92 #define DPRINTF(x) printf x
98 #define EG_BUFLEN 0x0670
103 * Ethernet software status per interface.
106 struct device sc_dev
;
108 struct ethercom sc_ethercom
; /* Ethernet common part */
109 bus_space_tag_t sc_iot
; /* bus space identifier */
110 bus_space_handle_t sc_ioh
; /* i/o handle */
111 u_int8_t eg_rom_major
; /* Cards ROM version (major number) */
112 u_int8_t eg_rom_minor
; /* Cards ROM version (minor number) */
113 short eg_ram
; /* Amount of RAM on the card */
114 u_int8_t eg_pcb
[EG_PCBLEN
]; /* Primary Command Block buffer */
115 u_int8_t eg_incount
; /* Number of buffers currently used */
116 void * eg_inbuf
; /* Incoming packet buffer */
117 void * eg_outbuf
; /* Outgoing packet buffer */
120 rndsource_element_t rnd_source
;
124 int egprobe(device_t
, cfdata_t
, void *);
125 void egattach(device_t
, device_t
, void *);
127 CFATTACH_DECL(eg
, sizeof(struct eg_softc
),
128 egprobe
, egattach
, NULL
, NULL
);
131 void eginit(struct eg_softc
*);
132 int egioctl(struct ifnet
*, u_long
, void *);
133 void egrecv(struct eg_softc
*);
134 void egstart(struct ifnet
*);
135 void egwatchdog(struct ifnet
*);
136 void egreset(struct eg_softc
*);
137 void egread(struct eg_softc
*, void *, int);
138 struct mbuf
*egget(struct eg_softc
*, void *, int);
139 void egstop(struct eg_softc
*);
141 static inline void egprintpcb(u_int8_t
*);
142 static inline void egprintstat(u_char
);
143 static int egoutPCB(bus_space_tag_t
, bus_space_handle_t
, u_int8_t
);
144 static int egreadPCBstat(bus_space_tag_t
, bus_space_handle_t
, u_int8_t
);
145 static int egreadPCBready(bus_space_tag_t
, bus_space_handle_t
);
146 static int egwritePCB(bus_space_tag_t
, bus_space_handle_t
, u_int8_t
*);
147 static int egreadPCB(bus_space_tag_t
, bus_space_handle_t
, u_int8_t
*);
154 egprintpcb(u_int8_t
*pcb
)
158 for (i
= 0; i
< pcb
[1] + 2; i
++)
159 DPRINTF(("pcb[%2d] = %x\n", i
, pcb
[i
]));
164 egprintstat(u_char b
)
166 DPRINTF(("%s %s %s %s %s %s %s\n",
167 (b
& EG_STAT_HCRE
)?"HCRE":"",
168 (b
& EG_STAT_ACRF
)?"ACRF":"",
169 (b
& EG_STAT_DIR
)?"DIR ":"",
170 (b
& EG_STAT_DONE
)?"DONE":"",
171 (b
& EG_STAT_ASF3
)?"ASF3":"",
172 (b
& EG_STAT_ASF2
)?"ASF2":"",
173 (b
& EG_STAT_ASF1
)?"ASF1":""));
177 egoutPCB(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int8_t b
)
181 for (i
=0; i
< 4000; i
++) {
182 if (bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_STAT_HCRE
) {
183 bus_space_write_1(iot
, ioh
, EG_COMMAND
, b
);
188 DPRINTF(("egoutPCB failed\n"));
193 egreadPCBstat(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int8_t statb
)
197 for (i
=0; i
< 5000; i
++) {
198 if ((bus_space_read_1(iot
, ioh
, EG_STATUS
) &
199 EG_PCB_STAT
) != EG_PCB_NULL
)
203 if ((bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_PCB_STAT
) == statb
)
209 egreadPCBready(bus_space_tag_t iot
, bus_space_handle_t ioh
)
213 for (i
=0; i
< 10000; i
++) {
214 if (bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_STAT_ACRF
)
218 DPRINTF(("PCB read not ready\n"));
223 egwritePCB(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int8_t
*pcb
)
228 bus_space_write_1(iot
, ioh
, EG_CONTROL
,
229 (bus_space_read_1(iot
, ioh
, EG_CONTROL
) & ~EG_PCB_STAT
) | EG_PCB_NULL
);
232 for (i
= 0; i
< len
; i
++)
233 egoutPCB(iot
, ioh
, pcb
[i
]);
235 for (i
=0; i
< 4000; i
++) {
236 if (bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_STAT_HCRE
)
241 bus_space_write_1(iot
, ioh
, EG_CONTROL
,
242 (bus_space_read_1(iot
, ioh
, EG_CONTROL
) & ~EG_PCB_STAT
) | EG_PCB_DONE
);
244 egoutPCB(iot
, ioh
, len
);
246 if (egreadPCBstat(iot
, ioh
, EG_PCB_ACCEPT
))
252 egreadPCB(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int8_t
*pcb
)
256 bus_space_write_1(iot
, ioh
, EG_CONTROL
,
257 (bus_space_read_1(iot
, ioh
, EG_CONTROL
) & ~EG_PCB_STAT
) | EG_PCB_NULL
);
259 memset(pcb
, 0, EG_PCBLEN
);
261 if (egreadPCBready(iot
, ioh
))
264 pcb
[0] = bus_space_read_1(iot
, ioh
, EG_COMMAND
);
266 if (egreadPCBready(iot
, ioh
))
269 pcb
[1] = bus_space_read_1(iot
, ioh
, EG_COMMAND
);
272 DPRINTF(("len %d too large\n", pcb
[1]));
276 for (i
= 0; i
< pcb
[1]; i
++) {
277 if (egreadPCBready(iot
, ioh
))
279 pcb
[2+i
] = bus_space_read_1(iot
, ioh
, EG_COMMAND
);
281 if (egreadPCBready(iot
, ioh
))
283 if (egreadPCBstat(iot
, ioh
, EG_PCB_DONE
))
285 if (bus_space_read_1(iot
, ioh
, EG_COMMAND
) != pcb
[1] + 2) {
289 bus_space_write_1(iot
, ioh
, EG_CONTROL
,
290 (bus_space_read_1(iot
, ioh
, EG_CONTROL
) &
291 ~EG_PCB_STAT
) | EG_PCB_ACCEPT
);
301 egprobe(device_t parent
, cfdata_t match
, void *aux
)
303 struct isa_attach_args
*ia
= aux
;
304 bus_space_tag_t iot
= ia
->ia_iot
;
305 bus_space_handle_t ioh
;
307 static u_int8_t pcb
[EG_PCBLEN
];
312 * XXX This probe is slow. If there are no ISA expansion slots,
315 if (isa_get_slotcount() == 0)
323 if (ISA_DIRECT_CONFIG(ia
))
326 /* Disallow wildcarded i/o address. */
327 if (ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
330 /* Disallow wildcarded IRQ. */
331 if (ia
->ia_irq
[0].ir_irq
== ISA_UNKNOWN_IRQ
)
334 if ((ia
->ia_io
[0].ir_addr
& ~0x07f0) != 0) {
335 DPRINTF(("Weird iobase %x\n", ia
->ia_io
[0].ir_addr
));
340 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, 0x08, 0, &ioh
)) {
341 DPRINTF(("egprobe: can't map i/o space in probe\n"));
345 /* hard reset card */
346 bus_space_write_1(iot
, ioh
, EG_CONTROL
, EG_CTL_RESET
);
347 bus_space_write_1(iot
, ioh
, EG_CONTROL
, 0);
348 for (i
= 0; i
< 500; i
++) {
350 if ((bus_space_read_1(iot
, ioh
, EG_STATUS
) &
351 EG_PCB_STAT
) == EG_PCB_NULL
)
354 if ((bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_PCB_STAT
) != EG_PCB_NULL
) {
355 DPRINTF(("egprobe: Reset failed\n"));
358 pcb
[0] = EG_CMD_GETINFO
; /* Get Adapter Info */
360 if (egwritePCB(iot
, ioh
, pcb
) != 0)
363 if ((egreadPCB(iot
, ioh
, pcb
) != 0) ||
364 pcb
[0] != EG_RSP_GETINFO
|| /* Get Adapter Info Response */
371 ia
->ia_io
[0].ir_size
= 0x08;
381 bus_space_unmap(iot
, ioh
, 0x08);
386 egattach(device_t parent
, device_t self
, void *aux
)
388 struct eg_softc
*sc
= (void *)self
;
389 struct isa_attach_args
*ia
= aux
;
390 bus_space_tag_t iot
= ia
->ia_iot
;
391 bus_space_handle_t ioh
;
392 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
393 u_int8_t myaddr
[ETHER_ADDR_LEN
];
398 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, 0x08, 0, &ioh
)) {
399 aprint_error_dev(self
, "can't map i/o space\n");
406 sc
->eg_pcb
[0] = EG_CMD_GETINFO
; /* Get Adapter Info */
408 if (egwritePCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
409 aprint_error_dev(self
, "error requesting adapter info\n");
412 if (egreadPCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
413 egprintpcb(sc
->eg_pcb
);
414 aprint_error_dev(self
, "error reading adapter info\n");
418 if (sc
->eg_pcb
[0] != EG_RSP_GETINFO
|| /* Get Adapter Info Response */
419 sc
->eg_pcb
[1] != 0x0a) {
420 egprintpcb(sc
->eg_pcb
);
421 aprint_error_dev(self
, "bogus adapter info\n");
425 sc
->eg_rom_major
= sc
->eg_pcb
[3];
426 sc
->eg_rom_minor
= sc
->eg_pcb
[2];
427 sc
->eg_ram
= sc
->eg_pcb
[6] | (sc
->eg_pcb
[7] << 8);
431 sc
->eg_pcb
[0] = EG_CMD_GETEADDR
; /* Get Station address */
433 if (egwritePCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
434 aprint_error_dev(self
, "can't send Get Station Address\n");
437 if (egreadPCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
438 aprint_error_dev(self
, "can't read station address\n");
439 egprintpcb(sc
->eg_pcb
);
443 /* check Get station address response */
444 if (sc
->eg_pcb
[0] != EG_RSP_GETEADDR
|| sc
->eg_pcb
[1] != 0x06) {
445 aprint_error_dev(self
, "card responded with garbage (1)\n");
446 egprintpcb(sc
->eg_pcb
);
449 memcpy(myaddr
, &sc
->eg_pcb
[2], ETHER_ADDR_LEN
);
451 printf("%s: ROM v%d.%02d %dk address %s\n", device_xname(self
),
452 sc
->eg_rom_major
, sc
->eg_rom_minor
, sc
->eg_ram
,
453 ether_sprintf(myaddr
));
455 sc
->eg_pcb
[0] = EG_CMD_SETEADDR
; /* Set station address */
456 if (egwritePCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
457 printf("%s: can't send Set Station Address\n", device_xname(self
));
460 if (egreadPCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
461 aprint_error_dev(self
, "can't read Set Station Address status\n");
462 egprintpcb(sc
->eg_pcb
);
465 if (sc
->eg_pcb
[0] != EG_RSP_SETEADDR
|| sc
->eg_pcb
[1] != 0x02 ||
466 sc
->eg_pcb
[2] != 0 || sc
->eg_pcb
[3] != 0) {
467 aprint_error_dev(self
, "card responded with garbage (2)\n");
468 egprintpcb(sc
->eg_pcb
);
472 /* Initialize ifnet structure. */
473 strlcpy(ifp
->if_xname
, device_xname(&sc
->sc_dev
), IFNAMSIZ
);
475 ifp
->if_start
= egstart
;
476 ifp
->if_ioctl
= egioctl
;
477 ifp
->if_watchdog
= egwatchdog
;
478 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
;
479 IFQ_SET_READY(&ifp
->if_snd
);
481 /* Now we can attach the interface. */
483 ether_ifattach(ifp
, myaddr
);
485 sc
->sc_ih
= isa_intr_establish(ia
->ia_ic
, ia
->ia_irq
[0].ir_irq
,
486 IST_EDGE
, IPL_NET
, egintr
, sc
);
489 rnd_attach_source(&sc
->rnd_source
, device_xname(&sc
->sc_dev
),
495 eginit(struct eg_softc
*sc
)
497 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
498 bus_space_tag_t iot
= sc
->sc_iot
;
499 bus_space_handle_t ioh
= sc
->sc_ioh
;
501 /* soft reset the board */
502 bus_space_write_1(iot
, ioh
, EG_CONTROL
, EG_CTL_FLSH
);
504 bus_space_write_1(iot
, ioh
, EG_CONTROL
, EG_CTL_ATTN
);
506 bus_space_write_1(iot
, ioh
, EG_CONTROL
, 0);
509 sc
->eg_pcb
[0] = EG_CMD_CONFIG82586
; /* Configure 82586 */
511 sc
->eg_pcb
[2] = 3; /* receive broadcast & multicast */
513 if (egwritePCB(iot
, ioh
, sc
->eg_pcb
) != 0)
514 aprint_error_dev(&sc
->sc_dev
, "can't send Configure 82586\n");
516 if (egreadPCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
517 aprint_error_dev(&sc
->sc_dev
, "can't read Configure 82586 status\n");
518 egprintpcb(sc
->eg_pcb
);
519 } else if (sc
->eg_pcb
[2] != 0 || sc
->eg_pcb
[3] != 0)
520 aprint_error_dev(&sc
->sc_dev
, "configure card command failed\n");
522 if (sc
->eg_inbuf
== NULL
) {
523 sc
->eg_inbuf
= malloc(EG_BUFLEN
, M_TEMP
, M_NOWAIT
);
524 if (sc
->eg_inbuf
== NULL
) {
525 aprint_error_dev(&sc
->sc_dev
, "can't allocate inbuf\n");
531 if (sc
->eg_outbuf
== NULL
) {
532 sc
->eg_outbuf
= malloc(EG_BUFLEN
, M_TEMP
, M_NOWAIT
);
533 if (sc
->eg_outbuf
== NULL
) {
534 aprint_error_dev(&sc
->sc_dev
, "can't allocate outbuf\n");
539 bus_space_write_1(iot
, ioh
, EG_CONTROL
, EG_CTL_CMDE
);
544 /* Interface is now `running', with no output active. */
545 ifp
->if_flags
|= IFF_RUNNING
;
546 ifp
->if_flags
&= ~IFF_OACTIVE
;
548 /* Attempt to start output, if any. */
553 egrecv(struct eg_softc
*sc
)
556 while (sc
->eg_incount
< EG_INLEN
) {
557 sc
->eg_pcb
[0] = EG_CMD_RECVPACKET
;
558 sc
->eg_pcb
[1] = 0x08;
559 sc
->eg_pcb
[2] = 0; /* address not used.. we send zero */
563 sc
->eg_pcb
[6] = EG_BUFLEN
& 0xff; /* our buffer size */
564 sc
->eg_pcb
[7] = (EG_BUFLEN
>> 8) & 0xff;
565 sc
->eg_pcb
[8] = 0; /* timeout, 0 == none */
567 if (egwritePCB(sc
->sc_iot
, sc
->sc_ioh
, sc
->eg_pcb
) != 0)
574 egstart(struct ifnet
*ifp
)
576 struct eg_softc
*sc
= ifp
->if_softc
;
577 bus_space_tag_t iot
= sc
->sc_iot
;
578 bus_space_handle_t ioh
= sc
->sc_ioh
;
584 /* Don't transmit if interface is busy or not running */
585 if ((ifp
->if_flags
& (IFF_RUNNING
|IFF_OACTIVE
)) != IFF_RUNNING
)
589 /* Dequeue the next datagram. */
590 IFQ_DEQUEUE(&ifp
->if_snd
, m0
);
594 ifp
->if_flags
|= IFF_OACTIVE
;
596 /* We need to use m->m_pkthdr.len, so require the header */
597 if ((m0
->m_flags
& M_PKTHDR
) == 0) {
598 aprint_error_dev(&sc
->sc_dev
, "no header mbuf\n");
601 len
= max(m0
->m_pkthdr
.len
, ETHER_MIN_LEN
- ETHER_CRC_LEN
);
605 bpf_mtap(ifp
->if_bpf
, m0
);
608 sc
->eg_pcb
[0] = EG_CMD_SENDPACKET
;
609 sc
->eg_pcb
[1] = 0x06;
610 sc
->eg_pcb
[2] = 0; /* address not used, we send zero */
614 sc
->eg_pcb
[6] = len
; /* length of packet */
615 sc
->eg_pcb
[7] = len
>> 8;
616 if (egwritePCB(iot
, ioh
, sc
->eg_pcb
) != 0) {
617 aprint_error_dev(&sc
->sc_dev
, "can't send Send Packet command\n");
619 ifp
->if_flags
&= ~IFF_OACTIVE
;
624 buffer
= sc
->eg_outbuf
;
625 for (m
= m0
; m
!= 0; m
= m
->m_next
) {
626 memcpy(buffer
, mtod(m
, void *), m
->m_len
);
629 if (len
> m0
->m_pkthdr
.len
)
630 memset(buffer
, 0, len
- m0
->m_pkthdr
.len
);
632 /* set direction bit: host -> adapter */
633 bus_space_write_1(iot
, ioh
, EG_CONTROL
,
634 bus_space_read_1(iot
, ioh
, EG_CONTROL
) & ~EG_CTL_DIR
);
636 for (ptr
= (u_int16_t
*) sc
->eg_outbuf
; len
> 0; len
-= 2) {
637 bus_space_write_2(iot
, ioh
, EG_DATA
, *ptr
++);
638 while (!(bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_STAT_HRDY
))
639 ; /* XXX need timeout here */
648 struct eg_softc
*sc
= arg
;
649 bus_space_tag_t iot
= sc
->sc_iot
;
650 bus_space_handle_t ioh
= sc
->sc_ioh
;
651 int i
, len
, serviced
;
656 while (bus_space_read_1(iot
, ioh
, EG_STATUS
) & EG_STAT_ACRF
) {
657 egreadPCB(iot
, ioh
, sc
->eg_pcb
);
658 switch (sc
->eg_pcb
[0]) {
659 case EG_RSP_RECVPACKET
:
660 len
= sc
->eg_pcb
[6] | (sc
->eg_pcb
[7] << 8);
662 /* Set direction bit : Adapter -> host */
663 bus_space_write_1(iot
, ioh
, EG_CONTROL
,
664 bus_space_read_1(iot
, ioh
, EG_CONTROL
) | EG_CTL_DIR
);
666 for (ptr
= (u_int16_t
*) sc
->eg_inbuf
;
668 while (!(bus_space_read_1(iot
, ioh
, EG_STATUS
) &
671 *ptr
++ = bus_space_read_2(iot
, ioh
, EG_DATA
);
674 len
= sc
->eg_pcb
[8] | (sc
->eg_pcb
[9] << 8);
675 egread(sc
, sc
->eg_inbuf
, len
);
682 case EG_RSP_SENDPACKET
:
683 if (sc
->eg_pcb
[6] || sc
->eg_pcb
[7]) {
684 DPRINTF(("%s: packet dropped\n",
685 device_xname(&sc
->sc_dev
)));
686 sc
->sc_ethercom
.ec_if
.if_oerrors
++;
688 sc
->sc_ethercom
.ec_if
.if_opackets
++;
689 sc
->sc_ethercom
.ec_if
.if_collisions
+=
691 sc
->sc_ethercom
.ec_if
.if_flags
&= ~IFF_OACTIVE
;
692 egstart(&sc
->sc_ethercom
.ec_if
);
696 /* XXX byte-order and type-size bugs here... */
697 case EG_RSP_GETSTATS
:
698 DPRINTF(("%s: Card Statistics\n",
699 device_xname(&sc
->sc_dev
)));
700 memcpy(&i
, &sc
->eg_pcb
[2], sizeof(i
));
701 DPRINTF(("Receive Packets %d\n", i
));
702 memcpy(&i
, &sc
->eg_pcb
[6], sizeof(i
));
703 DPRINTF(("Transmit Packets %d\n", i
));
704 DPRINTF(("CRC errors %d\n",
705 *(short *) &sc
->eg_pcb
[10]));
706 DPRINTF(("alignment errors %d\n",
707 *(short *) &sc
->eg_pcb
[12]));
708 DPRINTF(("no resources errors %d\n",
709 *(short *) &sc
->eg_pcb
[14]));
710 DPRINTF(("overrun errors %d\n",
711 *(short *) &sc
->eg_pcb
[16]));
716 printf("%s: egintr: Unknown response %x??\n",
717 device_xname(&sc
->sc_dev
), sc
->eg_pcb
[0]);
718 egprintpcb(sc
->eg_pcb
);
723 rnd_add_uint32(&sc
->rnd_source
, sc
->eg_pcb
[0]);
731 * Pass a packet up to the higher levels.
734 egread(struct eg_softc
*sc
, void *buf
, int len
)
736 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
739 if (len
<= sizeof(struct ether_header
) ||
740 len
> ETHER_MAX_LEN
) {
741 aprint_error_dev(&sc
->sc_dev
, "invalid packet size %d; dropping\n", len
);
746 /* Pull packet off interface. */
747 m
= egget(sc
, buf
, len
);
757 * Check if there's a BPF listener on this interface.
758 * If so, hand off the raw packet to BPF.
761 bpf_mtap(ifp
->if_bpf
, m
);
764 (*ifp
->if_input
)(ifp
, m
);
768 * convert buf into mbufs
771 egget(struct eg_softc
*sc
, void *buf
, int totlen
)
773 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
774 struct mbuf
*m
, *m0
, *newm
;
777 MGETHDR(m0
, M_DONTWAIT
, MT_DATA
);
780 m0
->m_pkthdr
.rcvif
= ifp
;
781 m0
->m_pkthdr
.len
= totlen
;
786 if (totlen
>= MINCLSIZE
) {
787 MCLGET(m
, M_DONTWAIT
);
788 if ((m
->m_flags
& M_EXT
) == 0)
793 m
->m_len
= len
= min(totlen
, len
);
794 memcpy(mtod(m
, void *), buf
, len
);
795 buf
= (char *)buf
+ len
;
799 MGET(newm
, M_DONTWAIT
, MT_DATA
);
803 m
= m
->m_next
= newm
;
815 egioctl(struct ifnet
*ifp
, unsigned long cmd
, void *data
)
817 struct eg_softc
*sc
= ifp
->if_softc
;
818 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
826 ifp
->if_flags
|= IFF_UP
;
829 switch (ifa
->ifa_addr
->sa_family
) {
832 arp_ifinit(ifp
, ifa
);
841 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
843 /* XXX re-use ether_ioctl() */
844 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
847 * If interface is marked down and it is running, then
851 ifp
->if_flags
&= ~IFF_RUNNING
;
855 * If interface is marked up and it is stopped, then
861 sc
->eg_pcb
[0] = EG_CMD_GETSTATS
;
863 if (egwritePCB(sc
->sc_iot
, sc
->sc_ioh
, sc
->eg_pcb
) != 0) {
864 DPRINTF(("write error\n"));
867 * XXX deal with flags changes:
868 * IFF_MULTICAST, IFF_PROMISC,
869 * IFF_LINK0, IFF_LINK1,
876 error
= ether_ioctl(ifp
, cmd
, data
);
885 egreset(struct eg_softc
*sc
)
889 DPRINTF(("%s: egreset()\n", device_xname(&sc
->sc_dev
)));
897 egwatchdog(struct ifnet
*ifp
)
899 struct eg_softc
*sc
= ifp
->if_softc
;
901 log(LOG_ERR
, "%s: device timeout\n", device_xname(&sc
->sc_dev
));
902 sc
->sc_ethercom
.ec_if
.if_oerrors
++;
908 egstop(struct eg_softc
*sc
)
911 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, EG_CONTROL
, 0);