if_tlp_pci.c revision 1.1 1 /* $NetBSD: if_tlp_pci.c,v 1.1 1999/09/01 00:32:42 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 1999 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 * PCI bus front-end for the Digital Semiconductor ``Tulip'' (21x4x)
42 * Ethernet controller family driver.
43 */
44
45 #include "opt_inet.h"
46 #include "opt_ns.h"
47 #include "bpfilter.h"
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/mbuf.h>
52 #include <sys/malloc.h>
53 #include <sys/kernel.h>
54 #include <sys/socket.h>
55 #include <sys/ioctl.h>
56 #include <sys/errno.h>
57 #include <sys/device.h>
58
59 #include <net/if.h>
60 #include <net/if_dl.h>
61 #include <net/if_media.h>
62 #include <net/if_ether.h>
63
64 #if NBPFILTER > 0
65 #include <net/bpf.h>
66 #endif
67
68 #ifdef INET
69 #include <netinet/in.h>
70 #include <netinet/if_inarp.h>
71 #endif
72
73 #ifdef NS
74 #include <netns/ns.h>
75 #include <netns/ns_if.h>
76 #endif
77
78 #include <machine/bus.h>
79 #include <machine/intr.h>
80
81 #include <dev/mii/miivar.h>
82
83 #include <dev/ic/tulipreg.h>
84 #include <dev/ic/tulipvar.h>
85
86 #include <dev/pci/pcivar.h>
87 #include <dev/pci/pcireg.h>
88 #include <dev/pci/pcidevs.h>
89
90 /*
91 * PCI configuration space registers used by the Tulip.
92 */
93 #define TULIP_PCI_IOBA 0x10 /* i/o mapped base */
94 #define TULIP_PCI_MMBA 0x14 /* memory mapped base */
95
96 struct tulip_pci_softc {
97 struct tulip_softc sc_tulip; /* real Tulip softc */
98
99 /* PCI-specific goo. */
100 void *sc_ih; /* interrupt handle */
101 };
102
103 int tlp_pci_match __P((struct device *, struct cfdata *, void *));
104 void tlp_pci_attach __P((struct device *, struct device *, void *));
105
106 struct cfattach tlp_pci_ca = {
107 sizeof(struct tulip_pci_softc), tlp_pci_match, tlp_pci_attach,
108 };
109
110 const struct tulip_pci_product {
111 u_int32_t tpp_vendor; /* PCI vendor ID */
112 u_int32_t tpp_product; /* PCI product ID */
113 tulip_chip_t tpp_chip; /* base Tulip chip type */
114 } tlp_pci_products[] = {
115 #if 0
116 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21040,
117 TULIP_CHIP_21040 },
118 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21041,
119 TULIP_CHIP_21041 },
120 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21140,
121 TULIP_CHIP_21140 },
122 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142,
123 TULIP_CHIP_21142 },
124 #endif
125
126 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNIC,
127 TULIP_CHIP_82C168 },
128
129 #if 0
130 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713,
131 TULIP_CHIP_MX98713 },
132 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX987x5,
133 TULIP_CHIP_MX98715 },
134 #endif
135
136 { PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F,
137 TULIP_CHIP_WB89C840F },
138
139 { 0, 0,
140 TULIP_CHIP_INVALID },
141 };
142
143 const char *tlp_pci_chip_names[] = TULIP_CHIP_NAMES;
144
145 const struct tulip_pci_product *tlp_pci_lookup
146 __P((const struct pci_attach_args *));
147
148 const struct tulip_pci_product *
149 tlp_pci_lookup(pa)
150 const struct pci_attach_args *pa;
151 {
152 const struct tulip_pci_product *tpp;
153
154 for (tpp = tlp_pci_products;
155 tlp_pci_chip_names[tpp->tpp_chip] != NULL;
156 tpp++) {
157 if (PCI_VENDOR(pa->pa_id) == tpp->tpp_vendor &&
158 PCI_PRODUCT(pa->pa_id) == tpp->tpp_product)
159 return (tpp);
160 }
161 return (NULL);
162 }
163
164 int
165 tlp_pci_match(parent, match, aux)
166 struct device *parent;
167 struct cfdata *match;
168 void *aux;
169 {
170 struct pci_attach_args *pa = aux;
171
172 if (tlp_pci_lookup(pa) != NULL)
173 return (10); /* beat if_de.c */
174
175 return (0);
176 }
177
178 void
179 tlp_pci_attach(parent, self, aux)
180 struct device *parent, *self;
181 void *aux;
182 {
183 struct tulip_pci_softc *psc = (void *) self;
184 struct tulip_softc *sc = &psc->sc_tulip;
185 struct pci_attach_args *pa = aux;
186 pci_chipset_tag_t pc = pa->pa_pc;
187 pci_intr_handle_t ih;
188 const char *intrstr = NULL;
189 bus_space_tag_t iot, memt;
190 bus_space_handle_t ioh, memh;
191 int ioh_valid, memh_valid, i, j;
192 const struct tulip_pci_product *tpp;
193 u_int8_t enaddr[ETHER_ADDR_LEN], *romdata;
194 u_int16_t rombuf[TULIP_MAX_ROM_SIZE >> 1];
195 u_int32_t val;
196 const char *name = NULL;
197
198 /*
199 * Map the device.
200 */
201 ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA,
202 PCI_MAPREG_TYPE_IO, 0,
203 &iot, &ioh, NULL, NULL) == 0);
204 memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA,
205 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
206 &memt, &memh, NULL, NULL) == 0);
207
208 if (memh_valid) {
209 sc->sc_st = memt;
210 sc->sc_sh = memh;
211 } else if (ioh_valid) {
212 sc->sc_st = iot;
213 sc->sc_sh = ioh;
214 } else {
215 printf(": unable to map device registers\n");
216 return;
217 }
218
219 tpp = tlp_pci_lookup(pa);
220 if (tpp == NULL) {
221 printf("\n");
222 panic("tlp_pci_attach: impossible");
223 }
224 sc->sc_chip = tpp->tpp_chip;
225
226 /*
227 * Get revision info, and set some chip-specific variables.
228 */
229 sc->sc_rev = PCI_REVISION(pa->pa_class);
230 sc->sc_regshift = 0;
231 switch (sc->sc_chip) {
232 case TULIP_CHIP_21140:
233 if (sc->sc_rev >= 0x20)
234 sc->sc_chip = TULIP_CHIP_21140A;
235 break;
236
237 case TULIP_CHIP_21142:
238 if (sc->sc_rev >= 0x20)
239 sc->sc_chip = TULIP_CHIP_21143;
240 break;
241
242 case TULIP_CHIP_82C168:
243 if (sc->sc_rev >= 0x20)
244 sc->sc_chip = TULIP_CHIP_82C169;
245 break;
246
247 case TULIP_CHIP_MX98713:
248 if (sc->sc_rev >= 0x10)
249 sc->sc_chip = TULIP_CHIP_MX98713A;
250 break;
251
252 case TULIP_CHIP_MX98715:
253 if (sc->sc_rev >= 0x30)
254 sc->sc_chip = TULIP_CHIP_MX98725;
255 break;
256
257 case TULIP_CHIP_WB89C840F:
258 sc->sc_regshift = 1;
259 break;
260
261 default:
262 /* Nothing. */
263 }
264
265 printf(": %s Ethernet, pass %d.%d\n",
266 tlp_pci_chip_names[sc->sc_chip],
267 (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);
268
269 sc->sc_dmat = pa->pa_dmat;
270
271 /*
272 * Make sure bus mastering is enabled.
273 */
274 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
275 pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
276 PCI_COMMAND_MASTER_ENABLE);
277
278 /*
279 * Get the cacheline size.
280 */
281 sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag,
282 PCI_BHLC_REG));
283
284 /*
285 * Read the contents of the Ethernet Address ROM/SROM.
286 */
287 memset(rombuf, 0, sizeof(rombuf));
288 romdata = (u_int8_t *) rombuf;
289 switch (sc->sc_chip) {
290 case TULIP_CHIP_21040:
291 TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS);
292 for (i = 0; i < sizeof(rombuf); i++) {
293 for (j = 0; j < 10000; j++) {
294 val = TULIP_READ(sc, CSR_MIIROM);
295 if ((val & MIIROM_DN) == 0)
296 break;
297 }
298 romdata[i] = val & MIIROM_DATA;
299 }
300 break;
301
302 case TULIP_CHIP_82C168:
303 case TULIP_CHIP_82C169:
304 /*
305 * The Lite-On PNIC stores the Ethernet address in
306 * the first 3 words of the EEPROM. EEPROM access
307 * is not like the other Tulip chips.
308 */
309 for (i = 0; i < 3; i++) {
310 TULIP_WRITE(sc, CSR_PNIC_SROMCTL,
311 PNIC_SROMCTL_READ | i);
312 for (j = 0; j < 500; j++) {
313 delay(2);
314 val = TULIP_READ(sc, CSR_MIIROM);
315 if ((val & PNIC_MIIROM_BUSY) == 0)
316 break;
317 }
318 if (val & PNIC_MIIROM_BUSY) {
319 printf("%s: EEPROM timed out\n",
320 sc->sc_dev.dv_xname);
321 return;
322 }
323 rombuf[i] = (val & PNIC_MIIROM_DATA);
324 }
325 break;
326
327 default:
328 tlp_read_srom(sc, 0, sizeof(rombuf) >> 1, rombuf);
329 }
330
331 /*
332 * Deal with chip/board quirks. This includes setting up
333 * the mediasw, and extracting the Ethernet address from
334 * the rombuf.
335 *
336 * XXX Eventually, handle master/slave interrupts on the
337 * XXX multi-port boards which require that.
338 */
339 switch (sc->sc_chip) {
340 case TULIP_CHIP_82C168:
341 case TULIP_CHIP_82C169:
342 /*
343 * Lite-On PNIC's Ethernet address is the first 6
344 * bytes of its EEPROM.
345 */
346 memcpy(enaddr, romdata, ETHER_ADDR_LEN);
347
348 /*
349 * Lite-On PNICs always use the same mediasw; we
350 * select MII vs. internal NWAY automatically.
351 */
352 sc->sc_mediasw = &tlp_pnic_mediasw;
353 break;
354
355 case TULIP_CHIP_WB89C840F:
356 /*
357 * Winbond 89C840F's Ethernet address is the first
358 * 6 bytes of its EEPROM.
359 */
360 memcpy(enaddr, romdata, ETHER_ADDR_LEN);
361
362 /*
363 * Winbond 89C840F has an MII attached to the SIO.
364 */
365 sc->sc_mediasw = &tlp_sio_mii_mediasw;
366 break;
367
368 default:
369 printf("%s: sorry, unable to handle your board\n",
370 sc->sc_dev.dv_xname);
371 return;
372 }
373
374 /*
375 * Map and establish our interrupt.
376 */
377 if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
378 pa->pa_intrline, &ih)) {
379 printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname);
380 return;
381 }
382 intrstr = pci_intr_string(pc, ih);
383 psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, tlp_intr, sc);
384 if (psc->sc_ih == NULL) {
385 printf("%s: unable to establish interrupt",
386 sc->sc_dev.dv_xname);
387 if (intrstr != NULL)
388 printf(" at %s", intrstr);
389 printf("\n");
390 return;
391 }
392 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
393
394 /*
395 * Finish off the attach.
396 */
397 tlp_attach(sc, name, enaddr);
398 }
399