Home | History | Annotate | Line # | Download | only in ic
we.c revision 1.1
      1 /*	$NetBSD: we.c,v 1.1 2001/03/23 17:34:41 jdolecek Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 /*
     41  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
     42  * adapters.
     43  *
     44  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
     45  *
     46  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
     47  * copied, distributed, and sold, in both source and binary form provided that
     48  * the above copyright and these terms are retained.  Under no circumstances is
     49  * the author responsible for the proper functioning of this software, nor does
     50  * the author assume any responsibility for damages incurred with its use.
     51  */
     52 
     53 /*
     54  * Device driver for the Western Digital/SMC 8003 and 8013 series,
     55  * and the SMC Elite Ultra (8216).
     56  */
     57 
     58 #include "opt_inet.h"
     59 #include "opt_ns.h"
     60 #include "bpfilter.h"
     61 #include "rnd.h"
     62 
     63 #include <sys/param.h>
     64 #include <sys/systm.h>
     65 #include <sys/device.h>
     66 #include <sys/socket.h>
     67 #include <sys/mbuf.h>
     68 #include <sys/syslog.h>
     69 
     70 #include <net/if.h>
     71 #include <net/if_dl.h>
     72 #include <net/if_types.h>
     73 #include <net/if_media.h>
     74 
     75 #include <net/if_ether.h>
     76 
     77 #ifdef INET
     78 #include <netinet/in.h>
     79 #include <netinet/in_systm.h>
     80 #include <netinet/in_var.h>
     81 #include <netinet/ip.h>
     82 #include <netinet/if_inarp.h>
     83 #endif
     84 
     85 #ifdef NS
     86 #include <netns/ns.h>
     87 #include <netns/ns_if.h>
     88 #endif
     89 
     90 #if NBPFILTER > 0
     91 #include <net/bpf.h>
     92 #include <net/bpfdesc.h>
     93 #endif
     94 
     95 #include <machine/bus.h>
     96 #include <machine/bswap.h>
     97 #include <machine/intr.h>
     98 
     99 #include <dev/isa/isareg.h>
    100 #include <dev/isa/isavar.h>
    101 
    102 #include <dev/ic/dp8390reg.h>
    103 #include <dev/ic/dp8390var.h>
    104 #include <dev/ic/wereg.h>
    105 #include <dev/ic/wevar.h>
    106 
    107 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
    108 #define	bus_space_read_region_stream_2	bus_space_read_region_2
    109 #define	bus_space_write_stream_2	bus_space_write_2
    110 #define	bus_space_write_region_stream_2	bus_space_write_region_2
    111 #endif
    112 
    113 static void	we_set_media __P((struct we_softc *, int));
    114 
    115 static void	we_media_init __P((struct dp8390_softc *));
    116 
    117 static int	we_mediachange __P((struct dp8390_softc *));
    118 static void	we_mediastatus __P((struct dp8390_softc *, struct ifmediareq *));
    119 
    120 static void	we_recv_int __P((struct dp8390_softc *));
    121 static void	we_init_card __P((struct dp8390_softc *));
    122 static int	we_write_mbuf __P((struct dp8390_softc *, struct mbuf *, int));
    123 static int	we_ring_copy __P((struct dp8390_softc *, int, caddr_t, u_short));
    124 static void	we_read_hdr __P((struct dp8390_softc *, int, struct dp8390_ring *));
    125 static int	we_test_mem __P((struct dp8390_softc *));
    126 
    127 static __inline void we_readmem __P((struct we_softc *, int, u_int8_t *, int));
    128 
    129 /*
    130  * Delay needed when switching 16-bit access to shared memory.
    131  */
    132 #define	WE_DELAY(wsc) delay(3)
    133 
    134 /*
    135  * Enable card RAM, and 16-bit access.
    136  */
    137 #define	WE_MEM_ENABLE(wsc) \
    138 do { \
    139 	if ((wsc)->sc_16bitp) \
    140 		bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
    141 		    WE_LAAR, (wsc)->sc_laar_proto | WE_LAAR_M16EN); \
    142 	bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
    143 	    WE_MSR, wsc->sc_msr_proto | WE_MSR_MENB); \
    144 	WE_DELAY((wsc)); \
    145 } while (0)
    146 
    147 /*
    148  * Disable card RAM, and 16-bit access.
    149  */
    150 #define	WE_MEM_DISABLE(wsc) \
    151 do { \
    152 	bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
    153 	    WE_MSR, (wsc)->sc_msr_proto); \
    154 	if ((wsc)->sc_16bitp) \
    155 		bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
    156 		    WE_LAAR, (wsc)->sc_laar_proto); \
    157 	WE_DELAY((wsc)); \
    158 } while (0)
    159 
    160 int
    161 we_config(self, wsc, typestr)
    162 	struct device *self;
    163 	struct we_softc *wsc;
    164 	const char *typestr;
    165 {
    166 	struct dp8390_softc *sc = &wsc->sc_dp8390;
    167 	u_int8_t x;
    168 	int i, forced_16bit = 0;
    169 
    170 	/*
    171 	 * Allow user to override 16-bit mode.  8-bit takes precedence.
    172 	 */
    173 	if (self->dv_cfdata->cf_flags & WE_FLAGS_FORCE_16BIT_MODE) {
    174 		wsc->sc_16bitp = 1;
    175 		forced_16bit = 1;
    176 	}
    177 	if (self->dv_cfdata->cf_flags & WE_FLAGS_FORCE_8BIT_MODE)
    178 		wsc->sc_16bitp = 0;
    179 
    180 	/* Registers are linear. */
    181 	for (i = 0; i < 16; i++)
    182 		sc->sc_reg_map[i] = i;
    183 
    184 	/* Now we can use the NIC_{GET,PUT}() macros. */
    185 
    186 	printf("%s: %s Ethernet (%s-bit)\n", sc->sc_dev.dv_xname,
    187 	    typestr, wsc->sc_16bitp ? "16" : "8");
    188 
    189 	/* Get station address from EEPROM. */
    190 	for (i = 0; i < ETHER_ADDR_LEN; i++)
    191 		sc->sc_enaddr[i] = bus_space_read_1(wsc->sc_asict,
    192 					wsc->sc_asich, WE_PROM + i);
    193 
    194 	/*
    195 	 * Set upper address bits and 8/16 bit access to shared memory.
    196 	 */
    197 	if (sc->is790) {
    198 		wsc->sc_laar_proto =
    199 		    bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_LAAR) &
    200 		    ~WE_LAAR_M16EN;
    201 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_LAAR,
    202 		    wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0));
    203 	} else if ((wsc->sc_type & WE_SOFTCONFIG) ||
    204 #ifdef TOSH_ETHER
    205 	    (wsc->sc_type == WE_TYPE_TOSHIBA1) ||
    206 	    (wsc->sc_type == WE_TYPE_TOSHIBA4) ||
    207 #endif
    208 	    (forced_16bit) ||
    209 	    (wsc->sc_type == WE_TYPE_WD8013EBT)) {
    210 		wsc->sc_laar_proto = (wsc->sc_maddr >> 19) & WE_LAAR_ADDRHI;
    211 		if (wsc->sc_16bitp)
    212 			wsc->sc_laar_proto |= WE_LAAR_L16EN;
    213 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_LAAR,
    214 		    wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0));
    215 	}
    216 
    217 	/*
    218 	 * Set address and enable interface shared memory.
    219 	 */
    220 	if (sc->is790) {
    221 		/* XXX MAGIC CONSTANTS XXX */
    222 		x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, 0x04);
    223 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, 0x04, x | 0x80);
    224 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, 0x0b,
    225 		    ((wsc->sc_maddr >> 13) & 0x0f) |
    226 		    ((wsc->sc_maddr >> 11) & 0x40) |
    227 		    (bus_space_read_1(wsc->sc_asict, wsc->sc_asich, 0x0b) & 0xb0));
    228 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, 0x04, x);
    229 		wsc->sc_msr_proto = 0x00;
    230 		sc->cr_proto = 0x00;
    231 	} else {
    232 #ifdef TOSH_ETHER
    233 		if (wsc->sc_type == WE_TYPE_TOSHIBA1 ||
    234 		    wsc->sc_type == WE_TYPE_TOSHIBA4) {
    235 			bus_space_write_1(wsc->sc_asict, wsc->sc_asich,
    236 			    WE_MSR + 1,
    237 			    ((wsc->sc_maddr >> 8) & 0xe0) | 0x04);
    238 			bus_space_write_1(wsc->sc_asict, wsc->sc_asich,
    239 			    WE_MSR + 2,
    240 			    ((wsc->sc_maddr >> 16) & 0x0f));
    241 			wsc->sc_msr_proto = WE_MSR_POW;
    242 		} else
    243 #endif
    244 			wsc->sc_msr_proto = (wsc->sc_maddr >> 13) &
    245 			    WE_MSR_ADDR;
    246 
    247 		sc->cr_proto = ED_CR_RD2;
    248 	}
    249 
    250 	bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_MSR,
    251 	    wsc->sc_msr_proto | WE_MSR_MENB);
    252 	WE_DELAY(wsc);
    253 
    254 	/*
    255 	 * DCR gets:
    256 	 *
    257 	 *	FIFO threshold to 8, No auto-init Remote DMA,
    258 	 *	byte order=80x86.
    259 	 *
    260 	 * 16-bit cards also get word-wide DMA transfers.
    261 	 */
    262 	sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
    263 	    (wsc->sc_16bitp ? ED_DCR_WTS : 0);
    264 
    265 	sc->test_mem = we_test_mem;
    266 	sc->ring_copy = we_ring_copy;
    267 	sc->write_mbuf = we_write_mbuf;
    268 	sc->read_hdr = we_read_hdr;
    269 	sc->recv_int = we_recv_int;
    270 	sc->init_card = we_init_card;
    271 
    272 	sc->sc_mediachange = we_mediachange;
    273 	sc->sc_mediastatus = we_mediastatus;
    274 
    275 	sc->mem_start = 0;
    276 	/* sc->mem_size has to be set by frontend */
    277 
    278 	sc->sc_flags = self->dv_cfdata->cf_flags;
    279 
    280 	/* Do generic parts of attach. */
    281 	if (wsc->sc_type & WE_SOFTCONFIG)
    282 		sc->sc_media_init = we_media_init;
    283 	else
    284 		sc->sc_media_init = dp8390_media_init;
    285 	if (dp8390_config(sc)) {
    286 		printf("%s: configuration failed\n", sc->sc_dev.dv_xname);
    287 		return (1);
    288 	}
    289 
    290 	/*
    291 	 * Disable 16-bit access to shared memory - we leave it disabled
    292 	 * so that:
    293 	 *
    294 	 *	(1) machines reboot properly when the board is set to
    295 	 *	    16-bit mode and there are conflicting 8-bit devices
    296 	 *	    within the same 128k address space as this board's
    297 	 *	    shared memory, and
    298 	 *
    299 	 *	(2) so that other 8-bit devices with shared memory
    300 	 *	    in this same 128k address space will work.
    301 	 */
    302 	WE_MEM_DISABLE(wsc);
    303 
    304 	return (0);
    305 }
    306 
    307 static int
    308 we_test_mem(sc)
    309 	struct dp8390_softc *sc;
    310 {
    311 	struct we_softc *wsc = (struct we_softc *)sc;
    312 	bus_space_tag_t memt = sc->sc_buft;
    313 	bus_space_handle_t memh = sc->sc_bufh;
    314 	bus_size_t memsize = sc->mem_size;
    315 	int i;
    316 
    317 	if (wsc->sc_16bitp)
    318 		bus_space_set_region_2(memt, memh, 0, 0, memsize >> 1);
    319 	else
    320 		bus_space_set_region_1(memt, memh, 0, 0, memsize);
    321 
    322 	if (wsc->sc_16bitp) {
    323 		for (i = 0; i < memsize; i += 2) {
    324 			if (bus_space_read_2(memt, memh, i) != 0)
    325 				goto fail;
    326 		}
    327 	} else {
    328 		for (i = 0; i < memsize; i++) {
    329 			if (bus_space_read_1(memt, memh, i) != 0)
    330 				goto fail;
    331 		}
    332 	}
    333 
    334 	return (0);
    335 
    336  fail:
    337 	printf("%s: failed to clear shared memory at offset 0x%x\n",
    338 	    sc->sc_dev.dv_xname, i);
    339 	WE_MEM_DISABLE(wsc);
    340 	return (1);
    341 }
    342 
    343 /*
    344  * Given a NIC memory source address and a host memory destination address,
    345  * copy 'len' from NIC to host using shared memory.  The 'len' is rounded
    346  * up to a word - ok as long as mbufs are word-sized.
    347  */
    348 static __inline void
    349 we_readmem(wsc, from, to, len)
    350 	struct we_softc *wsc;
    351 	int from;
    352 	u_int8_t *to;
    353 	int len;
    354 {
    355 	bus_space_tag_t memt = wsc->sc_dp8390.sc_buft;
    356 	bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh;
    357 
    358 	if (len & 1)
    359 		++len;
    360 
    361 	if (wsc->sc_16bitp)
    362 		bus_space_read_region_stream_2(memt, memh, from,
    363 		    (u_int16_t *)to, len >> 1);
    364 	else
    365 		bus_space_read_region_1(memt, memh, from,
    366 		    to, len);
    367 }
    368 
    369 static int
    370 we_write_mbuf(sc, m, buf)
    371 	struct dp8390_softc *sc;
    372 	struct mbuf *m;
    373 	int buf;
    374 {
    375 	struct we_softc *wsc = (struct we_softc *)sc;
    376 	bus_space_tag_t memt = wsc->sc_dp8390.sc_buft;
    377 	bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh;
    378 	u_int8_t *data, savebyte[2];
    379 	int savelen, len, leftover;
    380 #ifdef DIAGNOSTIC
    381 	u_int8_t *lim;
    382 #endif
    383 
    384 	savelen = m->m_pkthdr.len;
    385 
    386 	WE_MEM_ENABLE(wsc);
    387 
    388 	/*
    389 	 * 8-bit boards are simple; no alignment tricks are necessary.
    390 	 */
    391 	if (wsc->sc_16bitp == 0) {
    392 		for (; m != NULL; buf += m->m_len, m = m->m_next)
    393 			bus_space_write_region_1(memt, memh,
    394 			    buf, mtod(m, u_int8_t *), m->m_len);
    395 		goto out;
    396 	}
    397 
    398 	/* Start out with no leftover data. */
    399 	leftover = 0;
    400 	savebyte[0] = savebyte[1] = 0;
    401 
    402 	for (; m != NULL; m = m->m_next) {
    403 		len = m->m_len;
    404 		if (len == 0)
    405 			continue;
    406 		data = mtod(m, u_int8_t *);
    407 #ifdef DIAGNOSTIC
    408 		lim = data + len;
    409 #endif
    410 		while (len > 0) {
    411 			if (leftover) {
    412 				/*
    413 				 * Data left over (from mbuf or realignment).
    414 				 * Buffer the next byte, and write it and
    415 				 * the leftover data out.
    416 				 */
    417 				savebyte[1] = *data++;
    418 				len--;
    419 				bus_space_write_stream_2(memt, memh, buf,
    420 				    *(u_int16_t *)savebyte);
    421 				buf += 2;
    422 				leftover = 0;
    423 			} else if (BUS_SPACE_ALIGNED_POINTER(data, u_int16_t)
    424 				   == 0) {
    425 				/*
    426 				 * Unaligned dta; buffer the next byte.
    427 				 */
    428 				savebyte[0] = *data++;
    429 				len--;
    430 				leftover = 1;
    431 			} else {
    432 				/*
    433 				 * Aligned data; output contiguous words as
    434 				 * much as we can, then buffer the remaining
    435 				 * byte, if any.
    436 				 */
    437 				leftover = len & 1;
    438 				len &= ~1;
    439 				bus_space_write_region_stream_2(memt, memh,
    440 				    buf, (u_int16_t *)data, len >> 1);
    441 				data += len;
    442 				buf += len;
    443 				if (leftover)
    444 					savebyte[0] = *data++;
    445 				len = 0;
    446 			}
    447 		}
    448 		if (len < 0)
    449 			panic("we_write_mbuf: negative len");
    450 #ifdef DIAGNOSTIC
    451 		if (data != lim)
    452 			panic("we_write_mbuf: data != lim");
    453 #endif
    454 	}
    455 	if (leftover) {
    456 		savebyte[1] = 0;
    457 		bus_space_write_stream_2(memt, memh, buf,
    458 		    *(u_int16_t *)savebyte);
    459 	}
    460 
    461  out:
    462 	WE_MEM_DISABLE(wsc);
    463 
    464 	return (savelen);
    465 }
    466 
    467 static int
    468 we_ring_copy(sc, src, dst, amount)
    469 	struct dp8390_softc *sc;
    470 	int src;
    471 	caddr_t dst;
    472 	u_short amount;
    473 {
    474 	struct we_softc *wsc = (struct we_softc *)sc;
    475 	u_short tmp_amount;
    476 
    477 	/* Does copy wrap to lower addr in ring buffer? */
    478 	if (src + amount > sc->mem_end) {
    479 		tmp_amount = sc->mem_end - src;
    480 
    481 		/* Copy amount up to end of NIC memory. */
    482 		we_readmem(wsc, src, dst, tmp_amount);
    483 
    484 		amount -= tmp_amount;
    485 		src = sc->mem_ring;
    486 		dst += tmp_amount;
    487 	}
    488 
    489 	we_readmem(wsc, src, dst, amount);
    490 
    491 	return (src + amount);
    492 }
    493 
    494 static void
    495 we_read_hdr(sc, packet_ptr, packet_hdrp)
    496 	struct dp8390_softc *sc;
    497 	int packet_ptr;
    498 	struct dp8390_ring *packet_hdrp;
    499 {
    500 	struct we_softc *wsc = (struct we_softc *)sc;
    501 
    502 	we_readmem(wsc, packet_ptr, (u_int8_t *)packet_hdrp,
    503 	    sizeof(struct dp8390_ring));
    504 #if BYTE_ORDER == BIG_ENDIAN
    505 	packet_hdrp->count = bswap16(packet_hdrp->count);
    506 #endif
    507 }
    508 
    509 static void
    510 we_recv_int(sc)
    511 	struct dp8390_softc *sc;
    512 {
    513 	struct we_softc *wsc = (struct we_softc *)sc;
    514 
    515 	WE_MEM_ENABLE(wsc);
    516 	dp8390_rint(sc);
    517 	WE_MEM_DISABLE(wsc);
    518 }
    519 
    520 static void
    521 we_media_init(struct dp8390_softc *sc)
    522 {
    523 	struct we_softc *wsc = (void *) sc;
    524 	int defmedia = IFM_ETHER;
    525 	u_int8_t x;
    526 
    527 	if (sc->is790) {
    528 		x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR);
    529 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR,
    530 		    x | WE790_HWR_SWH);
    531 		if (bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE790_GCR) &
    532 		    WE790_GCR_GPOUT)
    533 			defmedia |= IFM_10_2;
    534 		else
    535 			defmedia |= IFM_10_5;
    536 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR,
    537 		    x & ~WE790_HWR_SWH);
    538 	} else {
    539 		x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_IRR);
    540 		if (x & WE_IRR_OUT2)
    541 			defmedia |= IFM_10_2;
    542 		else
    543 			defmedia |= IFM_10_5;
    544 	}
    545 
    546 	ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
    547 	ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_2, 0, NULL);
    548 	ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_5, 0, NULL);
    549 	ifmedia_set(&sc->sc_media, defmedia);
    550 }
    551 
    552 static int
    553 we_mediachange(sc)
    554 	struct dp8390_softc *sc;
    555 {
    556 
    557 	/*
    558 	 * Current media is already set up.  Just reset the interface
    559 	 * to let the new value take hold.  The new media will be
    560 	 * set up in we_init_card() called via dp8390_init().
    561 	 */
    562 	dp8390_reset(sc);
    563 	return (0);
    564 }
    565 
    566 static void
    567 we_mediastatus(sc, ifmr)
    568 	struct dp8390_softc *sc;
    569 	struct ifmediareq *ifmr;
    570 {
    571 	struct ifmedia *ifm = &sc->sc_media;
    572 
    573 	/*
    574 	 * The currently selected media is always the active media.
    575 	 */
    576 	ifmr->ifm_active = ifm->ifm_cur->ifm_media;
    577 }
    578 
    579 static void
    580 we_init_card(sc)
    581 	struct dp8390_softc *sc;
    582 {
    583 	struct we_softc *wsc = (struct we_softc *)sc;
    584 	struct ifmedia *ifm = &sc->sc_media;
    585 
    586 	if (wsc->sc_init_hook)
    587 		(*wsc->sc_init_hook)(wsc);
    588 
    589 	we_set_media(wsc, ifm->ifm_cur->ifm_media);
    590 }
    591 
    592 static void
    593 we_set_media(wsc, media)
    594 	struct we_softc *wsc;
    595 	int media;
    596 {
    597 	struct dp8390_softc *sc = &wsc->sc_dp8390;
    598 	bus_space_tag_t asict = wsc->sc_asict;
    599 	bus_space_handle_t asich = wsc->sc_asich;
    600 	u_int8_t hwr, gcr, irr;
    601 
    602 	if (sc->is790) {
    603 		hwr = bus_space_read_1(asict, asich, WE790_HWR);
    604 		bus_space_write_1(asict, asich, WE790_HWR,
    605 		    hwr | WE790_HWR_SWH);
    606 		gcr = bus_space_read_1(asict, asich, WE790_GCR);
    607 		if (IFM_SUBTYPE(media) == IFM_10_2)
    608 			gcr |= WE790_GCR_GPOUT;
    609 		else
    610 			gcr &= ~WE790_GCR_GPOUT;
    611 		bus_space_write_1(asict, asich, WE790_GCR,
    612 		    gcr | WE790_GCR_LIT);
    613 		bus_space_write_1(asict, asich, WE790_HWR,
    614 		    hwr & ~WE790_HWR_SWH);
    615 		return;
    616 	}
    617 
    618 	irr = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_IRR);
    619 	if (IFM_SUBTYPE(media) == IFM_10_2)
    620 		irr |= WE_IRR_OUT2;
    621 	else
    622 		irr &= ~WE_IRR_OUT2;
    623 	bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_IRR, irr);
    624 }
    625