if_dc_pci.c revision 1.5
1/*	$OpenBSD: if_dc_pci.c,v 1.5 2000/08/02 19:01:07 aaron 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 "bpfilter.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/mbuf.h>
42#include <sys/protosw.h>
43#include <sys/socket.h>
44#include <sys/ioctl.h>
45#include <sys/errno.h>
46#include <sys/malloc.h>
47#include <sys/kernel.h>
48#include <sys/device.h>
49
50#include <net/if.h>
51#include <net/if_dl.h>
52#include <net/if_types.h>
53
54#ifdef INET
55#include <netinet/in.h>
56#include <netinet/in_systm.h>
57#include <netinet/in_var.h>
58#include <netinet/ip.h>
59#include <netinet/if_ether.h>
60#endif
61
62#include <net/if_media.h>
63
64#if NBPFILTER > 0
65#include <net/bpf.h>
66#endif
67
68#include <vm/vm.h>              /* for vtophys */
69#include <vm/pmap.h>            /* for vtophys */
70
71#include <dev/mii/mii.h>
72#include <dev/mii/miivar.h>
73
74#include <dev/pci/pcireg.h>
75#include <dev/pci/pcivar.h>
76#include <dev/pci/pcidevs.h>
77
78#define DC_USEIOSPACE
79
80#include <dev/ic/dcreg.h>
81
82/*
83 * Various supported device vendors/types and their names.
84 */
85struct dc_type dc_devs[] = {
86	{ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 },
87	{ PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9100 },
88	{ PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102 },
89	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981 },
90	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983 },
91	{ PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A },
92	{ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713 },
93	{ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98715 },
94	{ PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_98713 },
95	{ PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNIC },
96	{ PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNICII },
97	{ PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN1217 },
98	{ 0, 0 }
99};
100
101int dc_pci_probe	__P((struct device *, void *, void *));
102void dc_pci_attach	__P((struct device *, struct device *, void *));
103void dc_pci_acpi	__P((struct device *, void *));
104
105/*
106 * Probe for a 21143 or clone chip. Check the PCI vendor and device
107 * IDs against our list and return a device name if we find a match.
108 */
109int
110dc_pci_probe(parent, match, aux)
111	struct device *parent;
112	void *match, *aux;
113{
114	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
115	struct dc_type *t;
116
117	for (t = dc_devs; t->dc_vid != 0; t++) {
118		if ((PCI_VENDOR(pa->pa_id) == t->dc_vid) &&
119		    (PCI_PRODUCT(pa->pa_id) == t->dc_did))
120			return (1);
121	}
122	return (0);
123}
124
125void dc_pci_acpi(self, aux)
126	struct device *self;
127	void *aux;
128{
129	struct dc_softc		*sc = (struct dc_softc *)self;
130	struct pci_attach_args	*pa = (struct pci_attach_args *)aux;
131	pci_chipset_tag_t	pc = pa->pa_pc;
132	u_int32_t		r, cptr;
133	int			unit;
134
135	unit = sc->dc_unit;
136
137	/* Find the location of the capabilities block */
138	cptr = pci_conf_read(pc, pa->pa_tag, DC_PCI_CCAP) & 0xFF;
139
140	r = pci_conf_read(pc, pa->pa_tag, cptr) & 0xFF;
141	if (r == 0x01) {
142
143		r = pci_conf_read(pc, pa->pa_tag, cptr + 4);
144		if (r & DC_PSTATE_D3) {
145			u_int32_t		iobase, membase, irq;
146
147			/* Save important PCI config data. */
148			iobase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBIO);
149			membase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBMA);
150			irq = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFIT);
151
152			/* Reset the power state. */
153			printf("dc%d: chip is in D%d power mode "
154			    "-- setting to D0\n", unit, r & DC_PSTATE_D3);
155			r &= 0xFFFFFFFC;
156			pci_conf_write(pc, pa->pa_tag, cptr + 4, r);
157
158			/* Restore PCI config data. */
159			pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBIO, iobase);
160			pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBMA, membase);
161			pci_conf_write(pc, pa->pa_tag, DC_PCI_CFIT, irq);
162		}
163	}
164	return;
165}
166
167/*
168 * Attach the interface. Allocate softc structures, do ifmedia
169 * setup and ethernet/BPF attach.
170 */
171void dc_pci_attach(parent, self, aux)
172	struct device *parent, *self;
173	void *aux;
174{
175	int			s;
176	const char		*intrstr = NULL;
177	u_int32_t		command;
178	struct dc_softc		*sc = (struct dc_softc *)self;
179	struct pci_attach_args	*pa = aux;
180	pci_chipset_tag_t	pc = pa->pa_pc;
181	pci_intr_handle_t	ih;
182	bus_addr_t		iobase;
183	bus_size_t		iosize;
184	u_int32_t		revision;
185	int			found = 0;
186
187	s = splimp();
188	sc->dc_unit = sc->sc_dev.dv_unit;
189
190	/*
191	 * Handle power management nonsense.
192	 */
193	dc_pci_acpi(self, aux);
194
195	/*
196	 * Map control/status registers.
197	 */
198	command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
199	command |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
200	    PCI_COMMAND_MASTER_ENABLE;
201	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
202	command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
203
204	sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
205
206#ifdef DC_USEIOSPACE
207	if (!(command & PCI_COMMAND_IO_ENABLE)) {
208		printf(": failed to enable I/O ports\n");
209		goto fail;
210	}
211	if (pci_io_find(pc, pa->pa_tag, DC_PCI_CFBIO, &iobase, &iosize)) {
212		printf(": can't find I/O space\n");
213		goto fail;
214	}
215	if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &sc->dc_bhandle)) {
216		printf(": can't map I/O space\n");
217		goto fail;
218	}
219	sc->dc_btag = pa->pa_iot;
220#else
221	if (!(command & PCI_COMMAND_MEM_ENABLE)) {
222		printf(": failed to enable memory mapping\n");
223		goto fail;
224	}
225	if (pci_mem_find(pc, pa->pa_tag, DC_PCI_CFBMA, &iobase, &iosize, NULL)){
226		printf(": can't find mem space\n");
227		goto fail;
228	}
229	if (bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->dc_bhandle)) {
230		printf(": can't map mem space\n");
231		goto fail;
232	}
233	sc->dc_btag = pa->pa_memt;
234#endif
235
236	/* Allocate interrupt */
237	if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline,
238	    &ih)) {
239		printf(": couldn't map interrupt\n");
240		goto fail;
241	}
242	intrstr = pci_intr_string(pc, ih);
243	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc,
244	    self->dv_xname);
245	if (sc->sc_ih == NULL) {
246		printf(": couldn't establish interrupt");
247		if (intrstr != NULL)
248			printf(" at %s", intrstr);
249		printf("\n");
250		goto fail;
251	}
252	printf(": %s", intrstr);
253
254	/* Need this info to decide on a chip type. */
255	sc->dc_revision = revision = PCI_REVISION(pa->pa_class);
256
257	switch (PCI_VENDOR(pa->pa_id)) {
258	case PCI_VENDOR_DEC:
259		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) {
260			found = 1;
261			sc->dc_type = DC_TYPE_21143;
262			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
263			sc->dc_flags |= DC_REDUCED_MII_POLL;
264		}
265		break;
266	case PCI_VENDOR_DAVICOM:
267		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 ||
268		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102) {
269			found = 1;
270			sc->dc_type = DC_TYPE_DM9102;
271			sc->dc_flags |= DC_TX_COALESCE|DC_TX_USE_TX_INTR;
272			sc->dc_flags |= DC_REDUCED_MII_POLL;
273			sc->dc_pmode = DC_PMODE_MII;
274		}
275		break;
276	case PCI_VENDOR_ADMTEK:
277		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) {
278			found = 1;
279			sc->dc_type = DC_TYPE_AL981;
280			sc->dc_flags |= DC_TX_USE_TX_INTR;
281			sc->dc_flags |= DC_TX_ADMTEK_WAR;
282			sc->dc_pmode = DC_PMODE_MII;
283		}
284		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983) {
285			found = 1;
286			sc->dc_type = DC_TYPE_AN983;
287			sc->dc_flags |= DC_TX_USE_TX_INTR;
288			sc->dc_flags |= DC_TX_ADMTEK_WAR;
289			sc->dc_pmode = DC_PMODE_MII;
290		}
291		break;
292	case PCI_VENDOR_MACRONIX:
293	case PCI_VENDOR_ACCTON:
294		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) {
295			found = 1;
296			if (revision < DC_REVISION_98713A) {
297				sc->dc_type = DC_TYPE_98713;
298			}
299			if (revision >= DC_REVISION_98713A) {
300				sc->dc_type = DC_TYPE_98713A;
301				sc->dc_flags |= DC_21143_NWAY;
302			}
303			sc->dc_flags |= DC_REDUCED_MII_POLL;
304			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
305		}
306		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 ||
307		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) {
308			found = 1;
309			if (revision >= DC_REVISION_98715AEC_C &&
310			    revision < DC_REVISION_98725)
311				sc->dc_flags |= DC_128BIT_HASH;
312			sc->dc_type = DC_TYPE_987x5;
313			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
314			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
315		}
316		break;
317	case PCI_VENDOR_COMPEX:
318		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) {
319			found = 1;
320			if (revision < DC_REVISION_98713A) {
321				sc->dc_type = DC_TYPE_98713;
322				sc->dc_flags |= DC_REDUCED_MII_POLL;
323			}
324			if (revision >= DC_REVISION_98713A)
325				sc->dc_type = DC_TYPE_98713A;
326			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
327		}
328		break;
329	case PCI_VENDOR_LITEON:
330		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) {
331			found = 1;
332			sc->dc_type = DC_TYPE_PNICII;
333			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
334			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
335			sc->dc_flags |= DC_128BIT_HASH;
336		}
337		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) {
338			found = 1;
339			sc->dc_type = DC_TYPE_PNIC;
340			sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS;
341			sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
342			sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF,
343			    M_NOWAIT);
344			if (revision < DC_REVISION_82C169)
345				sc->dc_pmode = DC_PMODE_SYM;
346		}
347		break;
348	case PCI_VENDOR_ASIX:
349		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) {
350			found = 1;
351			sc->dc_type = DC_TYPE_ASIX;
352			sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG;
353			sc->dc_flags |= DC_REDUCED_MII_POLL;
354			sc->dc_pmode = DC_PMODE_MII;
355		}
356		break;
357	}
358	if (found == 0) {
359		/* This shouldn't happen if probe has done it's job... */
360		printf(": unknown device: %x:%x\n",
361		    PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id));
362		goto fail;
363	}
364
365	/* Save the cache line size. */
366	if (DC_IS_DAVICOM(sc))
367		sc->dc_cachesize = 0;
368	else
369		sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag,
370		    DC_PCI_CFLT) & 0xFF;
371
372	/* Reset the adapter. */
373	dc_reset(sc);
374
375	/* Take 21143 out of snooze mode */
376	if (DC_IS_INTEL(sc)) {
377		command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD);
378		command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE);
379		pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command);
380	}
381
382	/*
383	 * Try to learn something about the supported media.
384	 * We know that ASIX and ADMtek and Davicom devices
385	 * will *always* be using MII media, so that's a no-brainer.
386	 * The tricky ones are the Macronix/PNIC II and the
387	 * Intel 21143.
388	 */
389	if (DC_IS_INTEL(sc)) {
390		u_int32_t		media, cwuc;
391		cwuc = pci_conf_read(pc, pa->pa_tag, DC_PCI_CWUC);
392		cwuc |= DC_CWUC_FORCE_WUL;
393		pci_conf_write(pc, pa->pa_tag, DC_PCI_CWUC, cwuc);
394		DELAY(10000);
395		media = pci_conf_read(pc, pa->pa_tag, DC_PCI_CWUC);
396		cwuc &= ~DC_CWUC_FORCE_WUL;
397		pci_conf_write(pc, pa->pa_tag, DC_PCI_CWUC, cwuc);
398		DELAY(10000);
399		if (media & DC_CWUC_MII_ABILITY)
400			sc->dc_pmode = DC_PMODE_MII;
401		if (media & DC_CWUC_SYM_ABILITY) {
402			sc->dc_pmode = DC_PMODE_SYM;
403			sc->dc_flags |= DC_21143_NWAY;
404		}
405		/*
406		 * If none of the bits are set, then this NIC
407		 * isn't meant to support 'wake up LAN' mode.
408		 * This is usually only the case on multiport
409		 * cards, and these cards almost always have
410		 * MII transceivers.
411		 */
412		if (media == 0)
413			sc->dc_pmode = DC_PMODE_MII;
414	} else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
415		if (sc->dc_type == DC_TYPE_98713)
416			sc->dc_pmode = DC_PMODE_MII;
417		else
418			sc->dc_pmode = DC_PMODE_SYM;
419	} else if (!sc->dc_pmode)
420		sc->dc_pmode = DC_PMODE_MII;
421
422	dc_attach_common(sc);
423
424fail:
425	splx(s);
426}
427
428struct cfattach dc_pci_ca = {
429	sizeof(struct dc_softc), dc_pci_probe, dc_pci_attach
430};
431