if_tlp_cardbus.c revision 1.13 1 /* $NetBSD: if_tlp_cardbus.c,v 1.13 2000/02/04 13:43:56 augustss Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000 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 * CardBus bus front-end for the Digital Semiconductor ``Tulip'' (21x4x)
42 * Ethernet controller family driver.
43 *
44 * TODO:
45 *
46 * - power management
47 */
48
49 #include "opt_inet.h"
50 #include "opt_ns.h"
51 #include "bpfilter.h"
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/mbuf.h>
56 #include <sys/malloc.h>
57 #include <sys/kernel.h>
58 #include <sys/socket.h>
59 #include <sys/ioctl.h>
60 #include <sys/errno.h>
61 #include <sys/device.h>
62
63 #include <machine/endian.h>
64
65 #include <net/if.h>
66 #include <net/if_dl.h>
67 #include <net/if_media.h>
68 #include <net/if_ether.h>
69
70 #if NBPFILTER > 0
71 #include <net/bpf.h>
72 #endif
73
74 #ifdef INET
75 #include <netinet/in.h>
76 #include <netinet/if_inarp.h>
77 #endif
78
79 #ifdef NS
80 #include <netns/ns.h>
81 #include <netns/ns_if.h>
82 #endif
83
84 #include <machine/bus.h>
85 #include <machine/intr.h>
86
87 #include <dev/mii/miivar.h>
88 #include <dev/mii/mii_bitbang.h>
89
90 #include <dev/ic/tulipreg.h>
91 #include <dev/ic/tulipvar.h>
92
93 #include <dev/pci/pcivar.h>
94 #include <dev/pci/pcireg.h>
95 #include <dev/pci/pcidevs.h>
96
97 #include <dev/cardbus/cardbusvar.h>
98
99 /*
100 * PCI configuration space registers used by the Tulip.
101 */
102 #define TULIP_PCI_IOBA 0x10 /* i/o mapped base */
103 #define TULIP_PCI_MMBA 0x14 /* memory mapped base */
104 #define TULIP_PCI_CFDA 0x40 /* configuration driver area */
105
106 #define CFDA_SLEEP 0x80000000 /* sleep mode */
107 #define CFDA_SNOOZE 0x40000000 /* snooze mode */
108
109 struct tulip_cardbus_softc {
110 struct tulip_softc sc_tulip; /* real Tulip softc */
111
112 /* CardBus-specific goo. */
113 void *sc_ih; /* interrupt handle */
114
115 cardbus_devfunc_t sc_ct; /* our CardBus devfuncs */
116 int sc_intrline; /* our interrupt line */
117 cardbustag_t sc_tag;
118
119 int sc_cbenable; /* what CardBus access type to enable */
120 int sc_csr; /* CSR bits */
121 bus_size_t sc_mapsize; /* the size of mapped bus space region */
122 };
123
124 int tlp_cardbus_match __P((struct device *, struct cfdata *, void *));
125 void tlp_cardbus_attach __P((struct device *, struct device *, void *));
126 int tlp_cardbus_detach __P((struct device *, int));
127
128 struct cfattach tlp_cardbus_ca = {
129 sizeof(struct tulip_cardbus_softc),
130 tlp_cardbus_match, tlp_cardbus_attach,
131 tlp_cardbus_detach, tlp_activate,
132 };
133
134 const struct tulip_cardbus_product {
135 u_int32_t tcp_vendor; /* PCI vendor ID */
136 u_int32_t tcp_product; /* PCI product ID */
137 tulip_chip_t tcp_chip; /* base Tulip chip type */
138 int tcp_pmreg; /* power management register offset */
139 } tlp_cardbus_products[] = {
140 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142,
141 TULIP_CHIP_21142, 0xe0 },
142
143 { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143,
144 TULIP_CHIP_X3201_3, 0xe0 },
145
146 { 0, 0,
147 TULIP_CHIP_INVALID, 0 },
148 };
149
150 void tlp_cardbus_x3201_reset __P((struct tulip_softc *));
151
152 const struct tulip_cardbus_product *tlp_cardbus_lookup
153 __P((const struct cardbus_attach_args *));
154
155 const struct tulip_cardbus_product *
156 tlp_cardbus_lookup(ca)
157 const struct cardbus_attach_args *ca;
158 {
159 const struct tulip_cardbus_product *tcp;
160
161 for (tcp = tlp_cardbus_products;
162 tlp_chip_names[tcp->tcp_chip] != NULL;
163 tcp++) {
164 if (PCI_VENDOR(ca->ca_id) == tcp->tcp_vendor &&
165 PCI_PRODUCT(ca->ca_id) == tcp->tcp_product)
166 return (tcp);
167 }
168 return (NULL);
169 }
170
171 int
172 tlp_cardbus_match(parent, match, aux)
173 struct device *parent;
174 struct cfdata *match;
175 void *aux;
176 {
177 struct cardbus_attach_args *ca = aux;
178
179 if (tlp_cardbus_lookup(ca) != NULL)
180 return (1);
181
182 return (0);
183 }
184
185 void
186 tlp_cardbus_attach(parent, self, aux)
187 struct device *parent, *self;
188 void *aux;
189 {
190 struct tulip_cardbus_softc *csc = (void *) self;
191 struct tulip_softc *sc = &csc->sc_tulip;
192 struct cardbus_attach_args *ca = aux;
193 cardbus_devfunc_t ct = ca->ca_ct;
194 cardbus_chipset_tag_t cc = ct->ct_cc;
195 cardbus_function_tag_t cf = ct->ct_cf;
196 const struct tulip_cardbus_product *tcp;
197 u_int8_t enaddr[ETHER_ADDR_LEN];
198 pcireg_t reg;
199
200 sc->sc_devno = ca->ca_device;
201 sc->sc_dmat = ca->ca_dmat;
202 csc->sc_ct = ct;
203 csc->sc_tag = ca->ca_tag;
204 csc->sc_intrline = ca->ca_intrline;
205
206 tcp = tlp_cardbus_lookup(ca);
207 if (tcp == NULL) {
208 printf("\n");
209 panic("tlp_cardbus_attach: impossible");
210 }
211 sc->sc_chip = tcp->tcp_chip;
212
213 /*
214 * By default, Tulip registers are 8 bytes long (4 bytes
215 * followed by a 4 byte pad).
216 */
217 sc->sc_regshift = 3;
218
219 /*
220 * Some chips have a 128 byte SROM (6 address bits), and some
221 * have a 512 byte SROM (8 address bits). Default to 6; we'll
222 * adjust below.
223 */
224 sc->sc_srom_addrbits = 6;
225
226 /*
227 * Get revision info, and set some chip-specific variables.
228 */
229 sc->sc_rev = PCI_REVISION(ca->ca_class);
230 switch (sc->sc_chip) {
231 case TULIP_CHIP_21142:
232 if (sc->sc_rev >= 0x20)
233 sc->sc_chip = TULIP_CHIP_21143;
234 if (sc->sc_rev >= 0x41) {
235 /*
236 * 21143 rev. 4.1 has a larger SROM.
237 */
238 sc->sc_srom_addrbits = 8;
239 }
240 break;
241
242 default:
243 /* Nothing. */
244 }
245
246 printf(": %s Ethernet, pass %d.%d\n",
247 tlp_chip_names[sc->sc_chip],
248 (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);
249
250 /*
251 * Check to see if the device is in power-save mode, and
252 * bring it out if necessary.
253 */
254 switch (sc->sc_chip) {
255 case TULIP_CHIP_21142:
256 case TULIP_CHIP_21143:
257 case TULIP_CHIP_X3201_3:
258 /*
259 * Clear the "sleep mode" bit in the CFDA register.
260 */
261 reg = cardbus_conf_read(cc, cf, ca->ca_tag, TULIP_PCI_CFDA);
262 if (reg & (CFDA_SLEEP|CFDA_SNOOZE))
263 cardbus_conf_write(cc, cf, ca->ca_tag, TULIP_PCI_CFDA,
264 reg & ~(CFDA_SLEEP|CFDA_SNOOZE));
265 break;
266
267 default:
268 /* Nothing. */
269 }
270
271 if (cardbus_get_capability(cc, cf, ca->ca_tag, PCI_CAP_PWRMGMT, 0, 0)) {
272 if (tcp->tcp_pmreg == 0) {
273 printf("%s: don't know location of PMCSR for this "
274 "chip\n", sc->sc_dev.dv_xname);
275 return;
276 }
277 reg = cardbus_conf_read(cc, cf, ca->ca_tag,
278 tcp->tcp_pmreg) & 0x03;
279 #if 1 /* XXX Probably not right for CardBus. */
280 if (reg == 3) {
281 /*
282 * The card has lost all configuration data in
283 * this state, so punt.
284 */
285 printf("%s: unable to wake up from power state D3\n",
286 sc->sc_dev.dv_xname);
287 return;
288 }
289 #endif
290 if (reg != 0) {
291 printf("%s: waking up from power state D%d\n",
292 sc->sc_dev.dv_xname, reg);
293 cardbus_conf_write(cc, cf, ca->ca_tag,
294 tcp->tcp_pmreg, 0);
295 }
296 }
297
298 /*
299 * Map the device.
300 */
301 csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
302 if (Cardbus_mapreg_map(csc->sc_ct, TULIP_PCI_MMBA,
303 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
304 &sc->sc_st, &sc->sc_sh, NULL, &csc->sc_mapsize) == 0) {
305 csc->sc_cbenable = CARDBUS_MEM_ENABLE;
306 csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
307 } else if (Cardbus_mapreg_map(csc->sc_ct, TULIP_PCI_IOBA,
308 PCI_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, NULL,
309 &csc->sc_mapsize) == 0) {
310 csc->sc_cbenable = CARDBUS_IO_ENABLE;
311 csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
312 } else {
313 printf("%s: unable to map device registers\n",
314 sc->sc_dev.dv_xname);
315 return;
316 }
317
318 /* Make sure the right access type is on the CardBus bridge. */
319 (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cbenable);
320 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
321
322 /* Enable the appropriate bits in the PCI CSR. */
323 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_COMMAND_STATUS_REG);
324 reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
325 reg |= csc->sc_csr;
326 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg);
327
328 /*
329 * Make sure the latency timer is set to some reasonable
330 * value.
331 */
332 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_BHLC_REG);
333 if (PCI_LATTIMER(reg) < 0x20) {
334 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
335 reg |= (0x20 << PCI_LATTIMER_SHIFT);
336 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_BHLC_REG, reg);
337 }
338
339 /*
340 * Read the contents of the Ethernet Address ROM/SROM.
341 */
342 memset(sc->sc_srom, 0, sizeof(sc->sc_srom));
343 switch (sc->sc_chip) {
344 case TULIP_CHIP_X3201_3:
345 /*
346 * No SROM on this chip.
347 */
348 break;
349
350 default:
351 tlp_read_srom(sc, 0, TULIP_ROM_SIZE(sc->sc_srom_addrbits) >> 1,
352 sc->sc_srom);
353 #if 0
354 {
355 int i;
356
357 printf("SROM CONTENTS:");
358 for (i = 0; i <
359 TULIP_ROM_SIZE(sc->sc_srom_addrbits); i++) {
360 if ((i % 8) == 0)
361 printf("\n\t");
362 printf("0x%02x ", sc->sc_srom[i]);
363 }
364 printf("\n");
365 }
366 #endif
367 }
368
369 /*
370 * Deal with chip/board quirks. This includes setting up
371 * the mediasw, and extracting the Ethernet address from
372 * the rombuf.
373 */
374 switch (sc->sc_chip) {
375 case TULIP_CHIP_21142:
376 case TULIP_CHIP_21143:
377 /* Check for new format SROM. */
378 if (tlp_isv_srom_enaddr(sc, enaddr) == 0) {
379 /*
380 * Not an ISV SROM; can't cope, for now.
381 */
382 goto cant_cope;
383 } else {
384 /*
385 * We start out with the 2114x ISV media switch.
386 * When we search for quirks, we may change to
387 * a different switch.
388 */
389 sc->sc_mediasw = &tlp_2114x_isv_mediasw;
390 }
391
392 /*
393 * Bail out now if we can't deal with this board.
394 */
395 if (sc->sc_mediasw == NULL)
396 goto cant_cope;
397 break;
398
399 case TULIP_CHIP_X3201_3:
400 /*
401 * The X3201 doens't have an SROM. Lift the MAC address
402 * from the CIS. Also, we have a special media switch:
403 * MII-on-SIO, plus some special GPIO setup.
404 */
405 memcpy(enaddr, ca->ca_cis.funce.network.netid, sizeof(enaddr));
406 sc->sc_reset = tlp_cardbus_x3201_reset;
407 sc->sc_mediasw = &tlp_sio_mii_mediasw;
408 break;
409
410 default:
411 cant_cope:
412 printf("%s: sorry, unable to handle your board\n",
413 sc->sc_dev.dv_xname);
414 return;
415 }
416
417 /*
418 * Map and establish the interrupt.
419 */
420 csc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
421 tlp_intr, sc);
422 if (csc->sc_ih == NULL) {
423 printf("%s: unable to establish interrupt at %d\n",
424 sc->sc_dev.dv_xname, ca->ca_intrline);
425 return;
426 }
427 printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
428 ca->ca_intrline);
429
430 /*
431 * Finish off the attach.
432 */
433 tlp_attach(sc, enaddr);
434 }
435
436 int
437 tlp_cardbus_detach(self, flags)
438 struct device *self;
439 int flags;
440 {
441 struct tulip_cardbus_softc *csc = (void *) self;
442 struct tulip_softc *sc = &csc->sc_tulip;
443 struct cardbus_devfunc *ct = csc->sc_ct;
444 int rv;
445 int reg;
446
447 #if defined(DIAGNOSTIC)
448 if (ct == NULL) {
449 panic("%s: data structure lacks\n", sc->sc_dev.dv_xname);
450 }
451 #endif
452
453 rv = tlp_detach(sc);
454 if (rv == 0) {
455 /*
456 * Unhook the interrupt handler.
457 */
458 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
459
460 /*
461 * release bus space and close window
462 */
463 if (csc->sc_cbenable == CARDBUS_MEM_ENABLE) {
464 reg = TULIP_PCI_MMBA;
465 } else {
466 reg = TULIP_PCI_IOBA;
467 }
468
469 Cardbus_mapreg_unmap(ct, reg, sc->sc_st, sc->sc_sh,
470 csc->sc_mapsize);
471 }
472 return (rv);
473 }
474
475 void
476 tlp_cardbus_x3201_reset(sc)
477 struct tulip_softc *sc;
478 {
479 u_int32_t reg;
480
481 reg = TULIP_READ(sc, CSR_SIAGEN);
482
483 /* make GP[2,0] outputs */
484 TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_MD) | SIAGEN_CWE |
485 0x00050000);
486 TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_CWE) | SIAGEN_MD);
487 }
488