if_rtk_cardbus.c revision 1.3.6.2 1 1.3.6.2 bouyer /* $NetBSD: if_rtk_cardbus.c,v 1.3.6.2 2000/11/20 11:39:54 bouyer Exp $ */
2 1.3.6.2 bouyer
3 1.3.6.2 bouyer /*
4 1.3.6.2 bouyer * Copyright (c) 2000 Masanori Kanaoka
5 1.3.6.2 bouyer * All rights reserved.
6 1.3.6.2 bouyer *
7 1.3.6.2 bouyer * Redistribution and use in source and binary forms, with or without
8 1.3.6.2 bouyer * modification, are permitted provided that the following conditions
9 1.3.6.2 bouyer * are met:
10 1.3.6.2 bouyer * 1. Redistributions of source code must retain the above copyright
11 1.3.6.2 bouyer * notice, this list of conditions and the following disclaimer.
12 1.3.6.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
13 1.3.6.2 bouyer * notice, this list of conditions and the following disclaimer in the
14 1.3.6.2 bouyer * documentation and/or other materials provided with the distribution.
15 1.3.6.2 bouyer * 3. The name of the author may not be used to endorse or promote products
16 1.3.6.2 bouyer * derived from this software without specific prior written permission.
17 1.3.6.2 bouyer *
18 1.3.6.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.3.6.2 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.3.6.2 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.3.6.2 bouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.3.6.2 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.3.6.2 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.3.6.2 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.3.6.2 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.3.6.2 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 1.3.6.2 bouyer * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.3.6.2 bouyer */
29 1.3.6.2 bouyer
30 1.3.6.2 bouyer /*
31 1.3.6.2 bouyer * if_rtk_cardbus.c:
32 1.3.6.2 bouyer * Cardbus specific routines for RealTek 8139 ethernet adapter.
33 1.3.6.2 bouyer * Tested for
34 1.3.6.2 bouyer * - elecom-Laneed LD-10/100CBA (Accton MPX5030)
35 1.3.6.2 bouyer * - MELCO LPC3-TX-CB (RealTek 8139)
36 1.3.6.2 bouyer */
37 1.3.6.2 bouyer
38 1.3.6.2 bouyer #include "opt_inet.h"
39 1.3.6.2 bouyer #include "opt_ns.h"
40 1.3.6.2 bouyer #include "bpfilter.h"
41 1.3.6.2 bouyer #include "rnd.h"
42 1.3.6.2 bouyer
43 1.3.6.2 bouyer #include <sys/param.h>
44 1.3.6.2 bouyer #include <sys/systm.h>
45 1.3.6.2 bouyer #include <sys/callout.h>
46 1.3.6.2 bouyer #include <sys/device.h>
47 1.3.6.2 bouyer #include <sys/sockio.h>
48 1.3.6.2 bouyer #include <sys/mbuf.h>
49 1.3.6.2 bouyer #include <sys/malloc.h>
50 1.3.6.2 bouyer #include <sys/kernel.h>
51 1.3.6.2 bouyer #include <sys/socket.h>
52 1.3.6.2 bouyer
53 1.3.6.2 bouyer #include <net/if.h>
54 1.3.6.2 bouyer #include <net/if_arp.h>
55 1.3.6.2 bouyer #include <net/if_ether.h>
56 1.3.6.2 bouyer #include <net/if_dl.h>
57 1.3.6.2 bouyer #include <net/if_media.h>
58 1.3.6.2 bouyer #ifdef INET
59 1.3.6.2 bouyer #include <netinet/in.h>
60 1.3.6.2 bouyer #include <netinet/if_inarp.h>
61 1.3.6.2 bouyer #endif
62 1.3.6.2 bouyer #ifdef NS
63 1.3.6.2 bouyer #include <netns/ns.h>
64 1.3.6.2 bouyer #include <netns/ns_if.h>
65 1.3.6.2 bouyer #endif
66 1.3.6.2 bouyer
67 1.3.6.2 bouyer #if NBPFILTER > 0
68 1.3.6.2 bouyer #include <net/bpf.h>
69 1.3.6.2 bouyer #endif
70 1.3.6.2 bouyer #if NRND > 0
71 1.3.6.2 bouyer #include <sys/rnd.h>
72 1.3.6.2 bouyer #endif
73 1.3.6.2 bouyer
74 1.3.6.2 bouyer #include <machine/bus.h>
75 1.3.6.2 bouyer
76 1.3.6.2 bouyer #include <dev/pci/pcireg.h>
77 1.3.6.2 bouyer #include <dev/pci/pcivar.h>
78 1.3.6.2 bouyer #include <dev/pci/pcidevs.h>
79 1.3.6.2 bouyer
80 1.3.6.2 bouyer #include <dev/cardbus/cardbusvar.h>
81 1.3.6.2 bouyer #include <dev/cardbus/cardbusdevs.h>
82 1.3.6.2 bouyer
83 1.3.6.2 bouyer #include <dev/mii/mii.h>
84 1.3.6.2 bouyer #include <dev/mii/miivar.h>
85 1.3.6.2 bouyer
86 1.3.6.2 bouyer /*
87 1.3.6.2 bouyer * Default to using PIO access for this driver. On SMP systems,
88 1.3.6.2 bouyer * there appear to be problems with memory mapped mode: it looks like
89 1.3.6.2 bouyer * doing too many memory mapped access back to back in rapid succession
90 1.3.6.2 bouyer * can hang the bus. I'm inclined to blame this on crummy design/construction
91 1.3.6.2 bouyer * on the part of RealTek. Memory mapped mode does appear to work on
92 1.3.6.2 bouyer * uniprocessor systems though.
93 1.3.6.2 bouyer */
94 1.3.6.2 bouyer #define RTK_USEIOSPACE
95 1.3.6.2 bouyer
96 1.3.6.2 bouyer #include <dev/ic/rtl81x9reg.h>
97 1.3.6.2 bouyer #include <dev/ic/rtl81x9var.h>
98 1.3.6.2 bouyer
99 1.3.6.2 bouyer /*
100 1.3.6.2 bouyer * Various supported device vendors/types and their names.
101 1.3.6.2 bouyer */
102 1.3.6.2 bouyer static const struct rtk_type rtk_cardbus_devs[] = {
103 1.3.6.2 bouyer { CARDBUS_VENDOR_ACCTON, CARDBUS_PRODUCT_ACCTON_MPX5030,
104 1.3.6.2 bouyer "Accton MPX 5030/5038 10/100BaseTX",
105 1.3.6.2 bouyer RTK_8139 },
106 1.3.6.2 bouyer { CARDBUS_VENDOR_REALTEK, CARDBUS_PRODUCT_REALTEK_RT8138,
107 1.3.6.2 bouyer "RealTek 8138 10/100BaseTX", RTK_8139 },
108 1.3.6.2 bouyer { 0, 0, NULL, 0 }
109 1.3.6.2 bouyer };
110 1.3.6.2 bouyer
111 1.3.6.2 bouyer static int rtk_cardbus_match __P((struct device *, struct cfdata *, void *));
112 1.3.6.2 bouyer static void rtk_cardbus_attach __P((struct device *, struct device *, void *));
113 1.3.6.2 bouyer static int rtk_cardbus_detach __P((struct device *, int));
114 1.3.6.2 bouyer
115 1.3.6.2 bouyer struct rtk_cardbus_softc {
116 1.3.6.2 bouyer struct rtk_softc sc_rtk; /* real rtk softc */
117 1.3.6.2 bouyer
118 1.3.6.2 bouyer /* CardBus-specific goo. */
119 1.3.6.2 bouyer void *sc_ih;
120 1.3.6.2 bouyer cardbus_devfunc_t sc_ct;
121 1.3.6.2 bouyer cardbustag_t sc_tag;
122 1.3.6.2 bouyer int sc_csr;
123 1.3.6.2 bouyer int sc_cben;
124 1.3.6.2 bouyer int sc_bar_reg;
125 1.3.6.2 bouyer pcireg_t sc_bar_val;
126 1.3.6.2 bouyer bus_size_t sc_mapsize;
127 1.3.6.2 bouyer int sc_intrline;
128 1.3.6.2 bouyer };
129 1.3.6.2 bouyer
130 1.3.6.2 bouyer struct cfattach rtk_cardbus_ca = {
131 1.3.6.2 bouyer sizeof(struct rtk_cardbus_softc),
132 1.3.6.2 bouyer rtk_cardbus_match, rtk_cardbus_attach,
133 1.3.6.2 bouyer rtk_cardbus_detach, rtk_activate,
134 1.3.6.2 bouyer };
135 1.3.6.2 bouyer
136 1.3.6.2 bouyer const struct rtk_type *rtk_cardbus_lookup
137 1.3.6.2 bouyer __P((const struct cardbus_attach_args *));
138 1.3.6.2 bouyer
139 1.3.6.2 bouyer void rtk_cardbus_setup __P((struct rtk_cardbus_softc *));
140 1.3.6.2 bouyer
141 1.3.6.2 bouyer int rtk_cardbus_enable __P((struct rtk_softc *));
142 1.3.6.2 bouyer void rtk_cardbus_disable __P((struct rtk_softc *));
143 1.3.6.2 bouyer void rtk_cardbus_power __P((struct rtk_softc *, int));
144 1.3.6.2 bouyer const struct rtk_type *
145 1.3.6.2 bouyer rtk_cardbus_lookup(ca)
146 1.3.6.2 bouyer const struct cardbus_attach_args *ca;
147 1.3.6.2 bouyer {
148 1.3.6.2 bouyer const struct rtk_type *t;
149 1.3.6.2 bouyer
150 1.3.6.2 bouyer for (t = rtk_cardbus_devs; t->rtk_name != NULL; t++){
151 1.3.6.2 bouyer if (CARDBUS_VENDOR(ca->ca_id) == t->rtk_vid &&
152 1.3.6.2 bouyer CARDBUS_PRODUCT(ca->ca_id) == t->rtk_did) {
153 1.3.6.2 bouyer return (t);
154 1.3.6.2 bouyer }
155 1.3.6.2 bouyer }
156 1.3.6.2 bouyer return (NULL);
157 1.3.6.2 bouyer }
158 1.3.6.2 bouyer
159 1.3.6.2 bouyer int
160 1.3.6.2 bouyer rtk_cardbus_match(parent, match, aux)
161 1.3.6.2 bouyer struct device *parent;
162 1.3.6.2 bouyer struct cfdata *match;
163 1.3.6.2 bouyer void *aux;
164 1.3.6.2 bouyer {
165 1.3.6.2 bouyer struct cardbus_attach_args *ca = aux;
166 1.3.6.2 bouyer
167 1.3.6.2 bouyer if (rtk_cardbus_lookup(ca) != NULL)
168 1.3.6.2 bouyer return (1);
169 1.3.6.2 bouyer
170 1.3.6.2 bouyer return (0);
171 1.3.6.2 bouyer }
172 1.3.6.2 bouyer
173 1.3.6.2 bouyer
174 1.3.6.2 bouyer void
175 1.3.6.2 bouyer rtk_cardbus_attach(parent, self, aux)
176 1.3.6.2 bouyer struct device *parent, *self;
177 1.3.6.2 bouyer void *aux;
178 1.3.6.2 bouyer {
179 1.3.6.2 bouyer struct rtk_cardbus_softc *csc = (struct rtk_cardbus_softc *)self;
180 1.3.6.2 bouyer struct rtk_softc *sc = &csc->sc_rtk;
181 1.3.6.2 bouyer struct cardbus_attach_args *ca = aux;
182 1.3.6.2 bouyer cardbus_devfunc_t ct = ca->ca_ct;
183 1.3.6.2 bouyer const struct rtk_type *t;
184 1.3.6.2 bouyer bus_addr_t adr;
185 1.3.6.2 bouyer
186 1.3.6.2 bouyer sc->sc_dmat = ca->ca_dmat;
187 1.3.6.2 bouyer csc->sc_ct = ct;
188 1.3.6.2 bouyer csc->sc_tag = ca->ca_tag;
189 1.3.6.2 bouyer csc->sc_intrline = ca->ca_intrline;
190 1.3.6.2 bouyer
191 1.3.6.2 bouyer t = rtk_cardbus_lookup(ca);
192 1.3.6.2 bouyer if (t == NULL) {
193 1.3.6.2 bouyer printf("\n");
194 1.3.6.2 bouyer panic("rtk_cardbus_attach: impossible");
195 1.3.6.2 bouyer }
196 1.3.6.2 bouyer printf(": %s\n", t->rtk_name);
197 1.3.6.2 bouyer
198 1.3.6.2 bouyer /*
199 1.3.6.2 bouyer * Power management hooks.
200 1.3.6.2 bouyer */
201 1.3.6.2 bouyer sc->sc_enable = rtk_cardbus_enable;
202 1.3.6.2 bouyer sc->sc_disable = rtk_cardbus_disable;
203 1.3.6.2 bouyer sc->sc_power = rtk_cardbus_power;
204 1.3.6.2 bouyer
205 1.3.6.2 bouyer /*
206 1.3.6.2 bouyer * Map control/status registers.
207 1.3.6.2 bouyer */
208 1.3.6.2 bouyer csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
209 1.3.6.2 bouyer #ifdef RTK_USEIOSPACE
210 1.3.6.2 bouyer if (Cardbus_mapreg_map(ct, RTK_PCI_LOIO, CARDBUS_MAPREG_TYPE_IO, 0,
211 1.3.6.2 bouyer &sc->rtk_btag, &sc->rtk_bhandle, &adr, &csc->sc_mapsize) == 0) {
212 1.3.6.2 bouyer #if rbus
213 1.3.6.2 bouyer #else
214 1.3.6.2 bouyer (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
215 1.3.6.2 bouyer #endif
216 1.3.6.2 bouyer csc->sc_cben = CARDBUS_IO_ENABLE;
217 1.3.6.2 bouyer csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
218 1.3.6.2 bouyer csc->sc_bar_reg = RTK_PCI_LOIO;
219 1.3.6.2 bouyer csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
220 1.3.6.2 bouyer }
221 1.3.6.2 bouyer #else
222 1.3.6.2 bouyer if (Cardbus_mapreg_map(ct, RTK_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
223 1.3.6.2 bouyer &sc->rtk_btag, &sc->rtk_bhandle, &adr, &csc->sc_mapsize) == 0) {
224 1.3.6.2 bouyer #if rbus
225 1.3.6.2 bouyer #else
226 1.3.6.2 bouyer (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
227 1.3.6.2 bouyer #endif
228 1.3.6.2 bouyer csc->sc_cben = CARDBUS_MEM_ENABLE;
229 1.3.6.2 bouyer csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
230 1.3.6.2 bouyer csc->sc_bar_reg = RTK_PCI_LOMEM;
231 1.3.6.2 bouyer csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
232 1.3.6.2 bouyer }
233 1.3.6.2 bouyer #endif
234 1.3.6.2 bouyer else {
235 1.3.6.2 bouyer printf("%s: unable to map deviceregisters\n",
236 1.3.6.2 bouyer sc->sc_dev.dv_xname);
237 1.3.6.2 bouyer return;
238 1.3.6.2 bouyer }
239 1.3.6.2 bouyer /*
240 1.3.6.2 bouyer * Handle power management nonsense and initialize the
241 1.3.6.2 bouyer * configuration registers.
242 1.3.6.2 bouyer */
243 1.3.6.2 bouyer rtk_cardbus_setup(csc);
244 1.3.6.2 bouyer sc->rtk_type = t->rtk_type;
245 1.3.6.2 bouyer
246 1.3.6.2 bouyer rtk_attach(sc);
247 1.3.6.2 bouyer
248 1.3.6.2 bouyer /*
249 1.3.6.2 bouyer * Power down the socket.
250 1.3.6.2 bouyer */
251 1.3.6.2 bouyer Cardbus_function_disable(csc->sc_ct);
252 1.3.6.2 bouyer }
253 1.3.6.2 bouyer
254 1.3.6.2 bouyer int
255 1.3.6.2 bouyer rtk_cardbus_detach(self, flags)
256 1.3.6.2 bouyer struct device *self;
257 1.3.6.2 bouyer int flags;
258 1.3.6.2 bouyer {
259 1.3.6.2 bouyer struct rtk_cardbus_softc *csc = (void *) self;
260 1.3.6.2 bouyer struct rtk_softc *sc = &csc->sc_rtk;
261 1.3.6.2 bouyer struct cardbus_devfunc *ct = csc->sc_ct;
262 1.3.6.2 bouyer int rv;
263 1.3.6.2 bouyer
264 1.3.6.2 bouyer #ifdef DIAGNOSTIC
265 1.3.6.2 bouyer if (ct == NULL)
266 1.3.6.2 bouyer panic("%s: data structure lacks\n", sc->sc_dev.dv_xname);
267 1.3.6.2 bouyer #endif
268 1.3.6.2 bouyer rv = rtk_detach(sc);
269 1.3.6.2 bouyer if (rv)
270 1.3.6.2 bouyer return (rv);
271 1.3.6.2 bouyer /*
272 1.3.6.2 bouyer * Unhook the interrut handler.
273 1.3.6.2 bouyer */
274 1.3.6.2 bouyer if (csc->sc_ih != NULL)
275 1.3.6.2 bouyer cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
276 1.3.6.2 bouyer
277 1.3.6.2 bouyer /*
278 1.3.6.2 bouyer * Release bus space and close window.
279 1.3.6.2 bouyer */
280 1.3.6.2 bouyer if (csc->sc_bar_reg != 0)
281 1.3.6.2 bouyer Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
282 1.3.6.2 bouyer sc->rtk_btag, sc->rtk_bhandle, csc->sc_mapsize);
283 1.3.6.2 bouyer
284 1.3.6.2 bouyer return (0);
285 1.3.6.2 bouyer }
286 1.3.6.2 bouyer
287 1.3.6.2 bouyer void
288 1.3.6.2 bouyer rtk_cardbus_setup(csc)
289 1.3.6.2 bouyer struct rtk_cardbus_softc *csc;
290 1.3.6.2 bouyer {
291 1.3.6.2 bouyer struct rtk_softc *sc = &csc->sc_rtk;
292 1.3.6.2 bouyer cardbus_devfunc_t ct = csc->sc_ct;
293 1.3.6.2 bouyer cardbus_chipset_tag_t cc = ct->ct_cc;
294 1.3.6.2 bouyer cardbus_function_tag_t cf = ct->ct_cf;
295 1.3.6.2 bouyer pcireg_t reg,command;
296 1.3.6.2 bouyer int pmreg;
297 1.3.6.2 bouyer
298 1.3.6.2 bouyer /*
299 1.3.6.2 bouyer * Handle power management nonsense.
300 1.3.6.2 bouyer */
301 1.3.6.2 bouyer if (cardbus_get_capability(cc, cf, csc->sc_tag,
302 1.3.6.2 bouyer PCI_CAP_PWRMGMT, &pmreg, 0)) {
303 1.3.6.2 bouyer command = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4);
304 1.3.6.2 bouyer if (command & RTK_PSTATE_MASK) {
305 1.3.6.2 bouyer pcireg_t iobase, membase, irq;
306 1.3.6.2 bouyer
307 1.3.6.2 bouyer /* Save important PCI config data. */
308 1.3.6.2 bouyer iobase = cardbus_conf_read(cc, cf, csc->sc_tag,
309 1.3.6.2 bouyer RTK_PCI_LOIO);
310 1.3.6.2 bouyer membase = cardbus_conf_read(cc, cf,csc->sc_tag,
311 1.3.6.2 bouyer RTK_PCI_LOMEM);
312 1.3.6.2 bouyer irq = cardbus_conf_read(cc, cf,csc->sc_tag,
313 1.3.6.2 bouyer PCI_PRODUCT_DELTA_8139);
314 1.3.6.2 bouyer
315 1.3.6.2 bouyer /* Reset the power state. */
316 1.3.6.2 bouyer printf("%s: chip is is in D%d power mode "
317 1.3.6.2 bouyer "-- setting to D0\n", sc->sc_dev.dv_xname,
318 1.3.6.2 bouyer command & RTK_PSTATE_MASK);
319 1.3.6.2 bouyer command &= 0xFFFFFFFC;
320 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag,
321 1.3.6.2 bouyer pmreg + 4, command);
322 1.3.6.2 bouyer
323 1.3.6.2 bouyer /* Restore PCI config data. */
324 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag,
325 1.3.6.2 bouyer RTK_PCI_LOIO, iobase);
326 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag,
327 1.3.6.2 bouyer RTK_PCI_LOMEM, membase);
328 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag,
329 1.3.6.2 bouyer PCI_PRODUCT_DELTA_8139, irq);
330 1.3.6.2 bouyer }
331 1.3.6.2 bouyer }
332 1.3.6.2 bouyer
333 1.3.6.2 bouyer /* Make sure the right access type is on the CardBus bridge. */
334 1.3.6.2 bouyer (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
335 1.3.6.2 bouyer (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
336 1.3.6.2 bouyer
337 1.3.6.2 bouyer /* Program the BAR */
338 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag,
339 1.3.6.2 bouyer csc->sc_bar_reg, csc->sc_bar_val);
340 1.3.6.2 bouyer
341 1.3.6.2 bouyer /* Enable the appropriate bits in the CARDBUS CSR. */
342 1.3.6.2 bouyer reg = cardbus_conf_read(cc, cf, csc->sc_tag,
343 1.3.6.2 bouyer CARDBUS_COMMAND_STATUS_REG);
344 1.3.6.2 bouyer reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
345 1.3.6.2 bouyer reg |= csc->sc_csr;
346 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag,
347 1.3.6.2 bouyer CARDBUS_COMMAND_STATUS_REG, reg);
348 1.3.6.2 bouyer
349 1.3.6.2 bouyer /*
350 1.3.6.2 bouyer * Make sure the latency timer is set to some reasonable
351 1.3.6.2 bouyer * value.
352 1.3.6.2 bouyer */
353 1.3.6.2 bouyer reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
354 1.3.6.2 bouyer if (CARDBUS_LATTIMER(reg) < 0x20) {
355 1.3.6.2 bouyer reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
356 1.3.6.2 bouyer reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
357 1.3.6.2 bouyer cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
358 1.3.6.2 bouyer }
359 1.3.6.2 bouyer }
360 1.3.6.2 bouyer
361 1.3.6.2 bouyer int
362 1.3.6.2 bouyer rtk_cardbus_enable(sc)
363 1.3.6.2 bouyer struct rtk_softc *sc;
364 1.3.6.2 bouyer {
365 1.3.6.2 bouyer struct rtk_cardbus_softc *csc = (void *) sc;
366 1.3.6.2 bouyer cardbus_devfunc_t ct = csc->sc_ct;
367 1.3.6.2 bouyer cardbus_chipset_tag_t cc = ct->ct_cc;
368 1.3.6.2 bouyer cardbus_function_tag_t cf = ct->ct_cf;
369 1.3.6.2 bouyer
370 1.3.6.2 bouyer /*
371 1.3.6.2 bouyer * Power on the socket.
372 1.3.6.2 bouyer */
373 1.3.6.2 bouyer Cardbus_function_enable(ct);
374 1.3.6.2 bouyer
375 1.3.6.2 bouyer /*
376 1.3.6.2 bouyer * Set up the PCI configuration registers.
377 1.3.6.2 bouyer */
378 1.3.6.2 bouyer rtk_cardbus_setup(csc);
379 1.3.6.2 bouyer
380 1.3.6.2 bouyer /*
381 1.3.6.2 bouyer * Map and establish the interrupt.
382 1.3.6.2 bouyer */
383 1.3.6.2 bouyer csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline,
384 1.3.6.2 bouyer IPL_NET, rtk_intr, sc);
385 1.3.6.2 bouyer if (csc->sc_ih == NULL) {
386 1.3.6.2 bouyer printf("%s: unable to establish interrupt at %d\n",
387 1.3.6.2 bouyer sc->sc_dev.dv_xname, csc->sc_intrline);
388 1.3.6.2 bouyer Cardbus_function_disable(csc->sc_ct);
389 1.3.6.2 bouyer return (1);
390 1.3.6.2 bouyer }
391 1.3.6.2 bouyer printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
392 1.3.6.2 bouyer csc->sc_intrline);
393 1.3.6.2 bouyer return (0);
394 1.3.6.2 bouyer }
395 1.3.6.2 bouyer
396 1.3.6.2 bouyer void
397 1.3.6.2 bouyer rtk_cardbus_disable(sc)
398 1.3.6.2 bouyer struct rtk_softc *sc;
399 1.3.6.2 bouyer {
400 1.3.6.2 bouyer struct rtk_cardbus_softc *csc = (void *) sc;
401 1.3.6.2 bouyer cardbus_devfunc_t ct = csc->sc_ct;
402 1.3.6.2 bouyer cardbus_chipset_tag_t cc = ct->ct_cc;
403 1.3.6.2 bouyer cardbus_function_tag_t cf = ct->ct_cf;
404 1.3.6.2 bouyer
405 1.3.6.2 bouyer /* Unhook the interrupt handler. */
406 1.3.6.2 bouyer cardbus_intr_disestablish(cc, cf, csc->sc_ih);
407 1.3.6.2 bouyer
408 1.3.6.2 bouyer /* Power down the socket. */
409 1.3.6.2 bouyer Cardbus_function_disable(ct);
410 1.3.6.2 bouyer }
411 1.3.6.2 bouyer
412 1.3.6.2 bouyer void
413 1.3.6.2 bouyer rtk_cardbus_power(sc, why)
414 1.3.6.2 bouyer struct rtk_softc *sc;
415 1.3.6.2 bouyer int why;
416 1.3.6.2 bouyer {
417 1.3.6.2 bouyer struct rtk_cardbus_softc *csc = (void *) sc;
418 1.3.6.2 bouyer
419 1.3.6.2 bouyer if (why == PWR_RESUME) {
420 1.3.6.2 bouyer /*
421 1.3.6.2 bouyer * Give the PCI configuration registers a kick
422 1.3.6.2 bouyer * in the head.
423 1.3.6.2 bouyer */
424 1.3.6.2 bouyer #ifdef DIAGNOSTIC
425 1.3.6.2 bouyer if (RTK_IS_ENABLED(sc) == 0)
426 1.3.6.2 bouyer panic("rtk_cardbus_power");
427 1.3.6.2 bouyer #endif
428 1.3.6.2 bouyer rtk_cardbus_setup(csc);
429 1.3.6.2 bouyer }
430 1.3.6.2 bouyer }
431