Line data Source code
1 : /* $OpenBSD: if_xl_cardbus.c,v 1.33 2015/11/24 17:11:39 mpi 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 : *
19 : * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
20 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 : * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
23 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 : * SUCH DAMAGE.
30 : *
31 : *
32 : */
33 :
34 : #include "bpfilter.h"
35 :
36 : #include <sys/param.h>
37 : #include <sys/systm.h>
38 : #include <sys/mbuf.h>
39 : #include <sys/socket.h>
40 : #include <sys/ioctl.h>
41 : #include <sys/errno.h>
42 : #include <sys/malloc.h>
43 : #include <sys/kernel.h>
44 : #include <sys/device.h>
45 :
46 : #include <net/if.h>
47 : #include <net/if_media.h>
48 :
49 : #include <netinet/in.h>
50 : #include <netinet/if_ether.h>
51 :
52 : #include <machine/cpu.h>
53 : #include <machine/bus.h>
54 :
55 : #include <dev/cardbus/cardbusvar.h>
56 : #include <dev/pci/pcidevs.h>
57 :
58 : #include <dev/mii/miivar.h>
59 :
60 : #include <dev/ic/xlreg.h>
61 :
62 : #if defined XL_DEBUG
63 : #define DPRINTF(a) printf a
64 : #else
65 : #define DPRINTF(a)
66 : #endif
67 :
68 : #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG CARDBUS_BASE2_REG /* means 0x18 */
69 :
70 : int xl_cardbus_match(struct device *, void *, void *);
71 : void xl_cardbus_attach(struct device *, struct device *,void *);
72 : int xl_cardbus_detach(struct device *, int);
73 : void xl_cardbus_intr_ack(struct xl_softc *);
74 :
75 : #define XL_CARDBUS_BOOMERANG 0x0001
76 : #define XL_CARDBUS_CYCLONE 0x0002
77 :
78 : #define XL_CARDBUS_INTR 0x0004
79 : #define XL_CARDBUS_INTR_ACK 0x8000
80 :
81 : struct xl_cardbus_softc {
82 : struct xl_softc sc_softc;
83 :
84 : cardbus_devfunc_t sc_ct;
85 : int sc_intrline;
86 : u_int8_t sc_cardbus_flags;
87 : u_int8_t sc_cardtype;
88 :
89 : /* CardBus function status space. 575B requests it. */
90 : bus_space_tag_t sc_funct;
91 : bus_space_handle_t sc_funch;
92 : bus_size_t sc_funcsize;
93 :
94 : bus_size_t sc_mapsize; /* size of mapped bus space region */
95 : };
96 :
97 : struct cfattach xl_cardbus_ca = {
98 : sizeof(struct xl_cardbus_softc), xl_cardbus_match,
99 : xl_cardbus_attach, xl_cardbus_detach
100 : };
101 :
102 : const struct xl_cardbus_product {
103 : u_int32_t ecp_prodid; /* CardBus product ID */
104 : int ecp_flags; /* initial softc flags */
105 : pcireg_t ecp_csr; /* PCI CSR flags */
106 : int ecp_cardtype; /* card type */
107 : } xl_cardbus_products[] = {
108 : { PCI_PRODUCT_3COM_3C575,
109 : XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM,
110 : PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE,
111 : XL_CARDBUS_BOOMERANG },
112 :
113 : { PCI_PRODUCT_3COM_3CCFE575BT,
114 : XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
115 : XL_FLAG_INVERT_LED_PWR,
116 : PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
117 : PCI_COMMAND_MASTER_ENABLE,
118 : XL_CARDBUS_CYCLONE },
119 :
120 : { PCI_PRODUCT_3COM_3CCFE575CT,
121 : XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
122 : XL_FLAG_INVERT_MII_PWR,
123 : PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
124 : PCI_COMMAND_MASTER_ENABLE,
125 : XL_CARDBUS_CYCLONE },
126 :
127 : { PCI_PRODUCT_3COM_3CCFEM656,
128 : XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
129 : XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
130 : PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
131 : PCI_COMMAND_MASTER_ENABLE,
132 : XL_CARDBUS_CYCLONE },
133 :
134 : { PCI_PRODUCT_3COM_3CCFEM656B,
135 : XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
136 : XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
137 : PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
138 : PCI_COMMAND_MASTER_ENABLE,
139 : XL_CARDBUS_CYCLONE },
140 :
141 : { PCI_PRODUCT_3COM_3CCFEM656C,
142 : XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
143 : XL_FLAG_INVERT_MII_PWR,
144 : PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
145 : PCI_COMMAND_MASTER_ENABLE,
146 : XL_CARDBUS_CYCLONE },
147 :
148 : { 0,
149 : 0,
150 : 0,
151 : 0 },
152 : };
153 :
154 : const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *);
155 :
156 : const struct xl_cardbus_product *
157 0 : xl_cardbus_lookup(const struct cardbus_attach_args *ca)
158 : {
159 : const struct xl_cardbus_product *ecp;
160 :
161 0 : if (PCI_VENDOR(ca->ca_id) != PCI_VENDOR_3COM)
162 0 : return (NULL);
163 :
164 0 : for (ecp = xl_cardbus_products; ecp->ecp_prodid != 0; ecp++)
165 0 : if (PCI_PRODUCT(ca->ca_id) == ecp->ecp_prodid)
166 0 : return (ecp);
167 0 : return (NULL);
168 0 : }
169 :
170 : int
171 0 : xl_cardbus_match(struct device *parent, void *match, void *aux)
172 : {
173 0 : struct cardbus_attach_args *ca = aux;
174 :
175 0 : if (xl_cardbus_lookup(ca) != NULL)
176 0 : return (1);
177 :
178 0 : return (0);
179 0 : }
180 :
181 : void
182 0 : xl_cardbus_attach(struct device *parent, struct device *self, void *aux)
183 : {
184 0 : struct xl_cardbus_softc *csc = (void *)self;
185 0 : struct xl_softc *sc = &csc->sc_softc;
186 0 : struct cardbus_attach_args *ca = aux;
187 0 : cardbus_devfunc_t ct = ca->ca_ct;
188 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
189 0 : cardbus_function_tag_t cf = ct->ct_cf;
190 : pcireg_t command, bhlc;
191 : const struct xl_cardbus_product *ecp;
192 0 : bus_space_handle_t ioh;
193 0 : bus_addr_t adr;
194 :
195 0 : if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, PCI_MAPREG_TYPE_IO, 0,
196 : &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) {
197 0 : printf(": can't map i/o space\n");
198 0 : return;
199 : }
200 :
201 0 : ecp = xl_cardbus_lookup(ca);
202 0 : if (ecp == NULL) {
203 0 : printf("\n");
204 0 : panic("xl_cardbus_attach: impossible");
205 : }
206 :
207 0 : sc->xl_flags = ecp->ecp_flags;
208 0 : sc->sc_dmat = ca->ca_dmat;
209 :
210 0 : sc->xl_bhandle = ioh;
211 :
212 0 : (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
213 :
214 0 : command = pci_conf_read(ca->ca_pc, ca->ca_tag,
215 : PCI_COMMAND_STATUS_REG);
216 0 : command |= ecp->ecp_csr;
217 0 : csc->sc_cardtype = ecp->ecp_cardtype;
218 :
219 0 : if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
220 : /* map CardBus function status window */
221 0 : if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG,
222 : PCI_MAPREG_TYPE_MEM, 0, &csc->sc_funct,
223 : &csc->sc_funch, 0, &csc->sc_funcsize)) {
224 0 : printf("%s: unable to map function status window\n",
225 0 : self->dv_xname);
226 0 : return;
227 : }
228 :
229 : /*
230 : * Make sure CardBus bridge can access memory space. Usually
231 : * memory access is enabled by BIOS, but some BIOSes do not
232 : * enable it.
233 : */
234 0 : (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
235 0 : }
236 :
237 0 : (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
238 0 : pci_conf_write(ca->ca_pc, ca->ca_tag, PCI_COMMAND_STATUS_REG,
239 : command);
240 :
241 : /*
242 : * set latency timer
243 : */
244 0 : bhlc = pci_conf_read(ca->ca_pc, ca->ca_tag, PCI_BHLC_REG);
245 0 : if (PCI_LATTIMER(bhlc) < 0x20) {
246 : /* at least the value of latency timer should 0x20. */
247 : DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n",
248 : PCI_LATTIMER(bhlc)));
249 0 : bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
250 0 : bhlc |= (0x20 << PCI_LATTIMER_SHIFT);
251 0 : pci_conf_write(ca->ca_pc, ca->ca_tag, PCI_BHLC_REG, bhlc);
252 0 : }
253 :
254 0 : csc->sc_ct = ca->ca_ct;
255 0 : csc->sc_intrline = ca->ca_intrline;
256 :
257 : /* Map and establish the interrupt. */
258 :
259 0 : sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline,
260 0 : IPL_NET, xl_intr, csc, self->dv_xname);
261 :
262 0 : if (sc->xl_intrhand == NULL) {
263 0 : printf(": couldn't establish interrupt");
264 0 : printf(" at %d", ca->ca_intrline);
265 0 : printf("\n");
266 0 : return;
267 : }
268 0 : printf(": irq %d", ca->ca_intrline);
269 :
270 0 : sc->intr_ack = xl_cardbus_intr_ack;
271 :
272 0 : xl_attach(sc);
273 :
274 0 : if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
275 0 : bus_space_write_4(csc->sc_funct, csc->sc_funch,
276 : XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK);
277 :
278 0 : }
279 :
280 : int
281 0 : xl_cardbus_detach(struct device *self, int arg)
282 : {
283 0 : struct xl_cardbus_softc *csc = (void *)self;
284 0 : struct xl_softc *sc = &csc->sc_softc;
285 0 : struct cardbus_devfunc *ct = csc->sc_ct;
286 :
287 0 : cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf,
288 0 : sc->xl_intrhand);
289 0 : xl_detach(sc);
290 0 : if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
291 0 : Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG,
292 : csc->sc_funct, csc->sc_funch, csc->sc_funcsize);
293 0 : Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag,
294 : sc->xl_bhandle, csc->sc_mapsize);
295 0 : return (0);
296 : }
297 :
298 : void
299 0 : xl_cardbus_intr_ack(struct xl_softc *sc)
300 : {
301 0 : struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc;
302 :
303 0 : bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR,
304 : XL_CARDBUS_INTR_ACK);
305 0 : }
|