Deleted Added
full compact
pccard.c (90187) pccard.c (90436)
1/* $NetBSD: pcmcia.c,v 1.23 2000/07/28 19:17:02 drochner Exp $ */
1/* $NetBSD: pcmcia.c,v 1.23 2000/07/28 19:17:02 drochner Exp $ */
2/* $FreeBSD: head/sys/dev/pccard/pccard.c 90187 2002-02-04 15:55:21Z imp $ */
2/* $FreeBSD: head/sys/dev/pccard/pccard.c 90436 2002-02-09 21:34:06Z imp $ */
3
4/*
5 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Marc Horowitz.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/kernel.h>
38#include <sys/queue.h>
39#include <sys/types.h>
40
41#include <sys/bus.h>
42#include <machine/bus.h>
43#include <sys/rman.h>
44#include <machine/resource.h>
45
46#include <net/ethernet.h>
47
48#include <dev/pccard/pccardreg.h>
49#include <dev/pccard/pccardvar.h>
50
51#include "power_if.h"
52#include "card_if.h"
53
54#define PCCARDDEBUG
55
56#ifdef PCCARDDEBUG
57int pccard_debug = 0;
58#define DPRINTF(arg) if (pccard_debug) printf arg
59#define DEVPRINTF(arg) if (pccard_debug) device_printf arg
60#define PRVERBOSE(arg) printf arg
61#define DEVPRVERBOSE(arg) device_printf arg
62#else
63#define DPRINTF(arg)
64#define DEVPRINTF(arg)
65#define PRVERBOSE(arg) if (bootverbose) printf arg
66#define DEVPRVERBOSE(arg) if (bootverbose) device_printf arg
67#endif
68
3
4/*
5 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Marc Horowitz.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/kernel.h>
38#include <sys/queue.h>
39#include <sys/types.h>
40
41#include <sys/bus.h>
42#include <machine/bus.h>
43#include <sys/rman.h>
44#include <machine/resource.h>
45
46#include <net/ethernet.h>
47
48#include <dev/pccard/pccardreg.h>
49#include <dev/pccard/pccardvar.h>
50
51#include "power_if.h"
52#include "card_if.h"
53
54#define PCCARDDEBUG
55
56#ifdef PCCARDDEBUG
57int pccard_debug = 0;
58#define DPRINTF(arg) if (pccard_debug) printf arg
59#define DEVPRINTF(arg) if (pccard_debug) device_printf arg
60#define PRVERBOSE(arg) printf arg
61#define DEVPRVERBOSE(arg) device_printf arg
62#else
63#define DPRINTF(arg)
64#define DEVPRINTF(arg)
65#define PRVERBOSE(arg) if (bootverbose) printf arg
66#define DEVPRVERBOSE(arg) if (bootverbose) device_printf arg
67#endif
68
69#ifdef PCCARDVERBOSE
70int pccard_verbose = 1;
71#else
72int pccard_verbose = 0;
73#endif
74
75static int pccard_ccr_read(struct pccard_function *pf, int ccr);
76static void pccard_ccr_write(struct pccard_function *pf, int ccr, int val);
77static int pccard_attach_card(device_t dev);
78static int pccard_detach_card(device_t dev, int flags);
79static int pccard_card_gettype(device_t dev, int *type);
80static void pccard_function_init(struct pccard_function *pf);
81static void pccard_function_free(struct pccard_function *pf);
82static int pccard_function_enable(struct pccard_function *pf);
83static void pccard_function_disable(struct pccard_function *pf);
84static int pccard_compat_do_probe(device_t bus, device_t dev);
85static int pccard_compat_do_attach(device_t bus, device_t dev);
86static int pccard_add_children(device_t dev, int busno);
87static int pccard_probe(device_t dev);
88static int pccard_attach(device_t dev);
89static int pccard_detach(device_t dev);
90static void pccard_print_resources(struct resource_list *rl,
91 const char *name, int type, int count, const char *format);
92static int pccard_print_child(device_t dev, device_t child);
93static int pccard_set_resource(device_t dev, device_t child, int type,
94 int rid, u_long start, u_long count);
95static int pccard_get_resource(device_t dev, device_t child, int type,
96 int rid, u_long *startp, u_long *countp);
97static void pccard_delete_resource(device_t dev, device_t child, int type,
98 int rid);
99static int pccard_set_res_flags(device_t dev, device_t child, int type,
100 int rid, u_int32_t flags);
101static int pccard_set_memory_offset(device_t dev, device_t child, int rid,
102 u_int32_t offset, u_int32_t *deltap);
103static int pccard_read_ivar(device_t bus, device_t child, int which,
104 u_char *result);
105static void pccard_driver_added(device_t dev, driver_t *driver);
106static struct resource *pccard_alloc_resource(device_t dev,
107 device_t child, int type, int *rid, u_long start,
108 u_long end, u_long count, u_int flags);
109static int pccard_release_resource(device_t dev, device_t child, int type,
110 int rid, struct resource *r);
111static void pccard_child_detached(device_t parent, device_t dev);
112static void pccard_intr(void *arg);
113static int pccard_setup_intr(device_t dev, device_t child,
114 struct resource *irq, int flags, driver_intr_t *intr,
115 void *arg, void **cookiep);
116static int pccard_teardown_intr(device_t dev, device_t child,
117 struct resource *r, void *cookie);
118
119static int
120pccard_ccr_read(struct pccard_function *pf, int ccr)
121{
122 return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
123 pf->pf_ccr_offset + ccr));
124}
125
126static void
127pccard_ccr_write(struct pccard_function *pf, int ccr, int val)
128{
129 if ((pf->ccr_mask) & (1 << (ccr / 2))) {
130 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
131 pf->pf_ccr_offset + ccr, val);
132 }
133}
134
135static int
136pccard_attach_card(device_t dev)
137{
138 struct pccard_softc *sc = PCCARD_SOFTC(dev);
139 struct pccard_function *pf;
140 struct pccard_ivar *ivar;
141 device_t child;
142
143 /*
144 * this is here so that when socket_enable calls gettype, trt happens
145 */
146 STAILQ_INIT(&sc->card.pf_head);
147
148 DEVPRINTF((dev, "chip_socket_enable\n"));
149 POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
150
151 DEVPRINTF((dev, "read_cis\n"));
152 pccard_read_cis(sc);
153
154 DEVPRINTF((dev, "check_cis_quirks\n"));
155 pccard_check_cis_quirks(dev);
156
157 /*
158 * bail now if the card has no functions, or if there was an error in
159 * the cis.
160 */
161
162 if (sc->card.error) {
163 device_printf (dev, "CARD ERROR!\n");
164 return (1);
165 }
166 if (STAILQ_EMPTY(&sc->card.pf_head)) {
167 device_printf (dev, "Card has no functions!\n");
168 return (1);
169 }
170
69static int pccard_ccr_read(struct pccard_function *pf, int ccr);
70static void pccard_ccr_write(struct pccard_function *pf, int ccr, int val);
71static int pccard_attach_card(device_t dev);
72static int pccard_detach_card(device_t dev, int flags);
73static int pccard_card_gettype(device_t dev, int *type);
74static void pccard_function_init(struct pccard_function *pf);
75static void pccard_function_free(struct pccard_function *pf);
76static int pccard_function_enable(struct pccard_function *pf);
77static void pccard_function_disable(struct pccard_function *pf);
78static int pccard_compat_do_probe(device_t bus, device_t dev);
79static int pccard_compat_do_attach(device_t bus, device_t dev);
80static int pccard_add_children(device_t dev, int busno);
81static int pccard_probe(device_t dev);
82static int pccard_attach(device_t dev);
83static int pccard_detach(device_t dev);
84static void pccard_print_resources(struct resource_list *rl,
85 const char *name, int type, int count, const char *format);
86static int pccard_print_child(device_t dev, device_t child);
87static int pccard_set_resource(device_t dev, device_t child, int type,
88 int rid, u_long start, u_long count);
89static int pccard_get_resource(device_t dev, device_t child, int type,
90 int rid, u_long *startp, u_long *countp);
91static void pccard_delete_resource(device_t dev, device_t child, int type,
92 int rid);
93static int pccard_set_res_flags(device_t dev, device_t child, int type,
94 int rid, u_int32_t flags);
95static int pccard_set_memory_offset(device_t dev, device_t child, int rid,
96 u_int32_t offset, u_int32_t *deltap);
97static int pccard_read_ivar(device_t bus, device_t child, int which,
98 u_char *result);
99static void pccard_driver_added(device_t dev, driver_t *driver);
100static struct resource *pccard_alloc_resource(device_t dev,
101 device_t child, int type, int *rid, u_long start,
102 u_long end, u_long count, u_int flags);
103static int pccard_release_resource(device_t dev, device_t child, int type,
104 int rid, struct resource *r);
105static void pccard_child_detached(device_t parent, device_t dev);
106static void pccard_intr(void *arg);
107static int pccard_setup_intr(device_t dev, device_t child,
108 struct resource *irq, int flags, driver_intr_t *intr,
109 void *arg, void **cookiep);
110static int pccard_teardown_intr(device_t dev, device_t child,
111 struct resource *r, void *cookie);
112
113static int
114pccard_ccr_read(struct pccard_function *pf, int ccr)
115{
116 return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
117 pf->pf_ccr_offset + ccr));
118}
119
120static void
121pccard_ccr_write(struct pccard_function *pf, int ccr, int val)
122{
123 if ((pf->ccr_mask) & (1 << (ccr / 2))) {
124 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
125 pf->pf_ccr_offset + ccr, val);
126 }
127}
128
129static int
130pccard_attach_card(device_t dev)
131{
132 struct pccard_softc *sc = PCCARD_SOFTC(dev);
133 struct pccard_function *pf;
134 struct pccard_ivar *ivar;
135 device_t child;
136
137 /*
138 * this is here so that when socket_enable calls gettype, trt happens
139 */
140 STAILQ_INIT(&sc->card.pf_head);
141
142 DEVPRINTF((dev, "chip_socket_enable\n"));
143 POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
144
145 DEVPRINTF((dev, "read_cis\n"));
146 pccard_read_cis(sc);
147
148 DEVPRINTF((dev, "check_cis_quirks\n"));
149 pccard_check_cis_quirks(dev);
150
151 /*
152 * bail now if the card has no functions, or if there was an error in
153 * the cis.
154 */
155
156 if (sc->card.error) {
157 device_printf (dev, "CARD ERROR!\n");
158 return (1);
159 }
160 if (STAILQ_EMPTY(&sc->card.pf_head)) {
161 device_printf (dev, "Card has no functions!\n");
162 return (1);
163 }
164
171 if (1)
165 if (bootverbose || pccard_debug)
172 pccard_print_cis(dev);
173
174 DEVPRINTF((dev, "functions scanning\n"));
175 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
176 if (STAILQ_EMPTY(&pf->cfe_head))
177 continue;
178
179 pf->sc = sc;
180 pf->cfe = NULL;
181 pf->dev = NULL;
182 }
183
184 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
185 if (STAILQ_EMPTY(&pf->cfe_head))
186 continue;
187 /*
188 * In NetBSD, the drivers are responsible for activating
189 * each function of a card. I think that in FreeBSD we
190 * want to activate them enough for the usual bus_*_resource
191 * routines will do the right thing. This many mean a
192 * departure from the current NetBSD model.
193 *
194 * This could get really ugly for multifunction cards. But
195 * it might also just fall out of the FreeBSD resource model.
196 *
197 */
198 ivar = malloc(sizeof(struct pccard_ivar), M_DEVBUF,
199 M_WAITOK | M_ZERO);
200 child = device_add_child(dev, NULL, -1);
201 device_set_ivars(child, ivar);
202 ivar->fcn = pf;
203 pf->dev = child;
204 /*
205 * XXX We might want to move the next two lines into
206 * XXX the pccard interface layer. For the moment, this
207 * XXX is OK, but some drivers want to pick the config
208 * XXX entry to use as well as some address tweaks (mostly
209 * XXX due to bugs in decode logic that makes some
210 * XXX addresses illegal or broken).
211 */
212 pccard_function_init(pf);
213 if (sc->sc_enabled_count == 0)
214 POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
215 if (pccard_function_enable(pf) == 0 &&
216 device_probe_and_attach(child) == 0) {
217 DEVPRINTF((sc->dev, "function %d CCR at %d "
218 "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
219 pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
220 pccard_ccr_read(pf, 0x00),
221 pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
222 pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
223 pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
224 pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
225 } else {
226 if (pf->cfe != NULL)
227 pccard_function_disable(pf);
228 }
229 }
230 if (sc->sc_enabled_count == 0)
231 pccard_detach_card(dev, 0);
232 return (0);
233}
234
235static int
236pccard_detach_card(device_t dev, int flags)
237{
238 struct pccard_softc *sc = PCCARD_SOFTC(dev);
239 struct pccard_function *pf;
240 struct pccard_config_entry *cfe;
241
242 /*
243 * We are running on either the PCCARD socket's event thread
244 * or in user context detaching a device by user request.
245 */
246 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
247 int state = device_get_state(pf->dev);
248
249 if (state == DS_ATTACHED || state == DS_BUSY)
250 device_detach(pf->dev);
251 if (pf->cfe != NULL)
252 pccard_function_disable(pf);
253 pccard_function_free(pf);
254 if (pf->dev != NULL)
255 device_delete_child(dev, pf->dev);
256 }
257 if (sc->sc_enabled_count == 0)
258 POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
259
260 while (NULL != (pf = STAILQ_FIRST(&sc->card.pf_head))) {
261 while (NULL != (cfe = STAILQ_FIRST(&pf->cfe_head))) {
262 STAILQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
263 free(cfe, M_DEVBUF);
264 }
265 STAILQ_REMOVE_HEAD(&sc->card.pf_head, pf_list);
266 free(pf, M_DEVBUF);
267 }
268 return (0);
269}
270
271const struct pccard_product *
272pccard_product_lookup(device_t dev, const struct pccard_product *tab,
273 size_t ent_size, pccard_product_match_fn matchfn)
274{
275 const struct pccard_product *ent;
276 int matches;
277 u_int32_t fcn;
278 u_int32_t vendor;
279 u_int32_t prod;
280 char *vendorstr;
281 char *prodstr;
282
283#ifdef DIAGNOSTIC
284 if (sizeof *ent > ent_size)
285 panic("pccard_product_lookup: bogus ent_size %ld",
286 (long) ent_size);
287#endif
288 if (pccard_get_vendor(dev, &vendor))
289 return (NULL);
290 if (pccard_get_product(dev, &prod))
291 return (NULL);
292 if (pccard_get_function_number(dev, &fcn))
293 return (NULL);
294 if (pccard_get_vendor_str(dev, &vendorstr))
295 return (NULL);
296 if (pccard_get_product_str(dev, &prodstr))
297 return (NULL);
298 for (ent = tab; ent->pp_name != NULL; ent =
299 (const struct pccard_product *) ((const char *) ent + ent_size)) {
300 matches = 1;
301 if (ent->pp_vendor == PCCARD_VENDOR_ANY &&
302 ent->pp_product == PCCARD_VENDOR_ANY &&
303 ent->pp_cis[0] == NULL &&
304 ent->pp_cis[1] == NULL) {
305 device_printf(dev,
306 "Total wildcard entry ignored for %s\n",
307 ent->pp_name);
308 continue;
309 }
310 if (matches && ent->pp_vendor != PCCARD_VENDOR_ANY &&
311 vendor != ent->pp_vendor)
312 matches = 0;
313 if (matches && ent->pp_product != PCCARD_PRODUCT_ANY &&
314 prod != ent->pp_product)
315 matches = 0;
316 if (matches && fcn != ent->pp_expfunc)
317 matches = 0;
318 if (matches && ent->pp_cis[0] &&
319 strcmp(ent->pp_cis[0], vendorstr) != 0)
320 matches = 0;
321 if (matches && ent->pp_cis[1] &&
322 strcmp(ent->pp_cis[1], prodstr) != 0)
323 matches = 0;
324 /* XXX need to match cis[2] and cis[3] also XXX */
325 if (matchfn != NULL)
326 matches = (*matchfn)(dev, ent, matches);
327 if (matches)
328 return (ent);
329 }
330 return (NULL);
331}
332
333static int
334pccard_card_gettype(device_t dev, int *type)
335{
336 struct pccard_softc *sc = PCCARD_SOFTC(dev);
337 struct pccard_function *pf;
338
339 /*
340 * set the iftype to memory if this card has no functions (not yet
341 * probed), or only one function, and that is not initialized yet or
342 * that is memory.
343 */
344 pf = STAILQ_FIRST(&sc->card.pf_head);
345 if (pf == NULL ||
346 (STAILQ_NEXT(pf, pf_list) == NULL &&
347 (pf->cfe == NULL || pf->cfe->iftype == PCCARD_IFTYPE_MEMORY)))
348 *type = PCCARD_IFTYPE_MEMORY;
349 else
350 *type = PCCARD_IFTYPE_IO;
351 return (0);
352}
353
354/*
355 * Initialize a PCCARD function. May be called as long as the function is
356 * disabled.
357 *
358 * Note: pccard_function_init should not keep resources allocated. It should
359 * only set them up ala isa pnp, set the values in the rl lists, and return.
360 * Any resource held after pccard_function_init is called is a bug. However,
361 * the bus routines to get the resources also assume that pccard_function_init
362 * does this, so they need to be fixed too.
363 */
364static void
365pccard_function_init(struct pccard_function *pf)
366{
367 struct pccard_config_entry *cfe;
368 int i;
369 struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
370 struct resource_list *rl = &devi->resources;
371 struct resource_list_entry *rle;
372 struct resource *r = 0;
373 device_t bus;
374 int start;
375 int end;
376
377 if (pf->pf_flags & PFF_ENABLED) {
378 printf("pccard_function_init: function is enabled");
379 return;
380 }
381 bus = device_get_parent(pf->dev);
382 /* Remember which configuration entry we are using. */
383 STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
384 for (i = 0; i < cfe->num_iospace; i++)
385 cfe->iores[i] = NULL;
386 cfe->irqres = NULL;
387 for (i = 0; i < cfe->num_iospace; i++) {
388 start = cfe->iospace[i].start;
389 if (start)
390 end = start + cfe->iospace[i].length - 1;
391 else
392 end = ~0;
393 cfe->iorid[i] = i;
394 r = cfe->iores[i] = bus_alloc_resource(bus,
395 SYS_RES_IOPORT, &cfe->iorid[i], start, end,
396 cfe->iospace[i].length,
397 rman_make_alignment_flags(cfe->iospace[i].length));
398 if (cfe->iores[i] == NULL)
399 goto not_this_one;
400 resource_list_add(rl, SYS_RES_IOPORT, cfe->iorid[i],
401 rman_get_start(r), rman_get_end(r),
402 cfe->iospace[i].length);
403 rle = resource_list_find(rl, SYS_RES_IOPORT,
404 cfe->iorid[i]);
405 rle->res = r;
406 }
407 if (cfe->num_memspace > 0) {
408 /*
409 * Not implement yet, Fix me.
410 */
411 }
412 if (cfe->irqmask) {
413 cfe->irqrid = 0;
414 r = cfe->irqres = bus_alloc_resource(bus, SYS_RES_IRQ,
415 &cfe->irqrid, 0, ~0, 1, 0);
416 if (cfe->irqres == NULL)
417 goto not_this_one;
418 resource_list_add(rl, SYS_RES_IRQ, cfe->irqrid,
419 rman_get_start(r), rman_get_end(r), 1);
420 rle = resource_list_find(rl, SYS_RES_IRQ,
421 cfe->irqrid);
422 rle->res = r;
423 }
424 /* If we get to here, we've allocated all we need */
425 pf->cfe = cfe;
426 break;
427 not_this_one:;
428 DEVPRVERBOSE((bus, "Allocation failed for cfe %d\n",
429 cfe->number));
430 /*
431 * Release resources that we partially allocated
432 * from this config entry.
433 */
434 for (i = 0; i < cfe->num_iospace; i++) {
435 if (cfe->iores[i] != NULL) {
436 bus_release_resource(bus, SYS_RES_IOPORT,
437 cfe->iorid[i], cfe->iores[i]);
438 rle = resource_list_find(rl, SYS_RES_IOPORT,
439 cfe->iorid[i]);
440 rle->res = NULL;
441 resource_list_delete(rl, SYS_RES_IOPORT,
442 cfe->iorid[i]);
443 }
444 cfe->iores[i] = NULL;
445 }
446 if (cfe->irqmask && cfe->irqres != NULL) {
447 bus_release_resource(bus, SYS_RES_IRQ,
448 cfe->irqrid, cfe->irqres);
449 rle = resource_list_find(rl, SYS_RES_IRQ,
450 cfe->irqrid);
451 rle->res = NULL;
452 resource_list_delete(rl, SYS_RES_IRQ, cfe->irqrid);
453 cfe->irqres = NULL;
454 }
455 }
456}
457
458/*
459 * Free resources allocated by pccard_function_init(), May be called as long
460 * as the function is disabled.
461 *
462 * NOTE: This function should be unnecessary. pccard_function_init should
463 * never keep resources initialized.
464 */
465static void
466pccard_function_free(struct pccard_function *pf)
467{
468 struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
469 struct resource_list_entry *rle;
470
471 if (pf->pf_flags & PFF_ENABLED) {
472 printf("pccard_function_init: function is enabled");
473 return;
474 }
475
476 SLIST_FOREACH(rle, &devi->resources, link) {
477 if (rle->res) {
478 if (rle->res->r_dev != pf->sc->dev)
479 device_printf(pf->sc->dev,
480 "function_free: Resource still owned by "
481 "child, oops. "
482 "(type=%d, rid=%d, addr=%lx)\n",
483 rle->type, rle->rid,
484 rman_get_start(rle->res));
485 BUS_RELEASE_RESOURCE(device_get_parent(pf->sc->dev),
486 rle->res->r_dev, rle->type, rle->rid, rle->res);
487 rle->res = NULL;
488 }
489 }
490 resource_list_free(&devi->resources);
491}
492
493/* Enable a PCCARD function */
494static int
495pccard_function_enable(struct pccard_function *pf)
496{
497 struct pccard_function *tmp;
498 int reg;
499 device_t dev = pf->sc->dev;
500
501 if (pf->cfe == NULL) {
502 DEVPRVERBOSE((dev, "No config entry could be allocated.\n"));
503 return (ENOMEM);
504 }
505
506 /*
507 * Increase the reference count on the socket, enabling power, if
508 * necessary.
509 */
510 pf->sc->sc_enabled_count++;
511
512 if (pf->pf_flags & PFF_ENABLED) {
513 /*
514 * Don't do anything if we're already enabled.
515 */
516 return (0);
517 }
518
519 /*
520 * it's possible for different functions' CCRs to be in the same
521 * underlying page. Check for that.
522 */
523 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
524 if ((tmp->pf_flags & PFF_ENABLED) &&
525 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
526 ((pf->ccr_base + PCCARD_CCR_SIZE) <=
527 (tmp->ccr_base - tmp->pf_ccr_offset +
528 tmp->pf_ccr_realsize))) {
529 pf->pf_ccrt = tmp->pf_ccrt;
530 pf->pf_ccrh = tmp->pf_ccrh;
531 pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
532
533 /*
534 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
535 * tmp->ccr_base) + pf->ccr_base;
536 */
537 /* pf->pf_ccr_offset =
538 (tmp->pf_ccr_offset + pf->ccr_base) -
539 tmp->ccr_base; */
540 pf->pf_ccr_window = tmp->pf_ccr_window;
541 break;
542 }
543 }
544 if (tmp == NULL) {
545 pf->ccr_rid = 0;
546 pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
547 &pf->ccr_rid, 0, ~0, 1 << 10, RF_ACTIVE);
548 if (!pf->ccr_res)
549 goto bad;
550 DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%lx\n",
551 rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res),
552 pf->ccr_base));
553 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
554 pf->ccr_rid, PCCARD_A_MEM_ATTR);
555 CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
556 pf->ccr_rid, pf->ccr_base, &pf->pf_ccr_offset);
557 pf->pf_ccrt = rman_get_bustag(pf->ccr_res);
558 pf->pf_ccrh = rman_get_bushandle(pf->ccr_res);
559 pf->pf_ccr_realsize = 1;
560 }
561
562 reg = (pf->cfe->number & PCCARD_CCR_OPTION_CFINDEX);
563 reg |= PCCARD_CCR_OPTION_LEVIREQ;
564 if (pccard_mfc(pf->sc)) {
565 reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE |
566 PCCARD_CCR_OPTION_ADDR_DECODE);
567 /* PCCARD_CCR_OPTION_IRQ_ENABLE set elsewhere as needed */
568 }
569 pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
570
571 reg = 0;
572 if ((pf->cfe->flags & PCCARD_CFE_IO16) == 0)
573 reg |= PCCARD_CCR_STATUS_IOIS8;
574 if (pf->cfe->flags & PCCARD_CFE_AUDIO)
575 reg |= PCCARD_CCR_STATUS_AUDIO;
576 pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg);
577
578 pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0);
579
580 if (pccard_mfc(pf->sc)) {
581 long tmp, iosize;
582
583 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
584 /* round up to nearest (2^n)-1 */
585 for (iosize = 1; iosize < tmp; iosize <<= 1)
586 ;
587 iosize--;
588
589 pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
590 pf->pf_mfc_iobase & 0xff);
591 pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
592 (pf->pf_mfc_iobase >> 8) & 0xff);
593 pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
594 pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
595
596 pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
597 }
598
599#ifdef PCCARDDEBUG
600 if (pccard_debug) {
601 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
602 device_printf(tmp->sc->dev,
603 "function %d CCR at %d offset %x: "
604 "%x %x %x %x, %x %x %x %x, %x\n",
605 tmp->number, tmp->pf_ccr_window,
606 tmp->pf_ccr_offset,
607 pccard_ccr_read(tmp, 0x00),
608 pccard_ccr_read(tmp, 0x02),
609 pccard_ccr_read(tmp, 0x04),
610 pccard_ccr_read(tmp, 0x06),
611 pccard_ccr_read(tmp, 0x0A),
612 pccard_ccr_read(tmp, 0x0C),
613 pccard_ccr_read(tmp, 0x0E),
614 pccard_ccr_read(tmp, 0x10),
615 pccard_ccr_read(tmp, 0x12));
616 }
617 }
618#endif
619 pf->pf_flags |= PFF_ENABLED;
620 return (0);
621
622 bad:
623 /*
624 * Decrement the reference count, and power down the socket, if
625 * necessary.
626 */
627 pf->sc->sc_enabled_count--;
628 DEVPRINTF((dev, "bad --enabled_count = %d\n", pf->sc->sc_enabled_count));
629
630 return (1);
631}
632
633/* Disable PCCARD function. */
634static void
635pccard_function_disable(struct pccard_function *pf)
636{
637 struct pccard_function *tmp;
638 device_t dev = pf->sc->dev;
639
640 if (pf->cfe == NULL)
641 panic("pccard_function_disable: function not initialized");
642
643 if ((pf->pf_flags & PFF_ENABLED) == 0) {
644 /*
645 * Don't do anything if we're already disabled.
646 */
647 return;
648 }
649
650 if (pf->intr_handler != NULL) {
651 struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
652 struct resource_list_entry *rle =
653 resource_list_find(&devi->resources, SYS_RES_IRQ, 0);
654 BUS_TEARDOWN_INTR(dev, pf->dev, rle->res,
655 pf->intr_handler_cookie);
656 }
657
658 /*
659 * it's possible for different functions' CCRs to be in the same
660 * underlying page. Check for that. Note we mark us as disabled
661 * first to avoid matching ourself.
662 */
663
664 pf->pf_flags &= ~PFF_ENABLED;
665 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
666 if ((tmp->pf_flags & PFF_ENABLED) &&
667 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
668 ((pf->ccr_base + PCCARD_CCR_SIZE) <=
669 (tmp->ccr_base - tmp->pf_ccr_offset +
670 tmp->pf_ccr_realsize)))
671 break;
672 }
673
674 /* Not used by anyone else; unmap the CCR. */
675 if (tmp == NULL) {
676 bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
677 pf->ccr_res);
678 pf->ccr_res = NULL;
679 }
680
681 /*
682 * Decrement the reference count, and power down the socket, if
683 * necessary.
684 */
685 pf->sc->sc_enabled_count--;
686}
687
688#if 0
689/* XXX These functions are needed, but not like this XXX */
690int
691pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset,
692 bus_size_t size, struct pccard_io_handle *pcihp, int *windowp)
693{
694 int reg;
695
696 if (pccard_chip_io_map(pf->sc->pct, pf->sc->pch, width, offset, size,
697 pcihp, windowp))
698 return (1);
699
700 /*
701 * XXX in the multifunction multi-iospace-per-function case, this
702 * needs to cooperate with io_alloc to make sure that the spaces
703 * don't overlap, and that the ccr's are set correctly
704 */
705
706 if (pccard_mfc(pf->sc)) {
707 long tmp, iosize;
708
709 if (pf->pf_mfc_iomax == 0) {
710 pf->pf_mfc_iobase = pcihp->addr + offset;
711 pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
712 } else {
713 /* this makes the assumption that nothing overlaps */
714 if (pf->pf_mfc_iobase > pcihp->addr + offset)
715 pf->pf_mfc_iobase = pcihp->addr + offset;
716 if (pf->pf_mfc_iomax < pcihp->addr + offset + size)
717 pf->pf_mfc_iomax = pcihp->addr + offset + size;
718 }
719
720 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
721 /* round up to nearest (2^n)-1 */
722 for (iosize = 1; iosize >= tmp; iosize <<= 1)
723 ;
724 iosize--;
725
726 pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
727 pf->pf_mfc_iobase & 0xff);
728 pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
729 (pf->pf_mfc_iobase >> 8) & 0xff);
730 pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
731 pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
732
733 pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
734
735 reg = pccard_ccr_read(pf, PCCARD_CCR_OPTION);
736 reg |= PCCARD_CCR_OPTION_ADDR_DECODE;
737 pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
738 }
739 return (0);
740}
741
742void
743pccard_io_unmap(struct pccard_function *pf, int window)
744{
745
746 pccard_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
747
748 /* XXX Anything for multi-function cards? */
749}
750#endif
751
752/*
753 * simulate the old "probe" routine. In the new world order, the driver
754 * needs to grab devices while in the old they were assigned to the device by
755 * the pccardd process. These symbols are exported to the upper layers.
756 */
757static int
758pccard_compat_do_probe(device_t bus, device_t dev)
759{
760 return (CARD_COMPAT_MATCH(dev));
761}
762
763static int
764pccard_compat_do_attach(device_t bus, device_t dev)
765{
766 int err;
767
768 err = CARD_COMPAT_PROBE(dev);
769 if (err == 0)
770 err = CARD_COMPAT_ATTACH(dev);
771 return (err);
772}
773
774#define PCCARD_NPORT 2
775#define PCCARD_NMEM 5
776#define PCCARD_NIRQ 1
777#define PCCARD_NDRQ 0
778
779static int
780pccard_add_children(device_t dev, int busno)
781{
782 /* Call parent to scan for any current children */
783 return (0);
784}
785
786static int
787pccard_probe(device_t dev)
788{
789 device_set_desc(dev, "16-bit PCCard bus");
790 return (pccard_add_children(dev, device_get_unit(dev)));
791}
792
793static int
794pccard_attach(device_t dev)
795{
796 struct pccard_softc *sc = PCCARD_SOFTC(dev);
797
798 sc->dev = dev;
799 sc->sc_enabled_count = 0;
800 return (bus_generic_attach(dev));
801}
802
803static int
804pccard_detach(device_t dev)
805{
806 pccard_detach_card(dev, 0);
807 return 0;
808}
809
810static int
811pccard_suspend(device_t self)
812{
813 pccard_detach_card(self, 0);
814 return (0);
815}
816
817static
818int
819pccard_resume(device_t self)
820{
821 return (0);
822}
823
824static void
825pccard_print_resources(struct resource_list *rl, const char *name, int type,
826 int count, const char *format)
827{
828 struct resource_list_entry *rle;
829 int printed;
830 int i;
831
832 printed = 0;
833 for (i = 0; i < count; i++) {
834 rle = resource_list_find(rl, type, i);
835 if (rle != NULL) {
836 if (printed == 0)
837 printf(" %s ", name);
838 else if (printed > 0)
839 printf(",");
840 printed++;
841 printf(format, rle->start);
842 if (rle->count > 1) {
843 printf("-");
844 printf(format, rle->start + rle->count - 1);
845 }
846 } else if (i > 3) {
847 /* check the first few regardless */
848 break;
849 }
850 }
851}
852
853static int
854pccard_print_child(device_t dev, device_t child)
855{
856 struct pccard_ivar *devi = PCCARD_IVAR(child);
857 struct resource_list *rl = &devi->resources;
858 int retval = 0;
859
860 retval += bus_print_child_header(dev, child);
861 retval += printf(" at");
862
863 if (devi != NULL) {
864 pccard_print_resources(rl, "port", SYS_RES_IOPORT,
865 PCCARD_NPORT, "%#lx");
866 pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
867 PCCARD_NMEM, "%#lx");
868 pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
869 "%ld");
870 pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
871 "%ld");
872 retval += printf(" function %d config %d", devi->fcn->number,
873 devi->fcn->cfe->number);
874 }
875
876 retval += bus_print_child_footer(dev, child);
877
878 return (retval);
879}
880
881static int
882pccard_set_resource(device_t dev, device_t child, int type, int rid,
883 u_long start, u_long count)
884{
885 struct pccard_ivar *devi = PCCARD_IVAR(child);
886 struct resource_list *rl = &devi->resources;
887
888 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
889 && type != SYS_RES_IRQ && type != SYS_RES_DRQ)
890 return (EINVAL);
891 if (rid < 0)
892 return (EINVAL);
893 if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
894 return (EINVAL);
895 if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
896 return (EINVAL);
897 if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
898 return (EINVAL);
899 if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
900 return (EINVAL);
901
902 resource_list_add(rl, type, rid, start, start + count - 1, count);
903 if (NULL != resource_list_alloc(rl, device_get_parent(dev), dev,
904 type, &rid, start, start + count - 1, count, 0))
905 return 0;
906 else
907 return ENOMEM;
908}
909
910static int
911pccard_get_resource(device_t dev, device_t child, int type, int rid,
912 u_long *startp, u_long *countp)
913{
914 struct pccard_ivar *devi = PCCARD_IVAR(child);
915 struct resource_list *rl = &devi->resources;
916 struct resource_list_entry *rle;
917
918 rle = resource_list_find(rl, type, rid);
919 if (rle == NULL)
920 return (ENOENT);
921
922 if (startp != NULL)
923 *startp = rle->start;
924 if (countp != NULL)
925 *countp = rle->count;
926
927 return (0);
928}
929
930static void
931pccard_delete_resource(device_t dev, device_t child, int type, int rid)
932{
933 struct pccard_ivar *devi = PCCARD_IVAR(child);
934 struct resource_list *rl = &devi->resources;
935 resource_list_delete(rl, type, rid);
936}
937
938static int
939pccard_set_res_flags(device_t dev, device_t child, int type, int rid,
940 u_int32_t flags)
941{
942 return (CARD_SET_RES_FLAGS(device_get_parent(dev), child, type,
943 rid, flags));
944}
945
946static int
947pccard_set_memory_offset(device_t dev, device_t child, int rid,
948 u_int32_t offset, u_int32_t *deltap)
949
950{
951 return (CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid,
952 offset, deltap));
953}
954
955static int
956pccard_read_ivar(device_t bus, device_t child, int which, u_char *result)
957{
958 struct pccard_ivar *devi = PCCARD_IVAR(child);
959 struct pccard_function *func = devi->fcn;
960 struct pccard_softc *sc = PCCARD_SOFTC(bus);
961
962 /* PCCARD_IVAR_ETHADDR unhandled from oldcard */
963 switch (which) {
964 default:
965 case PCCARD_IVAR_ETHADDR:
966 bcopy(func->pf_funce_lan_nid, result, ETHER_ADDR_LEN);
967 break;
968 case PCCARD_IVAR_VENDOR:
969 *(u_int32_t *) result = sc->card.manufacturer;
970 break;
971 case PCCARD_IVAR_PRODUCT:
972 *(u_int32_t *) result = sc->card.product;
973 break;
974 case PCCARD_IVAR_FUNCTION:
975 *(u_int32_t *) result = func->function;
976 break;
977 case PCCARD_IVAR_FUNCTION_NUMBER:
978 if (!func) {
979 device_printf(bus, "No function number, bug!\n");
980 return (ENOENT);
981 }
982 *(u_int32_t *) result = func->number;
983 break;
984 case PCCARD_IVAR_VENDOR_STR:
985 *(char **) result = sc->card.cis1_info[0];
986 break;
987 case PCCARD_IVAR_PRODUCT_STR:
988 *(char **) result = sc->card.cis1_info[1];
989 break;
990 case PCCARD_IVAR_CIS3_STR:
991 *(char **) result = sc->card.cis1_info[2];
992 break;
993 case PCCARD_IVAR_CIS4_STR:
994 *(char **) result = sc->card.cis1_info[2];
995 break;
996 }
997 return (0);
998}
999
1000static void
1001pccard_driver_added(device_t dev, driver_t *driver)
1002{
1003 struct pccard_softc *sc = PCCARD_SOFTC(dev);
1004 struct pccard_function *pf;
1005 device_t child;
1006
1007 if (sc->sc_enabled_count == 0) {
1008 CARD_REPROBE_CARD(device_get_parent(dev), dev);
1009 return;
1010 }
1011
1012 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
1013 if (STAILQ_EMPTY(&pf->cfe_head))
1014 continue;
1015 child = pf->dev;
1016 if (device_get_state(child) != DS_NOTPRESENT)
1017 continue;
1018 if (pccard_function_enable(pf) == 0 &&
1019 device_probe_and_attach(child) == 0) {
1020 DEVPRINTF((sc->dev, "function %d CCR at %d "
1021 "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
1022 pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
1023 pccard_ccr_read(pf, 0x00),
1024 pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
1025 pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
1026 pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
1027 pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
1028 } else {
1029 if (pf->cfe != NULL)
1030 pccard_function_disable(pf);
1031 }
1032 }
1033 return;
1034}
1035
1036static struct resource *
1037pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
1038 u_long start, u_long end, u_long count, u_int flags)
1039{
1040 struct pccard_ivar *dinfo;
1041 struct resource_list_entry *rle = 0;
1042 int passthrough = (device_get_parent(child) != dev);
1043
1044 if (passthrough) {
1045 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
1046 type, rid, start, end, count, flags));
1047 }
1048
1049 dinfo = device_get_ivars(child);
1050 rle = resource_list_find(&dinfo->resources, type, *rid);
1051
1052 if (!rle)
1053 return NULL; /* no resource of that type/rid */
1054
1055 if (!rle->res) {
1056 device_printf(dev, "WARNING: Resource not reserved by pccard bus\n");
1057 return NULL;
1058 } else {
1059 if (rle->res->r_dev != dev) return NULL;
1060 bus_release_resource(dev, type, *rid, rle->res);
1061 rle->res = NULL;
1062 switch(type) {
1063 case SYS_RES_IOPORT:
1064 case SYS_RES_MEMORY:
1065 if (!(flags & RF_ALIGNMENT_MASK))
1066 flags |= rman_make_alignment_flags(rle->count);
1067 break;
1068 case SYS_RES_IRQ:
1069 flags |= RF_SHAREABLE;
1070 break;
1071 }
1072 return resource_list_alloc(&dinfo->resources, dev, child, type,
1073 rid, rle->start, rle->end, rle->count, flags);
1074 }
1075}
1076
1077static int
1078pccard_release_resource(device_t dev, device_t child, int type, int rid,
1079 struct resource *r)
1080{
1081 struct pccard_ivar *dinfo;
1082 int passthrough = (device_get_parent(child) != dev);
1083 struct resource_list_entry *rle = 0;
1084 int ret;
1085 int flags;
1086
1087 if (passthrough)
1088 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1089 type, rid, r);
1090
1091 dinfo = device_get_ivars(child);
1092
1093 rle = resource_list_find(&dinfo->resources, type, rid);
1094
1095 if (!rle) {
1096 device_printf(dev, "Allocated resource not found, "
1097 "%d %x %lx %lx\n",
1098 type, rid, rman_get_start(r), rman_get_size(r));
1099 return ENOENT;
1100 }
1101 if (!rle->res) {
1102 device_printf(dev, "Allocated resource not recorded\n");
1103 return ENOENT;
1104 }
1105
1106 ret = BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1107 type, rid, r);
1108 switch(type) {
1109 case SYS_RES_IOPORT:
1110 case SYS_RES_MEMORY:
1111 flags = rman_make_alignment_flags(rle->count);
1112 break;
1113 case SYS_RES_IRQ:
1114 flags = RF_SHAREABLE;
1115 break;
1116 default:
1117 flags = 0;
1118 }
1119 rle->res = bus_alloc_resource(dev, type, &rid,
1120 rle->start, rle->end, rle->count, flags);
1121 if (rle->res == NULL)
1122 device_printf(dev, "release_resource: "
1123 "unable to reaquire resource\n");
1124 return ret;
1125}
1126
1127static void
1128pccard_child_detached(device_t parent, device_t dev)
1129{
1130 struct pccard_ivar *ivar = PCCARD_IVAR(dev);
1131 struct pccard_function *pf = ivar->fcn;
1132
1133 pccard_function_disable(pf);
1134}
1135
1136static void
1137pccard_intr(void *arg)
1138{
1139 struct pccard_function *pf = (struct pccard_function*) arg;
1140 int reg;
1141
1142 /*
1143 * If we go to resetting a card, we may need a null interrupt hanlder
1144 * to work (since the system may call it before the device can
1145 * establish an ISR) due to interrupt sharing at a higher level.
1146 */
1147 if (pf->intr_handler == NULL)
1148 panic("Null interrupt handler?\n");
1149
1150 /*
1151 * XXX The CCR_STATUS register bits used here are
1152 * only valid for multi function cards.
1153 */
1154 reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
1155 if (reg & PCCARD_CCR_STATUS_INTR) {
1156 pccard_ccr_write(pf, PCCARD_CCR_STATUS,
1157 reg & ~PCCARD_CCR_STATUS_INTR);
1158 pf->intr_handler(pf->intr_handler_arg);
1159 }
1160}
1161
1162static int
1163pccard_setup_intr(device_t dev, device_t child, struct resource *irq,
1164 int flags, driver_intr_t *intr, void *arg, void **cookiep)
1165{
1166 struct pccard_ivar *ivar = PCCARD_IVAR(child);
1167 struct pccard_function *func = ivar->fcn;
1168
1169 if (func->intr_handler != NULL)
1170 panic("Only one interrupt handler per function allowed\n");
1171
1172 func->intr_handler = intr;
1173 func->intr_handler_arg = arg;
1174 func->intr_handler_cookie = *cookiep;
1175 pccard_ccr_write(func, PCCARD_CCR_OPTION,
1176 pccard_ccr_read(func, PCCARD_CCR_OPTION) |
1177 PCCARD_CCR_OPTION_IREQ_ENABLE);
1178
1179 /*
1180 * XXX Don't use TTY type for our interrupt handler. It makes
1181 * the spl masks wrong on -stable. Instead, we should use the type
1182 * that was requested of us.
1183 */
1184 bus_setup_intr(dev, irq, INTR_TYPE_TTY/* | INTR_FAST*/,
1185 pccard_intr, func, cookiep);
1186 return (0);
1187}
1188
1189static int
1190pccard_teardown_intr(device_t dev, device_t child, struct resource *r,
1191 void *cookie)
1192{
1193 struct pccard_ivar *ivar = PCCARD_IVAR(child);
1194 struct pccard_function *func = ivar->fcn;
1195 int ret;
1196
1197 pccard_ccr_write(func, PCCARD_CCR_OPTION,
1198 pccard_ccr_read(func, PCCARD_CCR_OPTION) &
1199 ~PCCARD_CCR_OPTION_IREQ_ENABLE);
1200
1201 ret = bus_teardown_intr(dev, r, cookie);
1202 if (ret == 0) {
1203 func->intr_handler = NULL;
1204 func->intr_handler_arg = NULL;
1205 func->intr_handler_cookie = NULL;
1206 }
1207
1208 return (ret);
1209}
1210
1211static device_method_t pccard_methods[] = {
1212 /* Device interface */
1213 DEVMETHOD(device_probe, pccard_probe),
1214 DEVMETHOD(device_attach, pccard_attach),
1215 DEVMETHOD(device_detach, pccard_detach),
1216 DEVMETHOD(device_shutdown, bus_generic_shutdown),
1217 DEVMETHOD(device_suspend, pccard_suspend),
1218 DEVMETHOD(device_resume, pccard_resume),
1219
1220 /* Bus interface */
1221 DEVMETHOD(bus_print_child, pccard_print_child),
1222 DEVMETHOD(bus_driver_added, pccard_driver_added),
1223 DEVMETHOD(bus_child_detached, pccard_child_detached),
1224 DEVMETHOD(bus_alloc_resource, pccard_alloc_resource),
1225 DEVMETHOD(bus_release_resource, pccard_release_resource),
1226 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1227 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1228 DEVMETHOD(bus_setup_intr, pccard_setup_intr),
1229 DEVMETHOD(bus_teardown_intr, pccard_teardown_intr),
1230 DEVMETHOD(bus_set_resource, pccard_set_resource),
1231 DEVMETHOD(bus_get_resource, pccard_get_resource),
1232 DEVMETHOD(bus_delete_resource, pccard_delete_resource),
1233 DEVMETHOD(bus_read_ivar, pccard_read_ivar),
1234
1235 /* Card Interface */
1236 DEVMETHOD(card_set_res_flags, pccard_set_res_flags),
1237 DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
1238 DEVMETHOD(card_get_type, pccard_card_gettype),
1239 DEVMETHOD(card_attach_card, pccard_attach_card),
1240 DEVMETHOD(card_detach_card, pccard_detach_card),
1241 DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe),
1242 DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach),
1243
1244 { 0, 0 }
1245};
1246
1247static driver_t pccard_driver = {
1248 "pccard",
1249 pccard_methods,
1250 sizeof(struct pccard_softc)
1251};
1252
1253devclass_t pccard_devclass;
1254
1255DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
1256DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0);
1257DRIVER_MODULE(pccard, pccbb, pccard_driver, pccard_devclass, 0, 0);
1258DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0);
1259MODULE_VERSION(pccard, 1);
1260/*MODULE_DEPEND(pccard, pcic, 1, 1, 1);*/
166 pccard_print_cis(dev);
167
168 DEVPRINTF((dev, "functions scanning\n"));
169 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
170 if (STAILQ_EMPTY(&pf->cfe_head))
171 continue;
172
173 pf->sc = sc;
174 pf->cfe = NULL;
175 pf->dev = NULL;
176 }
177
178 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
179 if (STAILQ_EMPTY(&pf->cfe_head))
180 continue;
181 /*
182 * In NetBSD, the drivers are responsible for activating
183 * each function of a card. I think that in FreeBSD we
184 * want to activate them enough for the usual bus_*_resource
185 * routines will do the right thing. This many mean a
186 * departure from the current NetBSD model.
187 *
188 * This could get really ugly for multifunction cards. But
189 * it might also just fall out of the FreeBSD resource model.
190 *
191 */
192 ivar = malloc(sizeof(struct pccard_ivar), M_DEVBUF,
193 M_WAITOK | M_ZERO);
194 child = device_add_child(dev, NULL, -1);
195 device_set_ivars(child, ivar);
196 ivar->fcn = pf;
197 pf->dev = child;
198 /*
199 * XXX We might want to move the next two lines into
200 * XXX the pccard interface layer. For the moment, this
201 * XXX is OK, but some drivers want to pick the config
202 * XXX entry to use as well as some address tweaks (mostly
203 * XXX due to bugs in decode logic that makes some
204 * XXX addresses illegal or broken).
205 */
206 pccard_function_init(pf);
207 if (sc->sc_enabled_count == 0)
208 POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
209 if (pccard_function_enable(pf) == 0 &&
210 device_probe_and_attach(child) == 0) {
211 DEVPRINTF((sc->dev, "function %d CCR at %d "
212 "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
213 pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
214 pccard_ccr_read(pf, 0x00),
215 pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
216 pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
217 pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
218 pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
219 } else {
220 if (pf->cfe != NULL)
221 pccard_function_disable(pf);
222 }
223 }
224 if (sc->sc_enabled_count == 0)
225 pccard_detach_card(dev, 0);
226 return (0);
227}
228
229static int
230pccard_detach_card(device_t dev, int flags)
231{
232 struct pccard_softc *sc = PCCARD_SOFTC(dev);
233 struct pccard_function *pf;
234 struct pccard_config_entry *cfe;
235
236 /*
237 * We are running on either the PCCARD socket's event thread
238 * or in user context detaching a device by user request.
239 */
240 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
241 int state = device_get_state(pf->dev);
242
243 if (state == DS_ATTACHED || state == DS_BUSY)
244 device_detach(pf->dev);
245 if (pf->cfe != NULL)
246 pccard_function_disable(pf);
247 pccard_function_free(pf);
248 if (pf->dev != NULL)
249 device_delete_child(dev, pf->dev);
250 }
251 if (sc->sc_enabled_count == 0)
252 POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
253
254 while (NULL != (pf = STAILQ_FIRST(&sc->card.pf_head))) {
255 while (NULL != (cfe = STAILQ_FIRST(&pf->cfe_head))) {
256 STAILQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
257 free(cfe, M_DEVBUF);
258 }
259 STAILQ_REMOVE_HEAD(&sc->card.pf_head, pf_list);
260 free(pf, M_DEVBUF);
261 }
262 return (0);
263}
264
265const struct pccard_product *
266pccard_product_lookup(device_t dev, const struct pccard_product *tab,
267 size_t ent_size, pccard_product_match_fn matchfn)
268{
269 const struct pccard_product *ent;
270 int matches;
271 u_int32_t fcn;
272 u_int32_t vendor;
273 u_int32_t prod;
274 char *vendorstr;
275 char *prodstr;
276
277#ifdef DIAGNOSTIC
278 if (sizeof *ent > ent_size)
279 panic("pccard_product_lookup: bogus ent_size %ld",
280 (long) ent_size);
281#endif
282 if (pccard_get_vendor(dev, &vendor))
283 return (NULL);
284 if (pccard_get_product(dev, &prod))
285 return (NULL);
286 if (pccard_get_function_number(dev, &fcn))
287 return (NULL);
288 if (pccard_get_vendor_str(dev, &vendorstr))
289 return (NULL);
290 if (pccard_get_product_str(dev, &prodstr))
291 return (NULL);
292 for (ent = tab; ent->pp_name != NULL; ent =
293 (const struct pccard_product *) ((const char *) ent + ent_size)) {
294 matches = 1;
295 if (ent->pp_vendor == PCCARD_VENDOR_ANY &&
296 ent->pp_product == PCCARD_VENDOR_ANY &&
297 ent->pp_cis[0] == NULL &&
298 ent->pp_cis[1] == NULL) {
299 device_printf(dev,
300 "Total wildcard entry ignored for %s\n",
301 ent->pp_name);
302 continue;
303 }
304 if (matches && ent->pp_vendor != PCCARD_VENDOR_ANY &&
305 vendor != ent->pp_vendor)
306 matches = 0;
307 if (matches && ent->pp_product != PCCARD_PRODUCT_ANY &&
308 prod != ent->pp_product)
309 matches = 0;
310 if (matches && fcn != ent->pp_expfunc)
311 matches = 0;
312 if (matches && ent->pp_cis[0] &&
313 strcmp(ent->pp_cis[0], vendorstr) != 0)
314 matches = 0;
315 if (matches && ent->pp_cis[1] &&
316 strcmp(ent->pp_cis[1], prodstr) != 0)
317 matches = 0;
318 /* XXX need to match cis[2] and cis[3] also XXX */
319 if (matchfn != NULL)
320 matches = (*matchfn)(dev, ent, matches);
321 if (matches)
322 return (ent);
323 }
324 return (NULL);
325}
326
327static int
328pccard_card_gettype(device_t dev, int *type)
329{
330 struct pccard_softc *sc = PCCARD_SOFTC(dev);
331 struct pccard_function *pf;
332
333 /*
334 * set the iftype to memory if this card has no functions (not yet
335 * probed), or only one function, and that is not initialized yet or
336 * that is memory.
337 */
338 pf = STAILQ_FIRST(&sc->card.pf_head);
339 if (pf == NULL ||
340 (STAILQ_NEXT(pf, pf_list) == NULL &&
341 (pf->cfe == NULL || pf->cfe->iftype == PCCARD_IFTYPE_MEMORY)))
342 *type = PCCARD_IFTYPE_MEMORY;
343 else
344 *type = PCCARD_IFTYPE_IO;
345 return (0);
346}
347
348/*
349 * Initialize a PCCARD function. May be called as long as the function is
350 * disabled.
351 *
352 * Note: pccard_function_init should not keep resources allocated. It should
353 * only set them up ala isa pnp, set the values in the rl lists, and return.
354 * Any resource held after pccard_function_init is called is a bug. However,
355 * the bus routines to get the resources also assume that pccard_function_init
356 * does this, so they need to be fixed too.
357 */
358static void
359pccard_function_init(struct pccard_function *pf)
360{
361 struct pccard_config_entry *cfe;
362 int i;
363 struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
364 struct resource_list *rl = &devi->resources;
365 struct resource_list_entry *rle;
366 struct resource *r = 0;
367 device_t bus;
368 int start;
369 int end;
370
371 if (pf->pf_flags & PFF_ENABLED) {
372 printf("pccard_function_init: function is enabled");
373 return;
374 }
375 bus = device_get_parent(pf->dev);
376 /* Remember which configuration entry we are using. */
377 STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
378 for (i = 0; i < cfe->num_iospace; i++)
379 cfe->iores[i] = NULL;
380 cfe->irqres = NULL;
381 for (i = 0; i < cfe->num_iospace; i++) {
382 start = cfe->iospace[i].start;
383 if (start)
384 end = start + cfe->iospace[i].length - 1;
385 else
386 end = ~0;
387 cfe->iorid[i] = i;
388 r = cfe->iores[i] = bus_alloc_resource(bus,
389 SYS_RES_IOPORT, &cfe->iorid[i], start, end,
390 cfe->iospace[i].length,
391 rman_make_alignment_flags(cfe->iospace[i].length));
392 if (cfe->iores[i] == NULL)
393 goto not_this_one;
394 resource_list_add(rl, SYS_RES_IOPORT, cfe->iorid[i],
395 rman_get_start(r), rman_get_end(r),
396 cfe->iospace[i].length);
397 rle = resource_list_find(rl, SYS_RES_IOPORT,
398 cfe->iorid[i]);
399 rle->res = r;
400 }
401 if (cfe->num_memspace > 0) {
402 /*
403 * Not implement yet, Fix me.
404 */
405 }
406 if (cfe->irqmask) {
407 cfe->irqrid = 0;
408 r = cfe->irqres = bus_alloc_resource(bus, SYS_RES_IRQ,
409 &cfe->irqrid, 0, ~0, 1, 0);
410 if (cfe->irqres == NULL)
411 goto not_this_one;
412 resource_list_add(rl, SYS_RES_IRQ, cfe->irqrid,
413 rman_get_start(r), rman_get_end(r), 1);
414 rle = resource_list_find(rl, SYS_RES_IRQ,
415 cfe->irqrid);
416 rle->res = r;
417 }
418 /* If we get to here, we've allocated all we need */
419 pf->cfe = cfe;
420 break;
421 not_this_one:;
422 DEVPRVERBOSE((bus, "Allocation failed for cfe %d\n",
423 cfe->number));
424 /*
425 * Release resources that we partially allocated
426 * from this config entry.
427 */
428 for (i = 0; i < cfe->num_iospace; i++) {
429 if (cfe->iores[i] != NULL) {
430 bus_release_resource(bus, SYS_RES_IOPORT,
431 cfe->iorid[i], cfe->iores[i]);
432 rle = resource_list_find(rl, SYS_RES_IOPORT,
433 cfe->iorid[i]);
434 rle->res = NULL;
435 resource_list_delete(rl, SYS_RES_IOPORT,
436 cfe->iorid[i]);
437 }
438 cfe->iores[i] = NULL;
439 }
440 if (cfe->irqmask && cfe->irqres != NULL) {
441 bus_release_resource(bus, SYS_RES_IRQ,
442 cfe->irqrid, cfe->irqres);
443 rle = resource_list_find(rl, SYS_RES_IRQ,
444 cfe->irqrid);
445 rle->res = NULL;
446 resource_list_delete(rl, SYS_RES_IRQ, cfe->irqrid);
447 cfe->irqres = NULL;
448 }
449 }
450}
451
452/*
453 * Free resources allocated by pccard_function_init(), May be called as long
454 * as the function is disabled.
455 *
456 * NOTE: This function should be unnecessary. pccard_function_init should
457 * never keep resources initialized.
458 */
459static void
460pccard_function_free(struct pccard_function *pf)
461{
462 struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
463 struct resource_list_entry *rle;
464
465 if (pf->pf_flags & PFF_ENABLED) {
466 printf("pccard_function_init: function is enabled");
467 return;
468 }
469
470 SLIST_FOREACH(rle, &devi->resources, link) {
471 if (rle->res) {
472 if (rle->res->r_dev != pf->sc->dev)
473 device_printf(pf->sc->dev,
474 "function_free: Resource still owned by "
475 "child, oops. "
476 "(type=%d, rid=%d, addr=%lx)\n",
477 rle->type, rle->rid,
478 rman_get_start(rle->res));
479 BUS_RELEASE_RESOURCE(device_get_parent(pf->sc->dev),
480 rle->res->r_dev, rle->type, rle->rid, rle->res);
481 rle->res = NULL;
482 }
483 }
484 resource_list_free(&devi->resources);
485}
486
487/* Enable a PCCARD function */
488static int
489pccard_function_enable(struct pccard_function *pf)
490{
491 struct pccard_function *tmp;
492 int reg;
493 device_t dev = pf->sc->dev;
494
495 if (pf->cfe == NULL) {
496 DEVPRVERBOSE((dev, "No config entry could be allocated.\n"));
497 return (ENOMEM);
498 }
499
500 /*
501 * Increase the reference count on the socket, enabling power, if
502 * necessary.
503 */
504 pf->sc->sc_enabled_count++;
505
506 if (pf->pf_flags & PFF_ENABLED) {
507 /*
508 * Don't do anything if we're already enabled.
509 */
510 return (0);
511 }
512
513 /*
514 * it's possible for different functions' CCRs to be in the same
515 * underlying page. Check for that.
516 */
517 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
518 if ((tmp->pf_flags & PFF_ENABLED) &&
519 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
520 ((pf->ccr_base + PCCARD_CCR_SIZE) <=
521 (tmp->ccr_base - tmp->pf_ccr_offset +
522 tmp->pf_ccr_realsize))) {
523 pf->pf_ccrt = tmp->pf_ccrt;
524 pf->pf_ccrh = tmp->pf_ccrh;
525 pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
526
527 /*
528 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
529 * tmp->ccr_base) + pf->ccr_base;
530 */
531 /* pf->pf_ccr_offset =
532 (tmp->pf_ccr_offset + pf->ccr_base) -
533 tmp->ccr_base; */
534 pf->pf_ccr_window = tmp->pf_ccr_window;
535 break;
536 }
537 }
538 if (tmp == NULL) {
539 pf->ccr_rid = 0;
540 pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
541 &pf->ccr_rid, 0, ~0, 1 << 10, RF_ACTIVE);
542 if (!pf->ccr_res)
543 goto bad;
544 DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%lx\n",
545 rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res),
546 pf->ccr_base));
547 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
548 pf->ccr_rid, PCCARD_A_MEM_ATTR);
549 CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
550 pf->ccr_rid, pf->ccr_base, &pf->pf_ccr_offset);
551 pf->pf_ccrt = rman_get_bustag(pf->ccr_res);
552 pf->pf_ccrh = rman_get_bushandle(pf->ccr_res);
553 pf->pf_ccr_realsize = 1;
554 }
555
556 reg = (pf->cfe->number & PCCARD_CCR_OPTION_CFINDEX);
557 reg |= PCCARD_CCR_OPTION_LEVIREQ;
558 if (pccard_mfc(pf->sc)) {
559 reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE |
560 PCCARD_CCR_OPTION_ADDR_DECODE);
561 /* PCCARD_CCR_OPTION_IRQ_ENABLE set elsewhere as needed */
562 }
563 pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
564
565 reg = 0;
566 if ((pf->cfe->flags & PCCARD_CFE_IO16) == 0)
567 reg |= PCCARD_CCR_STATUS_IOIS8;
568 if (pf->cfe->flags & PCCARD_CFE_AUDIO)
569 reg |= PCCARD_CCR_STATUS_AUDIO;
570 pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg);
571
572 pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0);
573
574 if (pccard_mfc(pf->sc)) {
575 long tmp, iosize;
576
577 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
578 /* round up to nearest (2^n)-1 */
579 for (iosize = 1; iosize < tmp; iosize <<= 1)
580 ;
581 iosize--;
582
583 pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
584 pf->pf_mfc_iobase & 0xff);
585 pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
586 (pf->pf_mfc_iobase >> 8) & 0xff);
587 pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
588 pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
589
590 pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
591 }
592
593#ifdef PCCARDDEBUG
594 if (pccard_debug) {
595 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
596 device_printf(tmp->sc->dev,
597 "function %d CCR at %d offset %x: "
598 "%x %x %x %x, %x %x %x %x, %x\n",
599 tmp->number, tmp->pf_ccr_window,
600 tmp->pf_ccr_offset,
601 pccard_ccr_read(tmp, 0x00),
602 pccard_ccr_read(tmp, 0x02),
603 pccard_ccr_read(tmp, 0x04),
604 pccard_ccr_read(tmp, 0x06),
605 pccard_ccr_read(tmp, 0x0A),
606 pccard_ccr_read(tmp, 0x0C),
607 pccard_ccr_read(tmp, 0x0E),
608 pccard_ccr_read(tmp, 0x10),
609 pccard_ccr_read(tmp, 0x12));
610 }
611 }
612#endif
613 pf->pf_flags |= PFF_ENABLED;
614 return (0);
615
616 bad:
617 /*
618 * Decrement the reference count, and power down the socket, if
619 * necessary.
620 */
621 pf->sc->sc_enabled_count--;
622 DEVPRINTF((dev, "bad --enabled_count = %d\n", pf->sc->sc_enabled_count));
623
624 return (1);
625}
626
627/* Disable PCCARD function. */
628static void
629pccard_function_disable(struct pccard_function *pf)
630{
631 struct pccard_function *tmp;
632 device_t dev = pf->sc->dev;
633
634 if (pf->cfe == NULL)
635 panic("pccard_function_disable: function not initialized");
636
637 if ((pf->pf_flags & PFF_ENABLED) == 0) {
638 /*
639 * Don't do anything if we're already disabled.
640 */
641 return;
642 }
643
644 if (pf->intr_handler != NULL) {
645 struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
646 struct resource_list_entry *rle =
647 resource_list_find(&devi->resources, SYS_RES_IRQ, 0);
648 BUS_TEARDOWN_INTR(dev, pf->dev, rle->res,
649 pf->intr_handler_cookie);
650 }
651
652 /*
653 * it's possible for different functions' CCRs to be in the same
654 * underlying page. Check for that. Note we mark us as disabled
655 * first to avoid matching ourself.
656 */
657
658 pf->pf_flags &= ~PFF_ENABLED;
659 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
660 if ((tmp->pf_flags & PFF_ENABLED) &&
661 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
662 ((pf->ccr_base + PCCARD_CCR_SIZE) <=
663 (tmp->ccr_base - tmp->pf_ccr_offset +
664 tmp->pf_ccr_realsize)))
665 break;
666 }
667
668 /* Not used by anyone else; unmap the CCR. */
669 if (tmp == NULL) {
670 bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
671 pf->ccr_res);
672 pf->ccr_res = NULL;
673 }
674
675 /*
676 * Decrement the reference count, and power down the socket, if
677 * necessary.
678 */
679 pf->sc->sc_enabled_count--;
680}
681
682#if 0
683/* XXX These functions are needed, but not like this XXX */
684int
685pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset,
686 bus_size_t size, struct pccard_io_handle *pcihp, int *windowp)
687{
688 int reg;
689
690 if (pccard_chip_io_map(pf->sc->pct, pf->sc->pch, width, offset, size,
691 pcihp, windowp))
692 return (1);
693
694 /*
695 * XXX in the multifunction multi-iospace-per-function case, this
696 * needs to cooperate with io_alloc to make sure that the spaces
697 * don't overlap, and that the ccr's are set correctly
698 */
699
700 if (pccard_mfc(pf->sc)) {
701 long tmp, iosize;
702
703 if (pf->pf_mfc_iomax == 0) {
704 pf->pf_mfc_iobase = pcihp->addr + offset;
705 pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
706 } else {
707 /* this makes the assumption that nothing overlaps */
708 if (pf->pf_mfc_iobase > pcihp->addr + offset)
709 pf->pf_mfc_iobase = pcihp->addr + offset;
710 if (pf->pf_mfc_iomax < pcihp->addr + offset + size)
711 pf->pf_mfc_iomax = pcihp->addr + offset + size;
712 }
713
714 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
715 /* round up to nearest (2^n)-1 */
716 for (iosize = 1; iosize >= tmp; iosize <<= 1)
717 ;
718 iosize--;
719
720 pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
721 pf->pf_mfc_iobase & 0xff);
722 pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
723 (pf->pf_mfc_iobase >> 8) & 0xff);
724 pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
725 pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
726
727 pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
728
729 reg = pccard_ccr_read(pf, PCCARD_CCR_OPTION);
730 reg |= PCCARD_CCR_OPTION_ADDR_DECODE;
731 pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
732 }
733 return (0);
734}
735
736void
737pccard_io_unmap(struct pccard_function *pf, int window)
738{
739
740 pccard_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
741
742 /* XXX Anything for multi-function cards? */
743}
744#endif
745
746/*
747 * simulate the old "probe" routine. In the new world order, the driver
748 * needs to grab devices while in the old they were assigned to the device by
749 * the pccardd process. These symbols are exported to the upper layers.
750 */
751static int
752pccard_compat_do_probe(device_t bus, device_t dev)
753{
754 return (CARD_COMPAT_MATCH(dev));
755}
756
757static int
758pccard_compat_do_attach(device_t bus, device_t dev)
759{
760 int err;
761
762 err = CARD_COMPAT_PROBE(dev);
763 if (err == 0)
764 err = CARD_COMPAT_ATTACH(dev);
765 return (err);
766}
767
768#define PCCARD_NPORT 2
769#define PCCARD_NMEM 5
770#define PCCARD_NIRQ 1
771#define PCCARD_NDRQ 0
772
773static int
774pccard_add_children(device_t dev, int busno)
775{
776 /* Call parent to scan for any current children */
777 return (0);
778}
779
780static int
781pccard_probe(device_t dev)
782{
783 device_set_desc(dev, "16-bit PCCard bus");
784 return (pccard_add_children(dev, device_get_unit(dev)));
785}
786
787static int
788pccard_attach(device_t dev)
789{
790 struct pccard_softc *sc = PCCARD_SOFTC(dev);
791
792 sc->dev = dev;
793 sc->sc_enabled_count = 0;
794 return (bus_generic_attach(dev));
795}
796
797static int
798pccard_detach(device_t dev)
799{
800 pccard_detach_card(dev, 0);
801 return 0;
802}
803
804static int
805pccard_suspend(device_t self)
806{
807 pccard_detach_card(self, 0);
808 return (0);
809}
810
811static
812int
813pccard_resume(device_t self)
814{
815 return (0);
816}
817
818static void
819pccard_print_resources(struct resource_list *rl, const char *name, int type,
820 int count, const char *format)
821{
822 struct resource_list_entry *rle;
823 int printed;
824 int i;
825
826 printed = 0;
827 for (i = 0; i < count; i++) {
828 rle = resource_list_find(rl, type, i);
829 if (rle != NULL) {
830 if (printed == 0)
831 printf(" %s ", name);
832 else if (printed > 0)
833 printf(",");
834 printed++;
835 printf(format, rle->start);
836 if (rle->count > 1) {
837 printf("-");
838 printf(format, rle->start + rle->count - 1);
839 }
840 } else if (i > 3) {
841 /* check the first few regardless */
842 break;
843 }
844 }
845}
846
847static int
848pccard_print_child(device_t dev, device_t child)
849{
850 struct pccard_ivar *devi = PCCARD_IVAR(child);
851 struct resource_list *rl = &devi->resources;
852 int retval = 0;
853
854 retval += bus_print_child_header(dev, child);
855 retval += printf(" at");
856
857 if (devi != NULL) {
858 pccard_print_resources(rl, "port", SYS_RES_IOPORT,
859 PCCARD_NPORT, "%#lx");
860 pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
861 PCCARD_NMEM, "%#lx");
862 pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
863 "%ld");
864 pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
865 "%ld");
866 retval += printf(" function %d config %d", devi->fcn->number,
867 devi->fcn->cfe->number);
868 }
869
870 retval += bus_print_child_footer(dev, child);
871
872 return (retval);
873}
874
875static int
876pccard_set_resource(device_t dev, device_t child, int type, int rid,
877 u_long start, u_long count)
878{
879 struct pccard_ivar *devi = PCCARD_IVAR(child);
880 struct resource_list *rl = &devi->resources;
881
882 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
883 && type != SYS_RES_IRQ && type != SYS_RES_DRQ)
884 return (EINVAL);
885 if (rid < 0)
886 return (EINVAL);
887 if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
888 return (EINVAL);
889 if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
890 return (EINVAL);
891 if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
892 return (EINVAL);
893 if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
894 return (EINVAL);
895
896 resource_list_add(rl, type, rid, start, start + count - 1, count);
897 if (NULL != resource_list_alloc(rl, device_get_parent(dev), dev,
898 type, &rid, start, start + count - 1, count, 0))
899 return 0;
900 else
901 return ENOMEM;
902}
903
904static int
905pccard_get_resource(device_t dev, device_t child, int type, int rid,
906 u_long *startp, u_long *countp)
907{
908 struct pccard_ivar *devi = PCCARD_IVAR(child);
909 struct resource_list *rl = &devi->resources;
910 struct resource_list_entry *rle;
911
912 rle = resource_list_find(rl, type, rid);
913 if (rle == NULL)
914 return (ENOENT);
915
916 if (startp != NULL)
917 *startp = rle->start;
918 if (countp != NULL)
919 *countp = rle->count;
920
921 return (0);
922}
923
924static void
925pccard_delete_resource(device_t dev, device_t child, int type, int rid)
926{
927 struct pccard_ivar *devi = PCCARD_IVAR(child);
928 struct resource_list *rl = &devi->resources;
929 resource_list_delete(rl, type, rid);
930}
931
932static int
933pccard_set_res_flags(device_t dev, device_t child, int type, int rid,
934 u_int32_t flags)
935{
936 return (CARD_SET_RES_FLAGS(device_get_parent(dev), child, type,
937 rid, flags));
938}
939
940static int
941pccard_set_memory_offset(device_t dev, device_t child, int rid,
942 u_int32_t offset, u_int32_t *deltap)
943
944{
945 return (CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid,
946 offset, deltap));
947}
948
949static int
950pccard_read_ivar(device_t bus, device_t child, int which, u_char *result)
951{
952 struct pccard_ivar *devi = PCCARD_IVAR(child);
953 struct pccard_function *func = devi->fcn;
954 struct pccard_softc *sc = PCCARD_SOFTC(bus);
955
956 /* PCCARD_IVAR_ETHADDR unhandled from oldcard */
957 switch (which) {
958 default:
959 case PCCARD_IVAR_ETHADDR:
960 bcopy(func->pf_funce_lan_nid, result, ETHER_ADDR_LEN);
961 break;
962 case PCCARD_IVAR_VENDOR:
963 *(u_int32_t *) result = sc->card.manufacturer;
964 break;
965 case PCCARD_IVAR_PRODUCT:
966 *(u_int32_t *) result = sc->card.product;
967 break;
968 case PCCARD_IVAR_FUNCTION:
969 *(u_int32_t *) result = func->function;
970 break;
971 case PCCARD_IVAR_FUNCTION_NUMBER:
972 if (!func) {
973 device_printf(bus, "No function number, bug!\n");
974 return (ENOENT);
975 }
976 *(u_int32_t *) result = func->number;
977 break;
978 case PCCARD_IVAR_VENDOR_STR:
979 *(char **) result = sc->card.cis1_info[0];
980 break;
981 case PCCARD_IVAR_PRODUCT_STR:
982 *(char **) result = sc->card.cis1_info[1];
983 break;
984 case PCCARD_IVAR_CIS3_STR:
985 *(char **) result = sc->card.cis1_info[2];
986 break;
987 case PCCARD_IVAR_CIS4_STR:
988 *(char **) result = sc->card.cis1_info[2];
989 break;
990 }
991 return (0);
992}
993
994static void
995pccard_driver_added(device_t dev, driver_t *driver)
996{
997 struct pccard_softc *sc = PCCARD_SOFTC(dev);
998 struct pccard_function *pf;
999 device_t child;
1000
1001 if (sc->sc_enabled_count == 0) {
1002 CARD_REPROBE_CARD(device_get_parent(dev), dev);
1003 return;
1004 }
1005
1006 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
1007 if (STAILQ_EMPTY(&pf->cfe_head))
1008 continue;
1009 child = pf->dev;
1010 if (device_get_state(child) != DS_NOTPRESENT)
1011 continue;
1012 if (pccard_function_enable(pf) == 0 &&
1013 device_probe_and_attach(child) == 0) {
1014 DEVPRINTF((sc->dev, "function %d CCR at %d "
1015 "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
1016 pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
1017 pccard_ccr_read(pf, 0x00),
1018 pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
1019 pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
1020 pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
1021 pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
1022 } else {
1023 if (pf->cfe != NULL)
1024 pccard_function_disable(pf);
1025 }
1026 }
1027 return;
1028}
1029
1030static struct resource *
1031pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
1032 u_long start, u_long end, u_long count, u_int flags)
1033{
1034 struct pccard_ivar *dinfo;
1035 struct resource_list_entry *rle = 0;
1036 int passthrough = (device_get_parent(child) != dev);
1037
1038 if (passthrough) {
1039 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
1040 type, rid, start, end, count, flags));
1041 }
1042
1043 dinfo = device_get_ivars(child);
1044 rle = resource_list_find(&dinfo->resources, type, *rid);
1045
1046 if (!rle)
1047 return NULL; /* no resource of that type/rid */
1048
1049 if (!rle->res) {
1050 device_printf(dev, "WARNING: Resource not reserved by pccard bus\n");
1051 return NULL;
1052 } else {
1053 if (rle->res->r_dev != dev) return NULL;
1054 bus_release_resource(dev, type, *rid, rle->res);
1055 rle->res = NULL;
1056 switch(type) {
1057 case SYS_RES_IOPORT:
1058 case SYS_RES_MEMORY:
1059 if (!(flags & RF_ALIGNMENT_MASK))
1060 flags |= rman_make_alignment_flags(rle->count);
1061 break;
1062 case SYS_RES_IRQ:
1063 flags |= RF_SHAREABLE;
1064 break;
1065 }
1066 return resource_list_alloc(&dinfo->resources, dev, child, type,
1067 rid, rle->start, rle->end, rle->count, flags);
1068 }
1069}
1070
1071static int
1072pccard_release_resource(device_t dev, device_t child, int type, int rid,
1073 struct resource *r)
1074{
1075 struct pccard_ivar *dinfo;
1076 int passthrough = (device_get_parent(child) != dev);
1077 struct resource_list_entry *rle = 0;
1078 int ret;
1079 int flags;
1080
1081 if (passthrough)
1082 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1083 type, rid, r);
1084
1085 dinfo = device_get_ivars(child);
1086
1087 rle = resource_list_find(&dinfo->resources, type, rid);
1088
1089 if (!rle) {
1090 device_printf(dev, "Allocated resource not found, "
1091 "%d %x %lx %lx\n",
1092 type, rid, rman_get_start(r), rman_get_size(r));
1093 return ENOENT;
1094 }
1095 if (!rle->res) {
1096 device_printf(dev, "Allocated resource not recorded\n");
1097 return ENOENT;
1098 }
1099
1100 ret = BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1101 type, rid, r);
1102 switch(type) {
1103 case SYS_RES_IOPORT:
1104 case SYS_RES_MEMORY:
1105 flags = rman_make_alignment_flags(rle->count);
1106 break;
1107 case SYS_RES_IRQ:
1108 flags = RF_SHAREABLE;
1109 break;
1110 default:
1111 flags = 0;
1112 }
1113 rle->res = bus_alloc_resource(dev, type, &rid,
1114 rle->start, rle->end, rle->count, flags);
1115 if (rle->res == NULL)
1116 device_printf(dev, "release_resource: "
1117 "unable to reaquire resource\n");
1118 return ret;
1119}
1120
1121static void
1122pccard_child_detached(device_t parent, device_t dev)
1123{
1124 struct pccard_ivar *ivar = PCCARD_IVAR(dev);
1125 struct pccard_function *pf = ivar->fcn;
1126
1127 pccard_function_disable(pf);
1128}
1129
1130static void
1131pccard_intr(void *arg)
1132{
1133 struct pccard_function *pf = (struct pccard_function*) arg;
1134 int reg;
1135
1136 /*
1137 * If we go to resetting a card, we may need a null interrupt hanlder
1138 * to work (since the system may call it before the device can
1139 * establish an ISR) due to interrupt sharing at a higher level.
1140 */
1141 if (pf->intr_handler == NULL)
1142 panic("Null interrupt handler?\n");
1143
1144 /*
1145 * XXX The CCR_STATUS register bits used here are
1146 * only valid for multi function cards.
1147 */
1148 reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
1149 if (reg & PCCARD_CCR_STATUS_INTR) {
1150 pccard_ccr_write(pf, PCCARD_CCR_STATUS,
1151 reg & ~PCCARD_CCR_STATUS_INTR);
1152 pf->intr_handler(pf->intr_handler_arg);
1153 }
1154}
1155
1156static int
1157pccard_setup_intr(device_t dev, device_t child, struct resource *irq,
1158 int flags, driver_intr_t *intr, void *arg, void **cookiep)
1159{
1160 struct pccard_ivar *ivar = PCCARD_IVAR(child);
1161 struct pccard_function *func = ivar->fcn;
1162
1163 if (func->intr_handler != NULL)
1164 panic("Only one interrupt handler per function allowed\n");
1165
1166 func->intr_handler = intr;
1167 func->intr_handler_arg = arg;
1168 func->intr_handler_cookie = *cookiep;
1169 pccard_ccr_write(func, PCCARD_CCR_OPTION,
1170 pccard_ccr_read(func, PCCARD_CCR_OPTION) |
1171 PCCARD_CCR_OPTION_IREQ_ENABLE);
1172
1173 /*
1174 * XXX Don't use TTY type for our interrupt handler. It makes
1175 * the spl masks wrong on -stable. Instead, we should use the type
1176 * that was requested of us.
1177 */
1178 bus_setup_intr(dev, irq, INTR_TYPE_TTY/* | INTR_FAST*/,
1179 pccard_intr, func, cookiep);
1180 return (0);
1181}
1182
1183static int
1184pccard_teardown_intr(device_t dev, device_t child, struct resource *r,
1185 void *cookie)
1186{
1187 struct pccard_ivar *ivar = PCCARD_IVAR(child);
1188 struct pccard_function *func = ivar->fcn;
1189 int ret;
1190
1191 pccard_ccr_write(func, PCCARD_CCR_OPTION,
1192 pccard_ccr_read(func, PCCARD_CCR_OPTION) &
1193 ~PCCARD_CCR_OPTION_IREQ_ENABLE);
1194
1195 ret = bus_teardown_intr(dev, r, cookie);
1196 if (ret == 0) {
1197 func->intr_handler = NULL;
1198 func->intr_handler_arg = NULL;
1199 func->intr_handler_cookie = NULL;
1200 }
1201
1202 return (ret);
1203}
1204
1205static device_method_t pccard_methods[] = {
1206 /* Device interface */
1207 DEVMETHOD(device_probe, pccard_probe),
1208 DEVMETHOD(device_attach, pccard_attach),
1209 DEVMETHOD(device_detach, pccard_detach),
1210 DEVMETHOD(device_shutdown, bus_generic_shutdown),
1211 DEVMETHOD(device_suspend, pccard_suspend),
1212 DEVMETHOD(device_resume, pccard_resume),
1213
1214 /* Bus interface */
1215 DEVMETHOD(bus_print_child, pccard_print_child),
1216 DEVMETHOD(bus_driver_added, pccard_driver_added),
1217 DEVMETHOD(bus_child_detached, pccard_child_detached),
1218 DEVMETHOD(bus_alloc_resource, pccard_alloc_resource),
1219 DEVMETHOD(bus_release_resource, pccard_release_resource),
1220 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1221 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1222 DEVMETHOD(bus_setup_intr, pccard_setup_intr),
1223 DEVMETHOD(bus_teardown_intr, pccard_teardown_intr),
1224 DEVMETHOD(bus_set_resource, pccard_set_resource),
1225 DEVMETHOD(bus_get_resource, pccard_get_resource),
1226 DEVMETHOD(bus_delete_resource, pccard_delete_resource),
1227 DEVMETHOD(bus_read_ivar, pccard_read_ivar),
1228
1229 /* Card Interface */
1230 DEVMETHOD(card_set_res_flags, pccard_set_res_flags),
1231 DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
1232 DEVMETHOD(card_get_type, pccard_card_gettype),
1233 DEVMETHOD(card_attach_card, pccard_attach_card),
1234 DEVMETHOD(card_detach_card, pccard_detach_card),
1235 DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe),
1236 DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach),
1237
1238 { 0, 0 }
1239};
1240
1241static driver_t pccard_driver = {
1242 "pccard",
1243 pccard_methods,
1244 sizeof(struct pccard_softc)
1245};
1246
1247devclass_t pccard_devclass;
1248
1249DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
1250DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0);
1251DRIVER_MODULE(pccard, pccbb, pccard_driver, pccard_devclass, 0, 0);
1252DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0);
1253MODULE_VERSION(pccard, 1);
1254/*MODULE_DEPEND(pccard, pcic, 1, 1, 1);*/