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