xref: /openbsd-src/sys/dev/pci/if_dc_pci.c (revision 0f9891f1fafd8f53a63c41edb56ce51e2589b910)
1 /*	$OpenBSD: if_dc_pci.c,v 1.79 2024/05/24 06:02:53 jsg Exp $	*/
2 
3 /*
4  * Copyright (c) 1997, 1998, 1999
5  *	Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Bill Paul.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $FreeBSD: src/sys/pci/if_dc.c,v 1.5 2000/01/12 22:24:05 wpaul Exp $
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/timeout.h>
40 #include <sys/malloc.h>
41 #include <sys/device.h>
42 
43 #include <net/if.h>
44 
45 #include <netinet/in.h>
46 #include <netinet/if_ether.h>
47 
48 #include <net/if_media.h>
49 
50 #include <dev/mii/miivar.h>
51 
52 #include <dev/pci/pcireg.h>
53 #include <dev/pci/pcivar.h>
54 #include <dev/pci/pcidevs.h>
55 
56 #ifdef __sparc64__
57 #include <dev/ofw/openfirm.h>
58 #endif
59 
60 #ifndef __hppa__
61 #define DC_USEIOSPACE
62 #endif
63 
64 #include <dev/ic/dcreg.h>
65 
66 /*
67  * Various supported device vendors/types and their names.
68  */
69 struct dc_type dc_devs[] = {
70 	{ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21140 },
71 	{ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 },
72 	{ PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9009 },
73 	{ PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9100 },
74 	{ PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102 },
75 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM9511 },
76 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM9513 },
77 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981 },
78 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983 },
79 	{ PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A },
80 	{ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713 },
81 	{ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98715 },
82 	{ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98727 },
83 	{ PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_98713 },
84 	{ PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNIC },
85 	{ PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNICII },
86 	{ PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN1217 },
87 	{ PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242 },
88 	{ PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_RS7112 },
89 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_21145 },
90 	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CSHO100BTX },
91 	{ PCI_VENDOR_MICROSOFT, PCI_PRODUCT_MICROSOFT_MN130 },
92 	{ PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143 },
93 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN985 },
94 	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500 },
95 	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500MX },
96 	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_PCM200 },
97 	{ PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DRP32TXD },
98 	{ PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCMPC200 },
99 	{ PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCM200 },
100 	{ PCI_VENDOR_HAWKING, PCI_PRODUCT_HAWKING_PN672TX },
101 	{ PCI_VENDOR_MICROSOFT, PCI_PRODUCT_MICROSOFT_MN120 },
102 	{ 0, 0 }
103 };
104 
105 int dc_pci_match(struct device *, void *, void *);
106 void dc_pci_attach(struct device *, struct device *, void *);
107 int dc_pci_detach(struct device *, int);
108 
109 struct dc_pci_softc {
110 	struct dc_softc		psc_softc;
111 	pci_chipset_tag_t	psc_pc;
112 	bus_size_t		psc_mapsize;
113 };
114 
115 /*
116  * Probe for a 21143 or clone chip. Check the PCI vendor and device
117  * IDs against our list and return a device name if we find a match.
118  */
119 int
dc_pci_match(struct device * parent,void * match,void * aux)120 dc_pci_match(struct device *parent, void *match, void *aux)
121 {
122 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
123 	struct dc_type *t;
124 
125 	/*
126 	 * Support for the 21140 chip is experimental.  If it works for you,
127 	 * that's great.  By default, this chip will use de.
128 	 */
129         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DEC &&
130 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21140)
131 		return (1);
132 
133 	/*
134 	 * The following chip revision doesn't seem to work so well with dc,
135 	 * so let's have de handle it.  (de will return a match of 2)
136 	 */
137         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DEC &&
138 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142 &&
139 	    PCI_REVISION(pa->pa_class) == 0x21)
140 		return (1);
141 
142 	for (t = dc_devs; t->dc_vid != 0; t++) {
143 		if ((PCI_VENDOR(pa->pa_id) == t->dc_vid) &&
144 		    (PCI_PRODUCT(pa->pa_id) == t->dc_did)) {
145 			return (3);
146 		}
147 	}
148 
149 	return (0);
150 }
151 
152 /*
153  * Attach the interface. Allocate softc structures, do ifmedia
154  * setup and ethernet/BPF attach.
155  */
156 void
dc_pci_attach(struct device * parent,struct device * self,void * aux)157 dc_pci_attach(struct device *parent, struct device *self, void *aux)
158 {
159 	const char		*intrstr = NULL;
160 	pcireg_t		command;
161 	struct dc_pci_softc	*psc = (struct dc_pci_softc *)self;
162 	struct dc_softc		*sc = &psc->psc_softc;
163 	struct pci_attach_args	*pa = aux;
164 	pci_chipset_tag_t	pc = pa->pa_pc;
165 	pci_intr_handle_t	ih;
166 	int			found = 0;
167 
168 	psc->psc_pc = pa->pa_pc;
169 	sc->sc_dmat = pa->pa_dmat;
170 
171 	pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
172 
173 	sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
174 
175 	/*
176 	 * Map control/status registers.
177 	 */
178 #ifdef DC_USEIOSPACE
179 	if (pci_mapreg_map(pa, DC_PCI_CFBIO,
180 	    PCI_MAPREG_TYPE_IO, 0,
181 	    &sc->dc_btag, &sc->dc_bhandle, NULL, &psc->psc_mapsize, 0)) {
182 		printf(": can't map i/o space\n");
183 		return;
184 	}
185 #else
186 	if (pci_mapreg_map(pa, DC_PCI_CFBMA,
187 	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
188 	    &sc->dc_btag, &sc->dc_bhandle, NULL, &psc->psc_mapsize, 0)) {
189 		printf(": can't map mem space\n");
190 		return;
191 	}
192 #endif
193 
194 	/* Allocate interrupt */
195 	if (pci_intr_map(pa, &ih)) {
196 		printf(": couldn't map interrupt\n");
197 		goto fail_1;
198 	}
199 	intrstr = pci_intr_string(pc, ih);
200 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc,
201 	    self->dv_xname);
202 	if (sc->sc_ih == NULL) {
203 		printf(": couldn't establish interrupt");
204 		if (intrstr != NULL)
205 			printf(" at %s", intrstr);
206 		printf("\n");
207 		goto fail_1;
208 	}
209 	printf(": %s", intrstr);
210 
211 	/* Need this info to decide on a chip type. */
212 	sc->dc_revision = PCI_REVISION(pa->pa_class);
213 
214 	/* Get the eeprom width, if possible */
215 	if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LITEON &&
216 	      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC))
217 		;	/* PNIC has non-standard eeprom */
218 	else if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_XIRCOM &&
219 	      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143))
220 		;	/* XIRCOM has non-standard eeprom */
221 	else
222 		dc_eeprom_width(sc);
223 
224 	switch (PCI_VENDOR(pa->pa_id)) {
225 	case PCI_VENDOR_DEC:
226 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21140 ||
227 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) {
228 			found = 1;
229 			sc->dc_type = DC_TYPE_21143;
230 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
231 			sc->dc_flags |= DC_REDUCED_MII_POLL;
232 			dc_read_srom(sc, sc->dc_romwidth);
233 		}
234 		break;
235 	case PCI_VENDOR_INTEL:
236 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_21145) {
237 			found = 1;
238 			sc->dc_type = DC_TYPE_21145;
239 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
240 			sc->dc_flags |= DC_REDUCED_MII_POLL;
241 			dc_read_srom(sc, sc->dc_romwidth);
242 		}
243 		break;
244 	case PCI_VENDOR_DAVICOM:
245 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 ||
246 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102 ||
247 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9009) {
248 			found = 1;
249 			sc->dc_type = DC_TYPE_DM9102;
250 			sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS;
251 			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD;
252 			sc->dc_flags |= DC_TX_ALIGN;
253 			sc->dc_pmode = DC_PMODE_MII;
254 
255 			/* Increase the latency timer value. */
256 			command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFLT);
257 			command &= 0xFFFF00FF;
258 			command |= 0x00008000;
259 			pci_conf_write(pc, pa->pa_tag, DC_PCI_CFLT, command);
260 		}
261 		break;
262 	case PCI_VENDOR_ADMTEK:
263 	case PCI_VENDOR_3COM:
264 	case PCI_VENDOR_MICROSOFT:
265 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) {
266 			found = 1;
267 			sc->dc_type = DC_TYPE_AL981;
268 			sc->dc_flags |= DC_TX_USE_TX_INTR;
269 			sc->dc_flags |= DC_TX_ADMTEK_WAR;
270 			sc->dc_pmode = DC_PMODE_MII;
271 			dc_read_srom(sc, sc->dc_romwidth);
272 		}
273 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_ADM9511 ||
274 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_ADM9513 ||
275 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983 ||
276 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3COM_3CSHO100BTX ||
277 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MICROSOFT_MN130) {
278 			found = 1;
279 			sc->dc_type = DC_TYPE_AN983;
280 			sc->dc_flags |= DC_TX_USE_TX_INTR;
281 			sc->dc_flags |= DC_TX_ADMTEK_WAR;
282 			sc->dc_flags |= DC_64BIT_HASH;
283 			sc->dc_pmode = DC_PMODE_MII;
284 			/* Don't read SROM for - auto-loaded on reset */
285 		}
286 		break;
287 	case PCI_VENDOR_MACRONIX:
288 	case PCI_VENDOR_ACCTON:
289 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN2242) {
290 			found = 1;
291 			sc->dc_type = DC_TYPE_AN983;
292 			sc->dc_flags |= DC_TX_USE_TX_INTR;
293 			sc->dc_flags |= DC_TX_ADMTEK_WAR;
294 			sc->dc_flags |= DC_64BIT_HASH;
295 			sc->dc_pmode = DC_PMODE_MII;
296 			/* Don't read SROM for - auto-loaded on reset */
297 		}
298 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) {
299 			found = 1;
300 			if (sc->dc_revision < DC_REVISION_98713A)
301 				sc->dc_type = DC_TYPE_98713;
302 			if (sc->dc_revision >= DC_REVISION_98713A) {
303 				sc->dc_type = DC_TYPE_98713A;
304 				sc->dc_flags |= DC_21143_NWAY;
305 			}
306 			sc->dc_flags |= DC_REDUCED_MII_POLL;
307 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
308 		}
309 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 ||
310 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) {
311 			found = 1;
312 			if (sc->dc_revision >= DC_REVISION_98715AEC_C &&
313 			    sc->dc_revision < DC_REVISION_98725)
314 				sc->dc_flags |= DC_128BIT_HASH;
315 			sc->dc_type = DC_TYPE_987x5;
316 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
317 			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
318 		}
319 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98727) {
320 			found = 1;
321 			sc->dc_type = DC_TYPE_987x5;
322 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
323 			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
324 		}
325 		break;
326 	case PCI_VENDOR_COMPEX:
327 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) {
328 			found = 1;
329 			if (sc->dc_revision < DC_REVISION_98713A) {
330 				sc->dc_type = DC_TYPE_98713;
331 				sc->dc_flags |= DC_REDUCED_MII_POLL;
332 			}
333 			if (sc->dc_revision >= DC_REVISION_98713A)
334 				sc->dc_type = DC_TYPE_98713A;
335 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
336 		}
337 		break;
338 	case PCI_VENDOR_LITEON:
339 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) {
340 			found = 1;
341 			sc->dc_type = DC_TYPE_PNICII;
342 			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
343 			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
344 			sc->dc_flags |= DC_128BIT_HASH;
345 		}
346 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) {
347 			found = 1;
348 			sc->dc_type = DC_TYPE_PNIC;
349 			sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS;
350 			sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
351 			sc->dc_pnic_rx_buf = malloc(ETHER_MAX_DIX_LEN * 5,
352 			    M_DEVBUF, M_NOWAIT);
353 			if (sc->dc_pnic_rx_buf == NULL)
354 				panic("dc_pci_attach");
355 			if (sc->dc_revision < DC_REVISION_82C169)
356 				sc->dc_pmode = DC_PMODE_SYM;
357 		}
358 		break;
359 	case PCI_VENDOR_ASIX:
360 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) {
361 			found = 1;
362 			sc->dc_type = DC_TYPE_ASIX;
363 			sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG;
364 			sc->dc_flags |= DC_REDUCED_MII_POLL;
365 			sc->dc_pmode = DC_PMODE_MII;
366 		}
367 		break;
368 	case PCI_VENDOR_CONEXANT:
369 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONEXANT_RS7112) {
370 			found = 1;
371 			sc->dc_type = DC_TYPE_CONEXANT;
372 			sc->dc_flags |= DC_TX_INTR_ALWAYS;
373 			sc->dc_flags |= DC_REDUCED_MII_POLL;
374 			sc->dc_pmode = DC_PMODE_MII;
375 			dc_read_srom(sc, sc->dc_romwidth);
376 		}
377 		break;
378 	case PCI_VENDOR_XIRCOM:
379 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143) {
380 			found = 1;
381 			sc->dc_type = DC_TYPE_XIRCOM;
382 			sc->dc_flags |= DC_TX_INTR_ALWAYS;
383 			sc->dc_flags |= DC_TX_COALESCE;
384 			sc->dc_flags |= DC_TX_ALIGN;
385 			sc->dc_pmode = DC_PMODE_MII;
386 		}
387 		break;
388 	}
389 	if (found == 0) {
390 		/* This shouldn't happen if probe has done its job... */
391 		printf(": unknown device: %x:%x\n",
392 		    PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id));
393 		goto fail_2;
394 	}
395 
396 	/* Save the cache line size. */
397 	if (DC_IS_DAVICOM(sc))
398 		sc->dc_cachesize = 0;
399 	else
400 		sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag,
401 		    DC_PCI_CFLT) & 0xFF;
402 
403 	/* Reset the adapter. */
404 	dc_reset(sc);
405 
406 	/* Take 21143 out of snooze mode */
407 	if (DC_IS_INTEL(sc) || DC_IS_XIRCOM(sc)) {
408 		command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD);
409 		command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE);
410 		pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command);
411 	}
412 
413 	/*
414 	 * If we discover later (in dc_attach) that we have an
415 	 * MII with no PHY, we need to have the 21143 drive the LEDs.
416 	 * Except there are some systems like the NEC VersaPro NoteBook PC
417 	 * which have no LEDs, and twiddling these bits has adverse effects
418 	 * on them. (I.e. you suddenly can't get a link.)
419 	 *
420 	 * If mii_attach() returns an error, we leave the DC_TULIP_LEDS
421 	 * bit set, else we clear it. Since our dc(4) driver is split into
422 	 * bus-dependent and bus-independent parts, we must do set this bit
423 	 * here while we are able to do PCI configuration reads.
424 	 */
425 	if (DC_IS_INTEL(sc)) {
426 		if (pci_conf_read(pc, pa->pa_tag, DC_PCI_CSID) != 0x80281033)
427 			sc->dc_flags |= DC_TULIP_LEDS;
428 	}
429 
430 	/*
431 	 * Try to learn something about the supported media.
432 	 * We know that ASIX and ADMtek and Davicom devices
433 	 * will *always* be using MII media, so that's a no-brainer.
434 	 * The tricky ones are the Macronix/PNIC II and the
435 	 * Intel 21143.
436 	 */
437 	if (DC_IS_INTEL(sc))
438 		dc_parse_21143_srom(sc);
439 	else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
440 		if (sc->dc_type == DC_TYPE_98713)
441 			sc->dc_pmode = DC_PMODE_MII;
442 		else
443 			sc->dc_pmode = DC_PMODE_SYM;
444 	} else if (!sc->dc_pmode)
445 		sc->dc_pmode = DC_PMODE_MII;
446 
447 #ifdef __sparc64__
448 	{
449 		extern void myetheraddr(u_char *);
450 
451 		if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address",
452 		    sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0)
453 			myetheraddr(sc->sc_arpcom.ac_enaddr);
454 		if (sc->sc_arpcom.ac_enaddr[0] == 0x00 &&
455 		    sc->sc_arpcom.ac_enaddr[1] == 0x03 &&
456 		    sc->sc_arpcom.ac_enaddr[2] == 0xcc)
457 			sc->dc_flags |= DC_MOMENCO_BOTCH;
458 		sc->sc_hasmac = 1;
459 	}
460 #endif
461 
462 #ifdef SRM_MEDIA
463 	sc->dc_srm_media = 0;
464 
465 	/* Remember the SRM console media setting */
466 	if (DC_IS_INTEL(sc)) {
467 		command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD);
468 		command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE);
469 		switch ((command >> 8) & 0xff) {
470 		case 3:
471 			sc->dc_srm_media = IFM_10_T;
472 			break;
473 		case 4:
474 			sc->dc_srm_media = IFM_10_T | IFM_FDX;
475 			break;
476 		case 5:
477 			sc->dc_srm_media = IFM_100_TX;
478 			break;
479 		case 6:
480 			sc->dc_srm_media = IFM_100_TX | IFM_FDX;
481 			break;
482 		}
483 		if (sc->dc_srm_media)
484 			sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER;
485 	}
486 #endif
487 	dc_attach(sc);
488 
489 	return;
490 
491 fail_2:
492 	pci_intr_disestablish(pc, sc->sc_ih);
493 
494 fail_1:
495 	bus_space_unmap(sc->dc_btag, sc->dc_bhandle, psc->psc_mapsize);
496 }
497 
498 int
dc_pci_detach(struct device * self,int flags)499 dc_pci_detach(struct device *self, int flags)
500 {
501 	struct dc_pci_softc *psc = (void *)self;
502 	struct dc_softc *sc = &psc->psc_softc;
503 
504 	if (sc->sc_ih != NULL)
505 		pci_intr_disestablish(psc->psc_pc, sc->sc_ih);
506 	dc_detach(sc);
507 	bus_space_unmap(sc->dc_btag, sc->dc_bhandle, psc->psc_mapsize);
508 
509 	return (0);
510 }
511 
512 const struct cfattach dc_pci_ca = {
513 	sizeof(struct dc_softc), dc_pci_match, dc_pci_attach, dc_pci_detach,
514 	dc_activate
515 };
516