Annotation of sys/dev/cardbus/if_xl_cardbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_xl_cardbus.c,v 1.19 2007/05/05 13:24:03 deraadt Exp $ */
2: /* $NetBSD: if_xl_cardbus.c,v 1.13 2000/03/07 00:32:52 mycroft Exp $ */
3:
4: /*
5: * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter
6: *
7: * Copyright (c) 1998 and 1999
8: * HAYAKAWA Koichi. All rights reserved.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the author.
21: * 4. Neither the name of the author nor the names of any co-contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: *
38: */
39:
40: #include "bpfilter.h"
41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/mbuf.h>
45: #include <sys/socket.h>
46: #include <sys/ioctl.h>
47: #include <sys/errno.h>
48: #include <sys/malloc.h>
49: #include <sys/kernel.h>
50: #include <sys/proc.h>
51: #include <sys/device.h>
52:
53: #include <net/if.h>
54: #include <net/if_dl.h>
55: #include <net/if_types.h>
56: #include <net/if_media.h>
57:
58: #ifdef INET
59: #include <netinet/in.h>
60: #include <netinet/in_systm.h>
61: #include <netinet/in_var.h>
62: #include <netinet/ip.h>
63: #include <netinet/if_ether.h>
64: #endif
65:
66: #include <machine/cpu.h>
67: #include <machine/bus.h>
68:
69: #include <dev/cardbus/cardbusvar.h>
70: #include <dev/pci/pcidevs.h>
71:
72: #include <dev/mii/mii.h>
73: #include <dev/mii/miivar.h>
74:
75: #include <dev/ic/xlreg.h>
76:
77: #if defined XL_DEBUG
78: #define DPRINTF(a) printf a
79: #else
80: #define DPRINTF(a)
81: #endif
82:
83: #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG CARDBUS_BASE2_REG /* means 0x18 */
84:
85: int xl_cardbus_match(struct device *, void *, void *);
86: void xl_cardbus_attach(struct device *, struct device *,void *);
87: int xl_cardbus_detach(struct device *, int);
88: void xl_cardbus_intr_ack(struct xl_softc *);
89:
90: #define XL_CARDBUS_BOOMERANG 0x0001
91: #define XL_CARDBUS_CYCLONE 0x0002
92:
93: #define XL_CARDBUS_INTR 0x0004
94: #define XL_CARDBUS_INTR_ACK 0x8000
95:
96: struct xl_cardbus_softc {
97: struct xl_softc sc_softc;
98:
99: cardbus_devfunc_t sc_ct;
100: int sc_intrline;
101: u_int8_t sc_cardbus_flags;
102: u_int8_t sc_cardtype;
103:
104: /* CardBus function status space. 575B requests it. */
105: bus_space_tag_t sc_funct;
106: bus_space_handle_t sc_funch;
107: bus_size_t sc_funcsize;
108:
109: bus_size_t sc_mapsize; /* size of mapped bus space region */
110: };
111:
112: struct cfattach xl_cardbus_ca = {
113: sizeof(struct xl_cardbus_softc), xl_cardbus_match,
114: xl_cardbus_attach, xl_cardbus_detach
115: };
116:
117: const struct xl_cardbus_product {
118: u_int32_t ecp_prodid; /* CardBus product ID */
119: int ecp_flags; /* initial softc flags */
120: pcireg_t ecp_csr; /* PCI CSR flags */
121: int ecp_cardtype; /* card type */
122: const char *ecp_name; /* device name */
123: } xl_cardbus_products[] = {
124: { PCI_PRODUCT_3COM_3C575,
125: XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM,
126: CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE,
127: XL_CARDBUS_BOOMERANG,
128: "3c575-TX Ethernet" },
129:
130: { PCI_PRODUCT_3COM_3CCFE575BT,
131: XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
132: XL_FLAG_INVERT_LED_PWR,
133: CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
134: CARDBUS_COMMAND_MASTER_ENABLE,
135: XL_CARDBUS_CYCLONE,
136: "3c575B-TX Ethernet" },
137:
138: { PCI_PRODUCT_3COM_3CCFE575CT,
139: XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
140: XL_FLAG_INVERT_MII_PWR,
141: CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
142: CARDBUS_COMMAND_MASTER_ENABLE,
143: XL_CARDBUS_CYCLONE,
144: "3c575C-TX Ethernet" },
145:
146: { PCI_PRODUCT_3COM_3CCFEM656,
147: XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
148: XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
149: CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
150: CARDBUS_COMMAND_MASTER_ENABLE,
151: XL_CARDBUS_CYCLONE,
152: "3c656-TX Ethernet" },
153:
154: { PCI_PRODUCT_3COM_3CCFEM656B,
155: XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
156: XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
157: CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
158: CARDBUS_COMMAND_MASTER_ENABLE,
159: XL_CARDBUS_CYCLONE,
160: "3c656B-TX Ethernet" },
161:
162: { PCI_PRODUCT_3COM_3CCFEM656C,
163: XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
164: XL_FLAG_INVERT_MII_PWR,
165: CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
166: CARDBUS_COMMAND_MASTER_ENABLE,
167: XL_CARDBUS_CYCLONE,
168: "3c656C-TX Ethernet" },
169:
170: { 0,
171: 0,
172: 0,
173: 0,
174: NULL },
175: };
176:
177: const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *);
178:
179: const struct xl_cardbus_product *
180: xl_cardbus_lookup(const struct cardbus_attach_args *ca)
181: {
182: const struct xl_cardbus_product *ecp;
183:
184: if (CARDBUS_VENDOR(ca->ca_id) != PCI_VENDOR_3COM)
185: return (NULL);
186:
187: for (ecp = xl_cardbus_products; ecp->ecp_name != NULL; ecp++)
188: if (CARDBUS_PRODUCT(ca->ca_id) == ecp->ecp_prodid)
189: return (ecp);
190: return (NULL);
191: }
192:
193: int
194: xl_cardbus_match(struct device *parent, void *match, void *aux)
195: {
196: struct cardbus_attach_args *ca = aux;
197:
198: if (xl_cardbus_lookup(ca) != NULL)
199: return (1);
200:
201: return (0);
202: }
203:
204: void
205: xl_cardbus_attach(struct device *parent, struct device *self, void *aux)
206: {
207: struct xl_cardbus_softc *csc = (void *)self;
208: struct xl_softc *sc = &csc->sc_softc;
209: struct cardbus_attach_args *ca = aux;
210: cardbus_devfunc_t ct = ca->ca_ct;
211: cardbus_chipset_tag_t cc = ct->ct_cc;
212: cardbus_function_tag_t cf = ct->ct_cf;
213: cardbusreg_t iob, command, bhlc;
214: const struct xl_cardbus_product *ecp;
215: bus_space_handle_t ioh;
216: bus_addr_t adr;
217:
218: if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0,
219: &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) {
220: printf(": can't map i/o space\n");
221: return;
222: }
223:
224: ecp = xl_cardbus_lookup(ca);
225: if (ecp == NULL) {
226: printf("\n");
227: panic("xl_cardbus_attach: impossible");
228: }
229:
230: printf(": 3Com %s", ecp->ecp_name);
231:
232: sc->xl_flags = ecp->ecp_flags;
233: sc->sc_dmat = ca->ca_dmat;
234:
235: iob = adr;
236: sc->xl_bhandle = ioh;
237:
238: (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
239:
240: command = cardbus_conf_read(cc, cf, ca->ca_tag,
241: CARDBUS_COMMAND_STATUS_REG);
242: command |= ecp->ecp_csr;
243: csc->sc_cardtype = ecp->ecp_cardtype;
244:
245: if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
246: /* map CardBus function status window */
247: if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG,
248: CARDBUS_MAPREG_TYPE_MEM, 0, &csc->sc_funct,
249: &csc->sc_funch, 0, &csc->sc_funcsize)) {
250: printf("%s: unable to map function status window\n",
251: self->dv_xname);
252: return;
253: }
254:
255: /*
256: * Make sure CardBus bridge can access memory space. Usually
257: * memory access is enabled by BIOS, but some BIOSes do not
258: * enable it.
259: */
260: (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
261: }
262:
263: (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
264: cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG,
265: command);
266:
267: /*
268: * set latency timer
269: */
270: bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG);
271: if (CARDBUS_LATTIMER(bhlc) < 0x20) {
272: /* at least the value of latency timer should 0x20. */
273: DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n",
274: CARDBUS_LATTIMER(bhlc)));
275: bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
276: bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT);
277: cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc);
278: }
279:
280: csc->sc_ct = ca->ca_ct;
281: csc->sc_intrline = ca->ca_intrline;
282:
283: /* Map and establish the interrupt. */
284:
285: sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline,
286: IPL_NET, xl_intr, csc, self->dv_xname);
287:
288: if (sc->xl_intrhand == NULL) {
289: printf(": couldn't establish interrupt");
290: printf(" at %d", ca->ca_intrline);
291: printf("\n");
292: return;
293: }
294: printf(": irq %d", ca->ca_intrline);
295:
296: sc->intr_ack = xl_cardbus_intr_ack;
297:
298: xl_attach(sc);
299:
300: if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
301: bus_space_write_4(csc->sc_funct, csc->sc_funch,
302: XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK);
303:
304: }
305:
306: int
307: xl_detach(struct xl_softc *sc)
308: {
309: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
310: extern void xl_freetxrx(struct xl_softc *);
311:
312: /* Unhook our tick handler. */
313: timeout_del(&sc->xl_stsup_tmo);
314:
315: xl_freetxrx(sc);
316:
317: /* Detach all PHYs */
318: if (sc->xl_hasmii)
319: mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
320:
321: /* Delete all remaining media. */
322: ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
323:
324: ether_ifdetach(ifp);
325: if_detach(ifp);
326:
327: if (sc->sc_sdhook != NULL)
328: shutdownhook_disestablish(sc->sc_sdhook);
329: if (sc->sc_pwrhook != NULL)
330: powerhook_disestablish(sc->sc_pwrhook);
331:
332: return (0);
333: }
334:
335: int
336: xl_cardbus_detach(struct device *self, int arg)
337: {
338: struct xl_cardbus_softc *csc = (void *)self;
339: struct xl_softc *sc = &csc->sc_softc;
340: struct cardbus_devfunc *ct = csc->sc_ct;
341: int rv = 0;
342:
343: #if defined(DIAGNOSTIC)
344: if (ct == NULL) {
345: panic("%s: data structure lacks", sc->sc_dev.dv_xname);
346: }
347: #endif
348:
349: rv = xl_detach(sc);
350: if (rv == 0) {
351: /*
352: * Unhook the interrupt handler.
353: */
354: cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf,
355: sc->xl_intrhand);
356:
357: if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
358: Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG,
359: csc->sc_funct, csc->sc_funch, csc->sc_funcsize);
360: }
361:
362: Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag,
363: sc->xl_bhandle, csc->sc_mapsize);
364: }
365: return (rv);
366: }
367:
368: void
369: xl_cardbus_intr_ack(struct xl_softc *sc)
370: {
371: struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc;
372:
373: bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR,
374: XL_CARDBUS_INTR_ACK);
375: }
CVSweb