xref: /netbsd-src/sys/dev/ic/we.c (revision 5e4c038a45edbc7d63b7c2daa76e29f88b64a4e3)
1 /*	$NetBSD: we.c,v 1.4 2001/11/13 13:14:46 lukem 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 <sys/cdefs.h>
59 __KERNEL_RCSID(0, "$NetBSD: we.c,v 1.4 2001/11/13 13:14:46 lukem Exp $");
60 
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/device.h>
64 #include <sys/socket.h>
65 #include <sys/mbuf.h>
66 #include <sys/syslog.h>
67 
68 #include <net/if.h>
69 #include <net/if_dl.h>
70 #include <net/if_types.h>
71 #include <net/if_media.h>
72 
73 #include <net/if_ether.h>
74 
75 #include <machine/bus.h>
76 #include <machine/bswap.h>
77 #include <machine/intr.h>
78 
79 #include <dev/isa/isareg.h>
80 #include <dev/isa/isavar.h>
81 
82 #include <dev/ic/dp8390reg.h>
83 #include <dev/ic/dp8390var.h>
84 #include <dev/ic/wereg.h>
85 #include <dev/ic/wevar.h>
86 
87 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
88 #define	bus_space_read_region_stream_2	bus_space_read_region_2
89 #define	bus_space_write_stream_2	bus_space_write_2
90 #define	bus_space_write_region_stream_2	bus_space_write_region_2
91 #endif
92 
93 static void	we_set_media __P((struct we_softc *, int));
94 
95 static void	we_media_init __P((struct dp8390_softc *));
96 
97 static int	we_mediachange __P((struct dp8390_softc *));
98 static void	we_mediastatus __P((struct dp8390_softc *, struct ifmediareq *));
99 
100 static void	we_recv_int __P((struct dp8390_softc *));
101 static void	we_init_card __P((struct dp8390_softc *));
102 static int	we_write_mbuf __P((struct dp8390_softc *, struct mbuf *, int));
103 static int	we_ring_copy __P((struct dp8390_softc *, int, caddr_t, u_short));
104 static void	we_read_hdr __P((struct dp8390_softc *, int, struct dp8390_ring *));
105 static int	we_test_mem __P((struct dp8390_softc *));
106 
107 static __inline void we_readmem __P((struct we_softc *, int, u_int8_t *, int));
108 
109 /*
110  * Delay needed when switching 16-bit access to shared memory.
111  */
112 #define	WE_DELAY(wsc) delay(3)
113 
114 /*
115  * Enable card RAM, and 16-bit access.
116  */
117 #define	WE_MEM_ENABLE(wsc) \
118 do { \
119 	if ((wsc)->sc_16bitp) \
120 		bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
121 		    WE_LAAR, (wsc)->sc_laar_proto | WE_LAAR_M16EN); \
122 	bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
123 	    WE_MSR, wsc->sc_msr_proto | WE_MSR_MENB); \
124 	WE_DELAY((wsc)); \
125 } while (0)
126 
127 /*
128  * Disable card RAM, and 16-bit access.
129  */
130 #define	WE_MEM_DISABLE(wsc) \
131 do { \
132 	bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
133 	    WE_MSR, (wsc)->sc_msr_proto); \
134 	if ((wsc)->sc_16bitp) \
135 		bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
136 		    WE_LAAR, (wsc)->sc_laar_proto); \
137 	WE_DELAY((wsc)); \
138 } while (0)
139 
140 int
141 we_config(self, wsc, typestr)
142 	struct device *self;
143 	struct we_softc *wsc;
144 	const char *typestr;
145 {
146 	struct dp8390_softc *sc = &wsc->sc_dp8390;
147 	u_int8_t x;
148 	int i, forced_16bit = 0;
149 
150 	/*
151 	 * Allow user to override 16-bit mode.  8-bit takes precedence.
152 	 */
153 	if (self->dv_cfdata->cf_flags & DP8390_FORCE_16BIT_MODE) {
154 		wsc->sc_16bitp = 1;
155 		forced_16bit = 1;
156 	}
157 	if (self->dv_cfdata->cf_flags & DP8390_FORCE_8BIT_MODE)
158 		wsc->sc_16bitp = 0;
159 
160 	/* Registers are linear. */
161 	for (i = 0; i < 16; i++)
162 		sc->sc_reg_map[i] = i;
163 
164 	/* Now we can use the NIC_{GET,PUT}() macros. */
165 
166 	printf("%s: %s Ethernet (%s-bit)\n", sc->sc_dev.dv_xname,
167 	    typestr, wsc->sc_16bitp ? "16" : "8");
168 
169 	/* Get station address from EEPROM. */
170 	for (i = 0; i < ETHER_ADDR_LEN; i++)
171 		sc->sc_enaddr[i] = bus_space_read_1(wsc->sc_asict,
172 					wsc->sc_asich, WE_PROM + i);
173 
174 	/*
175 	 * Set upper address bits and 8/16 bit access to shared memory.
176 	 */
177 	if (sc->is790) {
178 		wsc->sc_laar_proto =
179 		    bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_LAAR) &
180 		    ~WE_LAAR_M16EN;
181 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_LAAR,
182 		    wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0));
183 	} else if ((wsc->sc_type & WE_SOFTCONFIG) ||
184 #ifdef TOSH_ETHER
185 	    (wsc->sc_type == WE_TYPE_TOSHIBA1) ||
186 	    (wsc->sc_type == WE_TYPE_TOSHIBA4) ||
187 #endif
188 	    (forced_16bit) ||
189 	    (wsc->sc_type == WE_TYPE_WD8013EBT)) {
190 		wsc->sc_laar_proto = (wsc->sc_maddr >> 19) & WE_LAAR_ADDRHI;
191 		if (wsc->sc_16bitp)
192 			wsc->sc_laar_proto |= WE_LAAR_L16EN;
193 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_LAAR,
194 		    wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0));
195 	}
196 
197 	/*
198 	 * Set address and enable interface shared memory.
199 	 */
200 	if (sc->is790) {
201 		/* XXX MAGIC CONSTANTS XXX */
202 		x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, 0x04);
203 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, 0x04, x | 0x80);
204 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, 0x0b,
205 		    ((wsc->sc_maddr >> 13) & 0x0f) |
206 		    ((wsc->sc_maddr >> 11) & 0x40) |
207 		    (bus_space_read_1(wsc->sc_asict, wsc->sc_asich, 0x0b) & 0xb0));
208 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, 0x04, x);
209 		wsc->sc_msr_proto = 0x00;
210 		sc->cr_proto = 0x00;
211 	} else {
212 #ifdef TOSH_ETHER
213 		if (wsc->sc_type == WE_TYPE_TOSHIBA1 ||
214 		    wsc->sc_type == WE_TYPE_TOSHIBA4) {
215 			bus_space_write_1(wsc->sc_asict, wsc->sc_asich,
216 			    WE_MSR + 1,
217 			    ((wsc->sc_maddr >> 8) & 0xe0) | 0x04);
218 			bus_space_write_1(wsc->sc_asict, wsc->sc_asich,
219 			    WE_MSR + 2,
220 			    ((wsc->sc_maddr >> 16) & 0x0f));
221 			wsc->sc_msr_proto = WE_MSR_POW;
222 		} else
223 #endif
224 			wsc->sc_msr_proto = (wsc->sc_maddr >> 13) &
225 			    WE_MSR_ADDR;
226 
227 		sc->cr_proto = ED_CR_RD2;
228 	}
229 
230 	bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_MSR,
231 	    wsc->sc_msr_proto | WE_MSR_MENB);
232 	WE_DELAY(wsc);
233 
234 	/*
235 	 * DCR gets:
236 	 *
237 	 *	FIFO threshold to 8, No auto-init Remote DMA,
238 	 *	byte order=80x86.
239 	 *
240 	 * 16-bit cards also get word-wide DMA transfers.
241 	 */
242 	sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
243 	    (wsc->sc_16bitp ? ED_DCR_WTS : 0);
244 
245 	sc->test_mem = we_test_mem;
246 	sc->ring_copy = we_ring_copy;
247 	sc->write_mbuf = we_write_mbuf;
248 	sc->read_hdr = we_read_hdr;
249 	sc->recv_int = we_recv_int;
250 	sc->init_card = we_init_card;
251 
252 	sc->sc_mediachange = we_mediachange;
253 	sc->sc_mediastatus = we_mediastatus;
254 
255 	sc->mem_start = 0;
256 	/* sc->mem_size has to be set by frontend */
257 
258 	sc->sc_flags = self->dv_cfdata->cf_flags;
259 
260 	/* Do generic parts of attach. */
261 	if (wsc->sc_type & WE_SOFTCONFIG)
262 		sc->sc_media_init = we_media_init;
263 	else
264 		sc->sc_media_init = dp8390_media_init;
265 	if (dp8390_config(sc)) {
266 		printf("%s: configuration failed\n", sc->sc_dev.dv_xname);
267 		return (1);
268 	}
269 
270 	/*
271 	 * Disable 16-bit access to shared memory - we leave it disabled
272 	 * so that:
273 	 *
274 	 *	(1) machines reboot properly when the board is set to
275 	 *	    16-bit mode and there are conflicting 8-bit devices
276 	 *	    within the same 128k address space as this board's
277 	 *	    shared memory, and
278 	 *
279 	 *	(2) so that other 8-bit devices with shared memory
280 	 *	    in this same 128k address space will work.
281 	 */
282 	WE_MEM_DISABLE(wsc);
283 
284 	return (0);
285 }
286 
287 static int
288 we_test_mem(sc)
289 	struct dp8390_softc *sc;
290 {
291 	struct we_softc *wsc = (struct we_softc *)sc;
292 	bus_space_tag_t memt = sc->sc_buft;
293 	bus_space_handle_t memh = sc->sc_bufh;
294 	bus_size_t memsize = sc->mem_size;
295 	int i;
296 
297 	if (wsc->sc_16bitp)
298 		bus_space_set_region_2(memt, memh, 0, 0, memsize >> 1);
299 	else
300 		bus_space_set_region_1(memt, memh, 0, 0, memsize);
301 
302 	if (wsc->sc_16bitp) {
303 		for (i = 0; i < memsize; i += 2) {
304 			if (bus_space_read_2(memt, memh, i) != 0)
305 				goto fail;
306 		}
307 	} else {
308 		for (i = 0; i < memsize; i++) {
309 			if (bus_space_read_1(memt, memh, i) != 0)
310 				goto fail;
311 		}
312 	}
313 
314 	return (0);
315 
316  fail:
317 	printf("%s: failed to clear shared memory at offset 0x%x\n",
318 	    sc->sc_dev.dv_xname, i);
319 	WE_MEM_DISABLE(wsc);
320 	return (1);
321 }
322 
323 /*
324  * Given a NIC memory source address and a host memory destination address,
325  * copy 'len' from NIC to host using shared memory.  The 'len' is rounded
326  * up to a word - ok as long as mbufs are word-sized.
327  */
328 static __inline void
329 we_readmem(wsc, from, to, len)
330 	struct we_softc *wsc;
331 	int from;
332 	u_int8_t *to;
333 	int len;
334 {
335 	bus_space_tag_t memt = wsc->sc_dp8390.sc_buft;
336 	bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh;
337 
338 	if (len & 1)
339 		++len;
340 
341 	if (wsc->sc_16bitp)
342 		bus_space_read_region_stream_2(memt, memh, from,
343 		    (u_int16_t *)to, len >> 1);
344 	else
345 		bus_space_read_region_1(memt, memh, from,
346 		    to, len);
347 }
348 
349 static int
350 we_write_mbuf(sc, m, buf)
351 	struct dp8390_softc *sc;
352 	struct mbuf *m;
353 	int buf;
354 {
355 	struct we_softc *wsc = (struct we_softc *)sc;
356 	bus_space_tag_t memt = wsc->sc_dp8390.sc_buft;
357 	bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh;
358 	u_int8_t *data, savebyte[2];
359 	int savelen, len, leftover;
360 #ifdef DIAGNOSTIC
361 	u_int8_t *lim;
362 #endif
363 
364 	savelen = m->m_pkthdr.len;
365 
366 	WE_MEM_ENABLE(wsc);
367 
368 	/*
369 	 * 8-bit boards are simple; no alignment tricks are necessary.
370 	 */
371 	if (wsc->sc_16bitp == 0) {
372 		for (; m != NULL; buf += m->m_len, m = m->m_next)
373 			bus_space_write_region_1(memt, memh,
374 			    buf, mtod(m, u_int8_t *), m->m_len);
375 		goto out;
376 	}
377 
378 	/* Start out with no leftover data. */
379 	leftover = 0;
380 	savebyte[0] = savebyte[1] = 0;
381 
382 	for (; m != NULL; m = m->m_next) {
383 		len = m->m_len;
384 		if (len == 0)
385 			continue;
386 		data = mtod(m, u_int8_t *);
387 #ifdef DIAGNOSTIC
388 		lim = data + len;
389 #endif
390 		while (len > 0) {
391 			if (leftover) {
392 				/*
393 				 * Data left over (from mbuf or realignment).
394 				 * Buffer the next byte, and write it and
395 				 * the leftover data out.
396 				 */
397 				savebyte[1] = *data++;
398 				len--;
399 				bus_space_write_stream_2(memt, memh, buf,
400 				    *(u_int16_t *)savebyte);
401 				buf += 2;
402 				leftover = 0;
403 			} else if (BUS_SPACE_ALIGNED_POINTER(data, u_int16_t)
404 				   == 0) {
405 				/*
406 				 * Unaligned dta; buffer the next byte.
407 				 */
408 				savebyte[0] = *data++;
409 				len--;
410 				leftover = 1;
411 			} else {
412 				/*
413 				 * Aligned data; output contiguous words as
414 				 * much as we can, then buffer the remaining
415 				 * byte, if any.
416 				 */
417 				leftover = len & 1;
418 				len &= ~1;
419 				bus_space_write_region_stream_2(memt, memh,
420 				    buf, (u_int16_t *)data, len >> 1);
421 				data += len;
422 				buf += len;
423 				if (leftover)
424 					savebyte[0] = *data++;
425 				len = 0;
426 			}
427 		}
428 		if (len < 0)
429 			panic("we_write_mbuf: negative len");
430 #ifdef DIAGNOSTIC
431 		if (data != lim)
432 			panic("we_write_mbuf: data != lim");
433 #endif
434 	}
435 	if (leftover) {
436 		savebyte[1] = 0;
437 		bus_space_write_stream_2(memt, memh, buf,
438 		    *(u_int16_t *)savebyte);
439 	}
440 
441  out:
442 	WE_MEM_DISABLE(wsc);
443 
444 	return (savelen);
445 }
446 
447 static int
448 we_ring_copy(sc, src, dst, amount)
449 	struct dp8390_softc *sc;
450 	int src;
451 	caddr_t dst;
452 	u_short amount;
453 {
454 	struct we_softc *wsc = (struct we_softc *)sc;
455 	u_short tmp_amount;
456 
457 	/* Does copy wrap to lower addr in ring buffer? */
458 	if (src + amount > sc->mem_end) {
459 		tmp_amount = sc->mem_end - src;
460 
461 		/* Copy amount up to end of NIC memory. */
462 		we_readmem(wsc, src, dst, tmp_amount);
463 
464 		amount -= tmp_amount;
465 		src = sc->mem_ring;
466 		dst += tmp_amount;
467 	}
468 
469 	we_readmem(wsc, src, dst, amount);
470 
471 	return (src + amount);
472 }
473 
474 static void
475 we_read_hdr(sc, packet_ptr, packet_hdrp)
476 	struct dp8390_softc *sc;
477 	int packet_ptr;
478 	struct dp8390_ring *packet_hdrp;
479 {
480 	struct we_softc *wsc = (struct we_softc *)sc;
481 
482 	we_readmem(wsc, packet_ptr, (u_int8_t *)packet_hdrp,
483 	    sizeof(struct dp8390_ring));
484 #if BYTE_ORDER == BIG_ENDIAN
485 	packet_hdrp->count = bswap16(packet_hdrp->count);
486 #endif
487 }
488 
489 static void
490 we_recv_int(sc)
491 	struct dp8390_softc *sc;
492 {
493 	struct we_softc *wsc = (struct we_softc *)sc;
494 
495 	WE_MEM_ENABLE(wsc);
496 	dp8390_rint(sc);
497 	WE_MEM_DISABLE(wsc);
498 }
499 
500 static void
501 we_media_init(struct dp8390_softc *sc)
502 {
503 	struct we_softc *wsc = (void *) sc;
504 	int defmedia = IFM_ETHER;
505 	u_int8_t x;
506 
507 	if (sc->is790) {
508 		x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR);
509 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR,
510 		    x | WE790_HWR_SWH);
511 		if (bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE790_GCR) &
512 		    WE790_GCR_GPOUT)
513 			defmedia |= IFM_10_2;
514 		else
515 			defmedia |= IFM_10_5;
516 		bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR,
517 		    x & ~WE790_HWR_SWH);
518 	} else {
519 		x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_IRR);
520 		if (x & WE_IRR_OUT2)
521 			defmedia |= IFM_10_2;
522 		else
523 			defmedia |= IFM_10_5;
524 	}
525 
526 	ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
527 	ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_2, 0, NULL);
528 	ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_5, 0, NULL);
529 	ifmedia_set(&sc->sc_media, defmedia);
530 }
531 
532 static int
533 we_mediachange(sc)
534 	struct dp8390_softc *sc;
535 {
536 
537 	/*
538 	 * Current media is already set up.  Just reset the interface
539 	 * to let the new value take hold.  The new media will be
540 	 * set up in we_init_card() called via dp8390_init().
541 	 */
542 	dp8390_reset(sc);
543 	return (0);
544 }
545 
546 static void
547 we_mediastatus(sc, ifmr)
548 	struct dp8390_softc *sc;
549 	struct ifmediareq *ifmr;
550 {
551 	struct ifmedia *ifm = &sc->sc_media;
552 
553 	/*
554 	 * The currently selected media is always the active media.
555 	 */
556 	ifmr->ifm_active = ifm->ifm_cur->ifm_media;
557 }
558 
559 static void
560 we_init_card(sc)
561 	struct dp8390_softc *sc;
562 {
563 	struct we_softc *wsc = (struct we_softc *)sc;
564 	struct ifmedia *ifm = &sc->sc_media;
565 
566 	if (wsc->sc_init_hook)
567 		(*wsc->sc_init_hook)(wsc);
568 
569 	we_set_media(wsc, ifm->ifm_cur->ifm_media);
570 }
571 
572 static void
573 we_set_media(wsc, media)
574 	struct we_softc *wsc;
575 	int media;
576 {
577 	struct dp8390_softc *sc = &wsc->sc_dp8390;
578 	bus_space_tag_t asict = wsc->sc_asict;
579 	bus_space_handle_t asich = wsc->sc_asich;
580 	u_int8_t hwr, gcr, irr;
581 
582 	if (sc->is790) {
583 		hwr = bus_space_read_1(asict, asich, WE790_HWR);
584 		bus_space_write_1(asict, asich, WE790_HWR,
585 		    hwr | WE790_HWR_SWH);
586 		gcr = bus_space_read_1(asict, asich, WE790_GCR);
587 		if (IFM_SUBTYPE(media) == IFM_10_2)
588 			gcr |= WE790_GCR_GPOUT;
589 		else
590 			gcr &= ~WE790_GCR_GPOUT;
591 		bus_space_write_1(asict, asich, WE790_GCR,
592 		    gcr | WE790_GCR_LIT);
593 		bus_space_write_1(asict, asich, WE790_HWR,
594 		    hwr & ~WE790_HWR_SWH);
595 		return;
596 	}
597 
598 	irr = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_IRR);
599 	if (IFM_SUBTYPE(media) == IFM_10_2)
600 		irr |= WE_IRR_OUT2;
601 	else
602 		irr &= ~WE_IRR_OUT2;
603 	bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_IRR, irr);
604 }
605