if_tlp_cardbus.c revision 1.16 1 /* $NetBSD: if_tlp_cardbus.c,v 1.16 2000/03/07 01:08:47 thorpej 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 /*
241 * Clear the "sleep mode" bit in the CFDA register.
242 */
243 reg = cardbus_conf_read(cc, cf, ca->ca_tag, TULIP_PCI_CFDA);
244 if (reg & (CFDA_SLEEP|CFDA_SNOOZE))
245 cardbus_conf_write(cc, cf, ca->ca_tag, TULIP_PCI_CFDA,
246 reg & ~(CFDA_SLEEP|CFDA_SNOOZE));
247 break;
248
249 default:
250 /* Nothing. */
251 }
252
253 if (cardbus_get_capability(cc, cf, ca->ca_tag, PCI_CAP_PWRMGMT, 0, 0)) {
254 if (tcp->tcp_pmreg == 0) {
255 printf("%s: don't know location of PMCSR for this "
256 "chip\n", sc->sc_dev.dv_xname);
257 return;
258 }
259 reg = cardbus_conf_read(cc, cf, ca->ca_tag,
260 tcp->tcp_pmreg) & 0x03;
261 #if 1 /* XXX Probably not right for CardBus. */
262 if (reg == 3) {
263 /*
264 * The card has lost all configuration data in
265 * this state, so punt.
266 */
267 printf("%s: unable to wake up from power state D3\n",
268 sc->sc_dev.dv_xname);
269 return;
270 }
271 #endif
272 if (reg != 0) {
273 printf("%s: waking up from power state D%d\n",
274 sc->sc_dev.dv_xname, reg);
275 cardbus_conf_write(cc, cf, ca->ca_tag,
276 tcp->tcp_pmreg, 0);
277 }
278 }
279
280 /*
281 * Map the device.
282 */
283 csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
284 if (0 && Cardbus_mapreg_map(ct, TULIP_PCI_MMBA,
285 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
286 &sc->sc_st, &sc->sc_sh, &adr, &csc->sc_mapsize) == 0) {
287 #if rbus
288 #else
289 (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
290 #endif
291 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
292 csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
293 } else if (Cardbus_mapreg_map(ct, TULIP_PCI_IOBA,
294 PCI_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
295 &csc->sc_mapsize) == 0) {
296 #if rbus
297 #else
298 (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
299 #endif
300 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
301 csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
302 } else {
303 printf("%s: unable to map device registers\n",
304 sc->sc_dev.dv_xname);
305 return;
306 }
307
308 /* Make sure the right access type is on the CardBus bridge. */
309 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
310
311 /* Enable the appropriate bits in the PCI CSR. */
312 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_COMMAND_STATUS_REG);
313 reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
314 reg |= csc->sc_csr;
315 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg);
316
317 /*
318 * Make sure the latency timer is set to some reasonable
319 * value.
320 */
321 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_BHLC_REG);
322 if (PCI_LATTIMER(reg) < 0x20) {
323 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
324 reg |= (0x20 << PCI_LATTIMER_SHIFT);
325 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_BHLC_REG, reg);
326 }
327
328 /*
329 * Read the contents of the Ethernet Address ROM/SROM.
330 */
331 switch (sc->sc_chip) {
332 case TULIP_CHIP_X3201_3:
333 /*
334 * No SROM on this chip.
335 */
336 break;
337
338 default:
339 if (tlp_read_srom(sc) == 0)
340 goto cant_cope;
341 break;
342 }
343
344 /*
345 * Deal with chip/board quirks. This includes setting up
346 * the mediasw, and extracting the Ethernet address from
347 * the rombuf.
348 */
349 switch (sc->sc_chip) {
350 case TULIP_CHIP_21142:
351 case TULIP_CHIP_21143:
352 /* Check for new format SROM. */
353 if (tlp_isv_srom_enaddr(sc, enaddr) == 0) {
354 /*
355 * Not an ISV SROM; try the old DEC Ethernet Address
356 * ROM format.
357 */
358 if (tlp_parse_old_srom(sc, enaddr) == 0)
359 goto cant_cope;
360 } else {
361 /*
362 * We start out with the 2114x ISV media switch.
363 * When we search for quirks, we may change to
364 * a different switch.
365 */
366 sc->sc_mediasw = &tlp_2114x_isv_mediasw;
367 }
368
369 /*
370 * Bail out now if we can't deal with this board.
371 */
372 if (sc->sc_mediasw == NULL)
373 goto cant_cope;
374 break;
375
376 case TULIP_CHIP_X3201_3:
377 /*
378 * The X3201 doesn't have an SROM. Lift the MAC address
379 * from the CIS. Also, we have a special media switch:
380 * MII-on-SIO, plus some special GPIO setup.
381 */
382 memcpy(enaddr, ca->ca_cis.funce.network.netid, sizeof(enaddr));
383 sc->sc_reset = tlp_cardbus_x3201_reset;
384 sc->sc_mediasw = &tlp_sio_mii_mediasw;
385 break;
386
387 default:
388 cant_cope:
389 printf("%s: sorry, unable to handle your board\n",
390 sc->sc_dev.dv_xname);
391 return;
392 }
393
394 /*
395 * Map and establish the interrupt.
396 */
397 csc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
398 tlp_intr, sc);
399 if (csc->sc_ih == NULL) {
400 printf("%s: unable to establish interrupt at %d\n",
401 sc->sc_dev.dv_xname, ca->ca_intrline);
402 return;
403 }
404 printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
405 ca->ca_intrline);
406
407 /*
408 * Finish off the attach.
409 */
410 csc->sc_attached = 1;
411 tlp_attach(sc, enaddr);
412 }
413
414 int
415 tlp_cardbus_detach(self, flags)
416 struct device *self;
417 int flags;
418 {
419 struct tulip_cardbus_softc *csc = (void *)self;
420 struct tulip_softc *sc = &csc->sc_tulip;
421 struct cardbus_devfunc *ct = csc->sc_ct;
422 int rv;
423 int reg;
424
425 #if defined(DIAGNOSTIC)
426 if (ct == NULL) {
427 panic("%s: data structure lacks\n", sc->sc_dev.dv_xname);
428 }
429 #endif
430
431 if (csc->sc_attached) {
432 rv = tlp_detach(sc);
433 if (rv)
434 return (rv);
435 }
436
437 /*
438 * Unhook the interrupt handler.
439 */
440 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
441
442 /*
443 * release bus space and close window
444 */
445 if (csc->sc_csr & PCI_COMMAND_MEM_ENABLE)
446 reg = TULIP_PCI_MMBA;
447 else
448 reg = TULIP_PCI_IOBA;
449 Cardbus_mapreg_unmap(ct, reg, sc->sc_st, sc->sc_sh,
450 csc->sc_mapsize);
451
452 return (0);
453 }
454
455 void
456 tlp_cardbus_x3201_reset(sc)
457 struct tulip_softc *sc;
458 {
459 u_int32_t reg;
460
461 reg = TULIP_READ(sc, CSR_SIAGEN);
462
463 /* make GP[2,0] outputs */
464 TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_MD) | SIAGEN_CWE |
465 0x00050000);
466 TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_CWE) | SIAGEN_MD);
467 }
468