if_tlp_cardbus.c revision 1.15 1 /* $NetBSD: if_tlp_cardbus.c,v 1.15 2000/03/07 00:43:36 mycroft 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 cardbus_devfunc_t sc_ct; /* our CardBus devfuncs */
115 int sc_csr; /* CSR bits */
116 bus_size_t sc_mapsize; /* the size of mapped bus space region */
117 int sc_attached;
118 };
119
120 int tlp_cardbus_match __P((struct device *, struct cfdata *, void *));
121 void tlp_cardbus_attach __P((struct device *, struct device *, void *));
122 int tlp_cardbus_detach __P((struct device *, int));
123
124 struct cfattach tlp_cardbus_ca = {
125 sizeof(struct tulip_cardbus_softc),
126 tlp_cardbus_match, tlp_cardbus_attach,
127 tlp_cardbus_detach, tlp_activate,
128 };
129
130 const struct tulip_cardbus_product {
131 u_int32_t tcp_vendor; /* PCI vendor ID */
132 u_int32_t tcp_product; /* PCI product ID */
133 tulip_chip_t tcp_chip; /* base Tulip chip type */
134 int tcp_pmreg; /* power management register offset */
135 } tlp_cardbus_products[] = {
136 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142,
137 TULIP_CHIP_21142, 0xe0 },
138
139 { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143,
140 TULIP_CHIP_X3201_3, 0xe0 },
141
142 { 0, 0,
143 TULIP_CHIP_INVALID, 0 },
144 };
145
146 void tlp_cardbus_x3201_reset __P((struct tulip_softc *));
147
148 const struct tulip_cardbus_product *tlp_cardbus_lookup
149 __P((const struct cardbus_attach_args *));
150
151 const struct tulip_cardbus_product *
152 tlp_cardbus_lookup(ca)
153 const struct cardbus_attach_args *ca;
154 {
155 const struct tulip_cardbus_product *tcp;
156
157 for (tcp = tlp_cardbus_products;
158 tlp_chip_names[tcp->tcp_chip] != NULL;
159 tcp++) {
160 if (PCI_VENDOR(ca->ca_id) == tcp->tcp_vendor &&
161 PCI_PRODUCT(ca->ca_id) == tcp->tcp_product)
162 return (tcp);
163 }
164 return (NULL);
165 }
166
167 int
168 tlp_cardbus_match(parent, match, aux)
169 struct device *parent;
170 struct cfdata *match;
171 void *aux;
172 {
173 struct cardbus_attach_args *ca = aux;
174
175 if (tlp_cardbus_lookup(ca) != NULL)
176 return (1);
177
178 return (0);
179 }
180
181 void
182 tlp_cardbus_attach(parent, self, aux)
183 struct device *parent, *self;
184 void *aux;
185 {
186 struct tulip_cardbus_softc *csc = (void *)self;
187 struct tulip_softc *sc = &csc->sc_tulip;
188 struct cardbus_attach_args *ca = aux;
189 cardbus_devfunc_t ct = ca->ca_ct;
190 cardbus_chipset_tag_t cc = ct->ct_cc;
191 cardbus_function_tag_t cf = ct->ct_cf;
192 const struct tulip_cardbus_product *tcp;
193 u_int8_t enaddr[ETHER_ADDR_LEN];
194 pcireg_t reg;
195 bus_addr_t adr;
196
197 sc->sc_devno = ca->ca_device;
198 sc->sc_dmat = ca->ca_dmat;
199 csc->sc_ct = ct;
200
201 tcp = tlp_cardbus_lookup(ca);
202 if (tcp == NULL) {
203 printf("\n");
204 panic("tlp_cardbus_attach: impossible");
205 }
206 sc->sc_chip = tcp->tcp_chip;
207
208 /*
209 * By default, Tulip registers are 8 bytes long (4 bytes
210 * followed by a 4 byte pad).
211 */
212 sc->sc_regshift = 3;
213
214 /*
215 * Get revision info, and set some chip-specific variables.
216 */
217 sc->sc_rev = PCI_REVISION(ca->ca_class);
218 switch (sc->sc_chip) {
219 case TULIP_CHIP_21142:
220 if (sc->sc_rev >= 0x20)
221 sc->sc_chip = TULIP_CHIP_21143;
222 break;
223
224 default:
225 /* Nothing. */
226 }
227
228 printf(": %s Ethernet, pass %d.%d\n",
229 tlp_chip_names[sc->sc_chip],
230 (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);
231
232 /*
233 * Check to see if the device is in power-save mode, and
234 * bring it out if necessary.
235 */
236 switch (sc->sc_chip) {
237 case TULIP_CHIP_21142:
238 case TULIP_CHIP_21143:
239 case TULIP_CHIP_X3201_3:
240 #if 0
241 /*
242 * Clear the "sleep mode" bit in the CFDA register.
243 */
244 reg = cardbus_conf_read(cc, cf, ca->ca_tag, TULIP_PCI_CFDA);
245 if (reg & (CFDA_SLEEP|CFDA_SNOOZE))
246 cardbus_conf_write(cc, cf, ca->ca_tag, TULIP_PCI_CFDA,
247 reg & ~(CFDA_SLEEP|CFDA_SNOOZE));
248 break;
249 #endif
250
251 default:
252 /* Nothing. */
253 }
254
255 if (cardbus_get_capability(cc, cf, ca->ca_tag, PCI_CAP_PWRMGMT, 0, 0)) {
256 if (tcp->tcp_pmreg == 0) {
257 printf("%s: don't know location of PMCSR for this "
258 "chip\n", sc->sc_dev.dv_xname);
259 return;
260 }
261 reg = cardbus_conf_read(cc, cf, ca->ca_tag,
262 tcp->tcp_pmreg) & 0x03;
263 #if 1 /* XXX Probably not right for CardBus. */
264 if (reg == 3) {
265 /*
266 * The card has lost all configuration data in
267 * this state, so punt.
268 */
269 printf("%s: unable to wake up from power state D3\n",
270 sc->sc_dev.dv_xname);
271 return;
272 }
273 #endif
274 if (reg != 0) {
275 printf("%s: waking up from power state D%d\n",
276 sc->sc_dev.dv_xname, reg);
277 cardbus_conf_write(cc, cf, ca->ca_tag,
278 tcp->tcp_pmreg, 0);
279 }
280 }
281
282 /*
283 * Map the device.
284 */
285 csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
286 if (0 && Cardbus_mapreg_map(ct, TULIP_PCI_MMBA,
287 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
288 &sc->sc_st, &sc->sc_sh, &adr, &csc->sc_mapsize) == 0) {
289 #if rbus
290 #else
291 (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
292 #endif
293 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
294 csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
295 } else if (Cardbus_mapreg_map(ct, TULIP_PCI_IOBA,
296 PCI_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
297 &csc->sc_mapsize) == 0) {
298 #if rbus
299 #else
300 (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
301 #endif
302 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
303 csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
304 } else {
305 printf("%s: unable to map device registers\n",
306 sc->sc_dev.dv_xname);
307 return;
308 }
309
310 /* Make sure the right access type is on the CardBus bridge. */
311 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
312
313 /* Enable the appropriate bits in the PCI CSR. */
314 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_COMMAND_STATUS_REG);
315 reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
316 reg |= csc->sc_csr;
317 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg);
318
319 /*
320 * Make sure the latency timer is set to some reasonable
321 * value.
322 */
323 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_BHLC_REG);
324 if (PCI_LATTIMER(reg) < 0x20) {
325 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
326 reg |= (0x20 << PCI_LATTIMER_SHIFT);
327 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_BHLC_REG, reg);
328 }
329
330 /*
331 * Read the contents of the Ethernet Address ROM/SROM.
332 */
333 switch (sc->sc_chip) {
334 case TULIP_CHIP_X3201_3:
335 /*
336 * No SROM on this chip.
337 */
338 break;
339
340 default:
341 if (tlp_read_srom(sc) == 0)
342 goto cant_cope;
343 break;
344 }
345
346 /*
347 * Deal with chip/board quirks. This includes setting up
348 * the mediasw, and extracting the Ethernet address from
349 * the rombuf.
350 */
351 switch (sc->sc_chip) {
352 case TULIP_CHIP_21142:
353 case TULIP_CHIP_21143:
354 /* Check for new format SROM. */
355 if (tlp_isv_srom_enaddr(sc, enaddr) == 0) {
356 /*
357 * Not an ISV SROM; try the old DEC Ethernet Address
358 * ROM format.
359 */
360 if (tlp_parse_old_srom(sc, enaddr) == 0)
361 goto cant_cope;
362 } else {
363 /*
364 * We start out with the 2114x ISV media switch.
365 * When we search for quirks, we may change to
366 * a different switch.
367 */
368 sc->sc_mediasw = &tlp_2114x_isv_mediasw;
369 }
370
371 /*
372 * Bail out now if we can't deal with this board.
373 */
374 if (sc->sc_mediasw == NULL)
375 goto cant_cope;
376 break;
377
378 case TULIP_CHIP_X3201_3:
379 /*
380 * The X3201 doesn't have an SROM. Lift the MAC address
381 * from the CIS. Also, we have a special media switch:
382 * MII-on-SIO, plus some special GPIO setup.
383 */
384 memcpy(enaddr, ca->ca_cis.funce.network.netid, sizeof(enaddr));
385 sc->sc_reset = tlp_cardbus_x3201_reset;
386 sc->sc_mediasw = &tlp_sio_mii_mediasw;
387 break;
388
389 default:
390 cant_cope:
391 printf("%s: sorry, unable to handle your board\n",
392 sc->sc_dev.dv_xname);
393 return;
394 }
395
396 /*
397 * Map and establish the interrupt.
398 */
399 csc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
400 tlp_intr, sc);
401 if (csc->sc_ih == NULL) {
402 printf("%s: unable to establish interrupt at %d\n",
403 sc->sc_dev.dv_xname, ca->ca_intrline);
404 return;
405 }
406 printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
407 ca->ca_intrline);
408
409 /*
410 * Finish off the attach.
411 */
412 csc->sc_attached = 1;
413 tlp_attach(sc, enaddr);
414 }
415
416 int
417 tlp_cardbus_detach(self, flags)
418 struct device *self;
419 int flags;
420 {
421 struct tulip_cardbus_softc *csc = (void *)self;
422 struct tulip_softc *sc = &csc->sc_tulip;
423 struct cardbus_devfunc *ct = csc->sc_ct;
424 int rv;
425 int reg;
426
427 #if defined(DIAGNOSTIC)
428 if (ct == NULL) {
429 panic("%s: data structure lacks\n", sc->sc_dev.dv_xname);
430 }
431 #endif
432
433 if (csc->sc_attached) {
434 rv = tlp_detach(sc);
435 if (rv)
436 return (rv);
437 }
438
439 /*
440 * Unhook the interrupt handler.
441 */
442 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
443
444 /*
445 * release bus space and close window
446 */
447 if (csc->sc_csr & PCI_COMMAND_MEM_ENABLE)
448 reg = TULIP_PCI_MMBA;
449 else
450 reg = TULIP_PCI_IOBA;
451 Cardbus_mapreg_unmap(ct, reg, sc->sc_st, sc->sc_sh,
452 csc->sc_mapsize);
453
454 return (0);
455 }
456
457 void
458 tlp_cardbus_x3201_reset(sc)
459 struct tulip_softc *sc;
460 {
461 u_int32_t reg;
462
463 reg = TULIP_READ(sc, CSR_SIAGEN);
464
465 /* make GP[2,0] outputs */
466 TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_MD) | SIAGEN_CWE |
467 0x00050000);
468 TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_CWE) | SIAGEN_MD);
469 }
470