pcmcia.c revision 1.81 1 /* $NetBSD: pcmcia.c,v 1.81 2006/10/24 20:54:10 drochner Exp $ */
2
3 /*
4 * Copyright (c) 2004 Charles M. Hannum. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Charles M. Hannum.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 */
20
21 /*
22 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 * 3. All advertising materials mentioning features or use of this software
33 * must display the following acknowledgement:
34 * This product includes software developed by Marc Horowitz.
35 * 4. The name of the author may not be used to endorse or promote products
36 * derived from this software without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
42 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
47 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 */
49
50 #include <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.81 2006/10/24 20:54:10 drochner Exp $");
52
53 #include "opt_pcmciaverbose.h"
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/device.h>
58
59 #include <dev/pcmcia/pcmciareg.h>
60 #include <dev/pcmcia/pcmciachip.h>
61 #include <dev/pcmcia/pcmciavar.h>
62 #ifdef IT8368E_LEGACY_MODE /* XXX -uch */
63 #include <arch/hpcmips/dev/it8368var.h>
64 #endif
65
66 #include "locators.h"
67
68 #ifdef PCMCIADEBUG
69 int pcmcia_debug = 0;
70 #define DPRINTF(arg) if (pcmcia_debug) printf arg
71 #else
72 #define DPRINTF(arg)
73 #endif
74
75 #ifdef PCMCIAVERBOSE
76 int pcmcia_verbose = 1;
77 #else
78 int pcmcia_verbose = 0;
79 #endif
80
81 int pcmcia_match(struct device *, struct cfdata *, void *);
82 void pcmcia_attach(struct device *, struct device *, void *);
83 int pcmcia_rescan(struct device *, const char *, const int *);
84 void pcmcia_childdetached(struct device *, struct device *);
85 int pcmcia_print(void *, const char *);
86
87 CFATTACH_DECL2(pcmcia, sizeof(struct pcmcia_softc),
88 pcmcia_match, pcmcia_attach, NULL, NULL,
89 pcmcia_rescan, pcmcia_childdetached);
90
91 int
92 pcmcia_ccr_read(pf, ccr)
93 struct pcmcia_function *pf;
94 int ccr;
95 {
96
97 return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
98 pf->pf_ccr_offset + ccr * 2));
99 }
100
101 void
102 pcmcia_ccr_write(pf, ccr, val)
103 struct pcmcia_function *pf;
104 int ccr;
105 int val;
106 {
107
108 if (pf->ccr_mask & (1 << ccr)) {
109 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
110 pf->pf_ccr_offset + ccr * 2, val);
111 }
112 }
113
114 int
115 pcmcia_match(struct device *parent __unused, struct cfdata *match, void *aux)
116 {
117 struct pcmciabus_attach_args *paa = aux;
118
119 if (strcmp(paa->paa_busname, match->cf_name)) {
120 return 0;
121 }
122 /* if the autoconfiguration got this far, there's a socket here */
123 return (1);
124 }
125
126 void
127 pcmcia_attach(struct device *parent __unused, struct device *self, void *aux)
128 {
129 struct pcmciabus_attach_args *paa = aux;
130 struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
131
132 printf("\n");
133
134 sc->pct = paa->pct;
135 sc->pch = paa->pch;
136 sc->iobase = paa->iobase;
137 sc->iosize = paa->iosize;
138
139 sc->ih = NULL;
140 }
141
142 int
143 pcmcia_card_attach(dev)
144 struct device *dev;
145 {
146 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
147 struct pcmcia_function *pf;
148 int error;
149 static const int wildcard[PCMCIACF_NLOCS] = {
150 PCMCIACF_FUNCTION_DEFAULT
151 };
152
153 /*
154 * this is here so that when socket_enable calls gettype, trt happens
155 */
156 SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
157
158 pcmcia_socket_enable(dev);
159
160 pcmcia_read_cis(sc);
161 pcmcia_check_cis_quirks(sc);
162
163 #if 1 /* XXX remove this, done below ??? */
164 /*
165 * bail now if the card has no functions, or if there was an error in
166 * the cis.
167 */
168 if (sc->card.error ||
169 SIMPLEQ_EMPTY(&sc->card.pf_head)) {
170 printf("%s: card appears to have bogus CIS\n",
171 sc->dev.dv_xname);
172 error = EIO;
173 goto done;
174 }
175 #endif
176
177 if (pcmcia_verbose)
178 pcmcia_print_cis(sc);
179
180 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
181 if (SIMPLEQ_EMPTY(&pf->cfe_head))
182 continue;
183
184 #ifdef DIAGNOSTIC
185 if (pf->child != NULL) {
186 printf("%s: %s still attached to function %d!\n",
187 sc->dev.dv_xname, pf->child->dv_xname,
188 pf->number);
189 panic("pcmcia_card_attach");
190 }
191 #endif
192 pf->sc = sc;
193 pf->child = NULL;
194 pf->cfe = NULL;
195 pf->pf_ih = NULL;
196 }
197
198 error = pcmcia_rescan(dev, "pcmcia", wildcard);
199 done:
200 pcmcia_socket_disable(dev);
201 return (error);
202 }
203
204 int
205 pcmcia_rescan(struct device *self, const char *ifattr __unused,
206 const int *locators)
207 {
208 struct pcmcia_softc *sc = (struct pcmcia_softc *)self;
209 struct pcmcia_function *pf;
210 struct pcmcia_attach_args paa;
211 int locs[PCMCIACF_NLOCS];
212
213 if (sc->card.error ||
214 SIMPLEQ_EMPTY(&sc->card.pf_head)) {
215 /* XXX silently ignore if no card present? */
216 return (EIO);
217 }
218
219 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
220 if (SIMPLEQ_EMPTY(&pf->cfe_head))
221 continue;
222
223 if ((locators[PCMCIACF_FUNCTION] != PCMCIACF_FUNCTION_DEFAULT)
224 && (locators[PCMCIACF_FUNCTION] != pf->number))
225 continue;
226
227 if (pf->child)
228 continue;
229
230 locs[PCMCIACF_FUNCTION] = pf->number;
231
232 paa.manufacturer = sc->card.manufacturer;
233 paa.product = sc->card.product;
234 paa.card = &sc->card;
235 paa.pf = pf;
236
237 pf->child = config_found_sm_loc(self, "pcmcia", locs, &paa,
238 pcmcia_print,
239 config_stdsubmatch);
240 }
241
242 return (0);
243 }
244
245 void
246 pcmcia_card_detach(dev, flags)
247 struct device *dev;
248 int flags; /* DETACH_* flags */
249 {
250 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
251 struct pcmcia_function *pf;
252 int error;
253
254 /*
255 * We are running on either the PCMCIA socket's event thread
256 * or in user context detaching a device by user request.
257 */
258 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
259 pf->pf_flags |= PFF_DETACHED;
260 if (SIMPLEQ_EMPTY(&pf->cfe_head))
261 continue;
262 if (pf->child == NULL)
263 continue;
264 DPRINTF(("%s: detaching %s (function %d)\n",
265 sc->dev.dv_xname, pf->child->dv_xname, pf->number));
266 if ((error = config_detach(pf->child, flags)) != 0) {
267 printf("%s: error %d detaching %s (function %d)\n",
268 sc->dev.dv_xname, error, pf->child->dv_xname,
269 pf->number);
270 }
271 }
272
273 if (sc->sc_enabled_count != 0) {
274 #ifdef DIAGNOSTIC
275 printf("pcmcia_card_detach: enabled_count should be 0 here??\n");
276 #endif
277 pcmcia_chip_socket_disable(sc->pct, sc->pch);
278 sc->sc_enabled_count = 0;
279 }
280 }
281
282 void
283 pcmcia_childdetached(struct device *self, struct device *child)
284 {
285 struct pcmcia_softc *sc = (struct pcmcia_softc *)self;
286 struct pcmcia_function *pf;
287
288 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
289 if (SIMPLEQ_EMPTY(&pf->cfe_head))
290 continue;
291 if (pf->child == child) {
292 KASSERT(device_locator(child, PCMCIACF_FUNCTION)
293 == pf->number);
294 pf->child = NULL;
295 return;
296 }
297 }
298
299 printf("%s: pcmcia_childdetached: %s not found\n",
300 self->dv_xname, child->dv_xname);
301 }
302
303 void
304 pcmcia_card_deactivate(dev)
305 struct device *dev;
306 {
307 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
308 struct pcmcia_function *pf;
309
310 /*
311 * We're in the chip's card removal interrupt handler.
312 * Deactivate the child driver. The PCMCIA socket's
313 * event thread will run later to finish the detach.
314 */
315 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
316 if (SIMPLEQ_EMPTY(&pf->cfe_head))
317 continue;
318 if (pf->child == NULL)
319 continue;
320 DPRINTF(("%s: deactivating %s (function %d)\n",
321 sc->dev.dv_xname, pf->child->dv_xname, pf->number));
322 config_deactivate(pf->child);
323 }
324 }
325
326 int
327 pcmcia_print(arg, pnp)
328 void *arg;
329 const char *pnp;
330 {
331 struct pcmcia_attach_args *pa = arg;
332 struct pcmcia_softc *sc = pa->pf->sc;
333 struct pcmcia_card *card = &sc->card;
334 char devinfo[256];
335
336 if (pnp)
337 aprint_normal("%s", pnp);
338
339 pcmcia_devinfo(card, !!pnp, devinfo, sizeof(devinfo));
340
341 aprint_normal(" function %d: %s\n", pa->pf->number, devinfo);
342
343 return (UNCONF);
344 }
345
346 void
347 pcmcia_devinfo(card, showhex, cp, cplen)
348 struct pcmcia_card *card;
349 int showhex;
350 char *cp;
351 size_t cplen;
352 {
353 int i, n;
354
355 if (cplen > 1) {
356 *cp++ = '<';
357 *cp = '\0';
358 cplen--;
359 }
360
361 for (i = 0; i < 4 && card->cis1_info[i] != NULL && cplen > 1; i++) {
362 n = snprintf(cp, cplen, "%s%s", i ? ", " : "",
363 card->cis1_info[i]);
364 cp += n;
365 if (cplen < n)
366 return;
367 cplen -= n;
368 }
369
370 if (cplen > 1) {
371 *cp++ = '>';
372 *cp = '\0';
373 cplen--;
374 }
375
376 if (showhex && cplen > 1)
377 snprintf(cp, cplen, " (manufacturer 0x%04x, product 0x%04x)",
378 card->manufacturer, card->product);
379 }
380
381 const void *
382 pcmcia_product_lookup(pa, tab, nent, ent_size, matchfn)
383 struct pcmcia_attach_args *pa;
384 const void *tab;
385 size_t nent;
386 size_t ent_size;
387 pcmcia_product_match_fn matchfn;
388 {
389 const struct pcmcia_product *pp;
390 int n;
391 int matches;
392
393 #ifdef DIAGNOSTIC
394 if (sizeof *pp > ent_size)
395 panic("pcmcia_product_lookup: bogus ent_size %ld",
396 (long) ent_size);
397 #endif
398
399 for (pp = tab, n = nent; n; pp = (const struct pcmcia_product *)
400 ((const char *)pp + ent_size), n--) {
401 /* see if it matches vendor/product */
402 matches = 0;
403 if ((pp->pp_vendor != PCMCIA_VENDOR_INVALID &&
404 pp->pp_vendor == pa->manufacturer) &&
405 (pp->pp_product != PCMCIA_PRODUCT_INVALID &&
406 pp->pp_product == pa->product))
407 matches = 1;
408 if ((pp->pp_cisinfo[0] && pa->card->cis1_info[0] &&
409 !strcmp(pp->pp_cisinfo[0], pa->card->cis1_info[0])) &&
410 (pp->pp_cisinfo[1] && pa->card->cis1_info[1] &&
411 !strcmp(pp->pp_cisinfo[1], pa->card->cis1_info[1])) &&
412 (!pp->pp_cisinfo[2] || (pa->card->cis1_info[2] &&
413 !strcmp(pp->pp_cisinfo[2], pa->card->cis1_info[2]))) &&
414 (!pp->pp_cisinfo[3] || (pa->card->cis1_info[3] &&
415 !strcmp(pp->pp_cisinfo[3], pa->card->cis1_info[3]))))
416 matches = 1;
417
418 /* if a separate match function is given, let it override */
419 if (matchfn)
420 matches = (*matchfn)(pa, pp, matches);
421
422 if (matches)
423 return (pp);
424 }
425 return (0);
426 }
427
428 void
429 pcmcia_socket_settype(dev, type)
430 struct device *dev;
431 int type;
432 {
433 struct pcmcia_softc *sc = (void *)dev;
434
435 pcmcia_chip_socket_settype(sc->pct, sc->pch, type);
436 }
437
438 /*
439 * Initialize a PCMCIA function. May be called as long as the function is
440 * disabled.
441 */
442 void
443 pcmcia_function_init(pf, cfe)
444 struct pcmcia_function *pf;
445 struct pcmcia_config_entry *cfe;
446 {
447 if (pf->pf_flags & PFF_ENABLED)
448 panic("pcmcia_function_init: function is enabled");
449
450 /* Remember which configuration entry we are using. */
451 pf->cfe = cfe;
452 }
453
454 void
455 pcmcia_socket_enable(dev)
456 struct device *dev;
457 {
458 struct pcmcia_softc *sc = (void *)dev;
459
460 if (sc->sc_enabled_count++ == 0)
461 pcmcia_chip_socket_enable(sc->pct, sc->pch);
462 DPRINTF(("%s: ++enabled_count = %d\n", sc->dev.dv_xname,
463 sc->sc_enabled_count));
464 }
465
466 void
467 pcmcia_socket_disable(dev)
468 struct device *dev;
469 {
470 struct pcmcia_softc *sc = (void *)dev;
471
472 if (--sc->sc_enabled_count == 0)
473 pcmcia_chip_socket_disable(sc->pct, sc->pch);
474 DPRINTF(("%s: --enabled_count = %d\n", sc->dev.dv_xname,
475 sc->sc_enabled_count));
476 }
477
478 /* Enable a PCMCIA function */
479 int
480 pcmcia_function_enable(pf)
481 struct pcmcia_function *pf;
482 {
483 struct pcmcia_softc *sc = pf->sc;
484 struct pcmcia_function *tmp;
485 int reg;
486 int error;
487
488 if (pf->cfe == NULL)
489 panic("pcmcia_function_enable: function not initialized");
490
491 /*
492 * Increase the reference count on the socket, enabling power, if
493 * necessary.
494 */
495 pcmcia_socket_enable(&sc->dev);
496 pcmcia_socket_settype(&sc->dev, pf->cfe->iftype);
497
498 if (pf->pf_flags & PFF_ENABLED) {
499 /*
500 * Don't do anything if we're already enabled.
501 */
502 return (0);
503 }
504
505 /*
506 * it's possible for different functions' CCRs to be in the same
507 * underlying page. Check for that.
508 */
509
510 SIMPLEQ_FOREACH(tmp, &sc->card.pf_head, pf_list) {
511 if ((tmp->pf_flags & PFF_ENABLED) &&
512 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
513 ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
514 (tmp->ccr_base - tmp->pf_ccr_offset +
515 tmp->pf_ccr_realsize))) {
516 pf->pf_ccrt = tmp->pf_ccrt;
517 pf->pf_ccrh = tmp->pf_ccrh;
518 pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
519
520 /*
521 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
522 * tmp->ccr_base) + pf->ccr_base;
523 */
524 pf->pf_ccr_offset =
525 (tmp->pf_ccr_offset + pf->ccr_base) -
526 tmp->ccr_base;
527 pf->pf_ccr_window = tmp->pf_ccr_window;
528 break;
529 }
530 }
531
532 if (tmp == NULL) {
533 error = pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh);
534 if (error)
535 goto bad;
536
537 error = pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
538 PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
539 &pf->pf_ccr_window);
540 if (error) {
541 pcmcia_mem_free(pf, &pf->pf_pcmh);
542 goto bad;
543 }
544 }
545
546 if (pcmcia_mfc(sc) || 1) {
547 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
548 (pf->pf_mfc_iobase >> 0) & 0xff);
549 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
550 (pf->pf_mfc_iobase >> 8) & 0xff);
551 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
552 (pf->pf_mfc_iobase >> 16) & 0xff);
553 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
554 (pf->pf_mfc_iobase >> 24) & 0xff);
555 pcmcia_ccr_write(pf, PCMCIA_CCR_IOLIMIT,
556 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
557 }
558
559 reg = 0;
560 if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
561 reg |= PCMCIA_CCR_STATUS_AUDIO;
562 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
563
564 pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
565
566 reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
567 reg |= PCMCIA_CCR_OPTION_LEVIREQ;
568 if (pcmcia_mfc(sc)) {
569 reg |= (PCMCIA_CCR_OPTION_FUNC_ENABLE |
570 PCMCIA_CCR_OPTION_ADDR_DECODE);
571 if (pf->pf_ih)
572 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
573
574 }
575 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
576
577 #ifdef PCMCIADEBUG
578 if (pcmcia_debug) {
579 SIMPLEQ_FOREACH(tmp, &sc->card.pf_head, pf_list) {
580 printf("%s: function %d CCR at %d offset %lx: "
581 "%x %x %x %x, %x %x %x %x, %x\n",
582 tmp->sc->dev.dv_xname, tmp->number,
583 tmp->pf_ccr_window,
584 (unsigned long) tmp->pf_ccr_offset,
585 pcmcia_ccr_read(tmp, 0),
586 pcmcia_ccr_read(tmp, 1),
587 pcmcia_ccr_read(tmp, 2),
588 pcmcia_ccr_read(tmp, 3),
589
590 pcmcia_ccr_read(tmp, 5),
591 pcmcia_ccr_read(tmp, 6),
592 pcmcia_ccr_read(tmp, 7),
593 pcmcia_ccr_read(tmp, 8),
594
595 pcmcia_ccr_read(tmp, 9));
596 }
597 }
598 #endif
599
600 #ifdef IT8368E_LEGACY_MODE
601 /* return to I/O mode */
602 it8368_mode(pf, IT8368_IO_MODE, IT8368_WIDTH_16);
603 #endif
604
605 pf->pf_flags |= PFF_ENABLED;
606 return (0);
607
608 bad:
609 /*
610 * Decrement the reference count, and power down the socket, if
611 * necessary.
612 */
613 printf("%s: couldn't map the CCR\n", pf->child->dv_xname);
614 pcmcia_socket_disable(&sc->dev);
615
616 return (error);
617 }
618
619 /* Disable PCMCIA function. */
620 void
621 pcmcia_function_disable(pf)
622 struct pcmcia_function *pf;
623 {
624 struct pcmcia_softc *sc = pf->sc;
625 struct pcmcia_function *tmp;
626 int reg;
627
628 if (pf->cfe == NULL)
629 panic("pcmcia_function_enable: function not initialized");
630
631 if ((pf->pf_flags & PFF_ENABLED) == 0) {
632 /*
633 * Don't do anything but decrement if we're already disabled.
634 */
635 goto out;
636 }
637
638 if (pcmcia_mfc(sc) &&
639 (pf->pf_flags & PFF_DETACHED) == 0) {
640 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
641 reg &= ~(PCMCIA_CCR_OPTION_FUNC_ENABLE|
642 PCMCIA_CCR_OPTION_ADDR_DECODE|
643 PCMCIA_CCR_OPTION_IREQ_ENABLE);
644 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
645 }
646
647 /*
648 * it's possible for different functions' CCRs to be in the same
649 * underlying page. Check for that. Note we mark us as disabled
650 * first to avoid matching ourself.
651 */
652
653 pf->pf_flags &= ~PFF_ENABLED;
654 SIMPLEQ_FOREACH(tmp, &sc->card.pf_head, pf_list) {
655 if ((tmp->pf_flags & PFF_ENABLED) &&
656 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
657 ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
658 (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
659 break;
660 }
661
662 /* Not used by anyone else; unmap the CCR. */
663 if (tmp == NULL) {
664 pcmcia_mem_unmap(pf, pf->pf_ccr_window);
665 pcmcia_mem_free(pf, &pf->pf_pcmh);
666 }
667
668 out:
669 /*
670 * Decrement the reference count, and power down the socket, if
671 * necessary.
672 */
673 pcmcia_socket_disable(&sc->dev);
674 }
675
676 int
677 pcmcia_io_map(pf, width, pcihp, windowp)
678 struct pcmcia_function *pf;
679 int width;
680 struct pcmcia_io_handle *pcihp;
681 int *windowp;
682 {
683 struct pcmcia_softc *sc = pf->sc;
684 int error;
685
686 if (pf->pf_flags & PFF_ENABLED)
687 printf("pcmcia_io_map: function is enabled!\n");
688
689 error = pcmcia_chip_io_map(sc->pct, sc->pch,
690 width, 0, pcihp->size, pcihp, windowp);
691 if (error)
692 return (error);
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 (pcmcia_mfc(sc) || 1) {
701 bus_addr_t iobase = pcihp->addr;
702 bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
703
704 DPRINTF(("window iobase %lx iomax %lx\n", (long)iobase,
705 (long)iomax));
706 if (pf->pf_mfc_iobase == 0) {
707 pf->pf_mfc_iobase = iobase;
708 pf->pf_mfc_iomax = iomax;
709 } else {
710 if (iobase < pf->pf_mfc_iobase)
711 pf->pf_mfc_iobase = iobase;
712 if (iomax > pf->pf_mfc_iomax)
713 pf->pf_mfc_iomax = iomax;
714 }
715 DPRINTF(("function iobase %lx iomax %lx\n",
716 (long)pf->pf_mfc_iobase, (long)pf->pf_mfc_iomax));
717 }
718
719 return (0);
720 }
721
722 void
723 pcmcia_io_unmap(pf, window)
724 struct pcmcia_function *pf;
725 int window;
726 {
727 struct pcmcia_softc *sc = pf->sc;
728
729 if (pf->pf_flags & PFF_ENABLED)
730 printf("pcmcia_io_unmap: function is enabled!\n");
731
732 pcmcia_chip_io_unmap(sc->pct, sc->pch, window);
733 }
734
735 void *
736 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
737 struct pcmcia_function *pf;
738 int ipl;
739 int (*ih_fct)(void *);
740 void *ih_arg;
741 {
742
743 if (pf->pf_flags & PFF_ENABLED)
744 printf("pcmcia_intr_establish: function is enabled!\n");
745 if (pf->pf_ih)
746 panic("pcmcia_intr_establish: already done\n");
747
748 pf->pf_ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
749 pf, ipl, ih_fct, ih_arg);
750 if (!pf->pf_ih)
751 printf("%s: interrupt establish failed\n", pf->child->dv_xname);
752 return (pf->pf_ih);
753 }
754
755 void
756 pcmcia_intr_disestablish(pf, ih)
757 struct pcmcia_function *pf;
758 void *ih;
759 {
760
761 if (pf->pf_flags & PFF_ENABLED)
762 printf("pcmcia_intr_disestablish: function is enabled!\n");
763 if (!pf->pf_ih)
764 panic("pcmcia_intr_distestablish: already done\n");
765
766 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
767 pf->pf_ih = 0;
768 }
769
770 int
771 pcmcia_config_alloc(pf, cfe)
772 struct pcmcia_function *pf;
773 struct pcmcia_config_entry *cfe;
774 {
775 int error = 0;
776 int n, m;
777
778 for (n = 0; n < cfe->num_iospace; n++) {
779 bus_addr_t start = cfe->iospace[n].start;
780 bus_size_t length = cfe->iospace[n].length;
781 bus_size_t align = cfe->iomask ? (1 << cfe->iomask) :
782 length;
783 bus_size_t skew = start & (align - 1);
784
785 if ((start - skew) == 0 && align < 0x400) {
786 if (skew)
787 printf("Drats! I need a skew!\n");
788 start = 0;
789 }
790
791 DPRINTF(("pcmcia_config_alloc: io %d start=%lx length=%lx align=%lx skew=%lx\n",
792 n, (long)start, (long)length, (long)align, (long)skew));
793
794 error = pcmcia_io_alloc(pf, start, length, align,
795 &cfe->iospace[n].handle);
796 if (error)
797 break;
798 }
799 if (n < cfe->num_iospace) {
800 for (m = 0; m < n; m++)
801 pcmcia_io_free(pf, &cfe->iospace[m].handle);
802 return (error);
803 }
804
805 for (n = 0; n < cfe->num_memspace; n++) {
806 bus_size_t length = cfe->memspace[n].length;
807
808 DPRINTF(("pcmcia_config_alloc: mem %d length %lx\n", n,
809 (long)length));
810
811 error = pcmcia_mem_alloc(pf, length, &cfe->memspace[n].handle);
812 if (error)
813 break;
814 }
815 if (n < cfe->num_memspace) {
816 for (m = 0; m < cfe->num_iospace; m++)
817 pcmcia_io_free(pf, &cfe->iospace[m].handle);
818 for (m = 0; m < n; m++)
819 pcmcia_mem_free(pf, &cfe->memspace[m].handle);
820 return (error);
821 }
822
823 /* This one's good! */
824 return (error);
825 }
826
827 void
828 pcmcia_config_free(pf)
829 struct pcmcia_function *pf;
830 {
831 struct pcmcia_config_entry *cfe = pf->cfe;
832 int m;
833
834 for (m = 0; m < cfe->num_iospace; m++)
835 pcmcia_io_free(pf, &cfe->iospace[m].handle);
836 for (m = 0; m < cfe->num_memspace; m++)
837 pcmcia_mem_free(pf, &cfe->memspace[m].handle);
838 }
839
840 int
841 pcmcia_config_map(pf)
842 struct pcmcia_function *pf;
843 {
844 struct pcmcia_config_entry *cfe = pf->cfe;
845 int error = 0;
846 int n, m;
847
848 for (n = 0; n < cfe->num_iospace; n++) {
849 int width;
850
851 if (cfe->flags & PCMCIA_CFE_IO16)
852 width = PCMCIA_WIDTH_AUTO;
853 else
854 width = PCMCIA_WIDTH_IO8;
855 error = pcmcia_io_map(pf, width, &cfe->iospace[n].handle,
856 &cfe->iospace[n].window);
857 if (error)
858 break;
859 }
860 if (n < cfe->num_iospace) {
861 for (m = 0; m < n; m++)
862 pcmcia_io_unmap(pf, cfe->iospace[m].window);
863 return (error);
864 }
865
866 for (n = 0; n < cfe->num_memspace; n++) {
867 bus_size_t length = cfe->memspace[n].length;
868 int width;
869
870 DPRINTF(("pcmcia_config_alloc: mem %d length %lx\n", n,
871 (long)length));
872
873 /*XXX*/
874 width = PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON;
875 error = pcmcia_mem_map(pf, width, 0, length,
876 &cfe->memspace[n].handle, &cfe->memspace[n].offset,
877 &cfe->memspace[n].window);
878 if (error)
879 break;
880 }
881 if (n < cfe->num_memspace) {
882 for (m = 0; m < cfe->num_iospace; m++)
883 pcmcia_io_unmap(pf, cfe->iospace[m].window);
884 for (m = 0; m < n; m++)
885 pcmcia_mem_unmap(pf, cfe->memspace[m].window);
886 return (error);
887 }
888
889 /* This one's good! */
890 return (error);
891 }
892
893 void
894 pcmcia_config_unmap(pf)
895 struct pcmcia_function *pf;
896 {
897 struct pcmcia_config_entry *cfe = pf->cfe;
898 int m;
899
900 for (m = 0; m < cfe->num_iospace; m++)
901 pcmcia_io_unmap(pf, cfe->iospace[m].window);
902 for (m = 0; m < cfe->num_memspace; m++)
903 pcmcia_mem_unmap(pf, cfe->memspace[m].window);
904 }
905
906 int
907 pcmcia_function_configure(pf, validator)
908 struct pcmcia_function *pf;
909 int (*validator)(struct pcmcia_config_entry *);
910 {
911 struct pcmcia_config_entry *cfe;
912 int error = ENOENT;
913
914 SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
915 error = validator(cfe);
916 if (error)
917 continue;
918 error = pcmcia_config_alloc(pf, cfe);
919 if (!error)
920 break;
921 }
922 if (!cfe) {
923 DPRINTF(("pcmcia_function_configure: no config entry found, error=%d\n",
924 error));
925 return (error);
926 }
927
928 /* Remember which configuration entry we are using. */
929 pf->cfe = cfe;
930
931 error = pcmcia_config_map(pf);
932 if (error) {
933 DPRINTF(("pcmcia_function_configure: map failed, error=%d\n",
934 error));
935 return (error);
936 }
937
938 return (0);
939 }
940
941 void
942 pcmcia_function_unconfigure(pf)
943 struct pcmcia_function *pf;
944 {
945
946 pcmcia_config_unmap(pf);
947 pcmcia_config_free(pf);
948 }
949