isapnp.c revision 1.30 1 /* $NetBSD: isapnp.c,v 1.30 1998/11/21 23:38:11 fvdl Exp $ */
2
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * ISA PnP bus autoconfiguration.
41 */
42
43 #include "isadma.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/device.h>
48 #include <sys/malloc.h>
49
50 #include <machine/bus.h>
51
52 #include <dev/isa/isavar.h>
53
54 #include <dev/isapnp/isapnpreg.h>
55 #include <dev/isapnp/isapnpvar.h>
56 #include <dev/isapnp/isapnpdevs.h>
57
58 static void isapnp_init __P((struct isapnp_softc *));
59 static __inline u_char isapnp_shift_bit __P((struct isapnp_softc *));
60 static int isapnp_findcard __P((struct isapnp_softc *));
61 static void isapnp_free_region __P((bus_space_tag_t, struct isapnp_region *));
62 static int isapnp_alloc_region __P((bus_space_tag_t, struct isapnp_region *));
63 static int isapnp_alloc_irq __P((isa_chipset_tag_t, struct isapnp_pin *));
64 static int isapnp_alloc_drq __P((isa_chipset_tag_t, struct isapnp_pin *));
65 static int isapnp_testconfig __P((bus_space_tag_t, bus_space_tag_t,
66 struct isapnp_attach_args *, int));
67 static struct isapnp_attach_args *isapnp_bestconfig __P((struct isapnp_softc *,
68 struct isapnp_attach_args **));
69 static void isapnp_print_region __P((const char *, struct isapnp_region *,
70 size_t));
71 static void isapnp_configure __P((struct isapnp_softc *,
72 const struct isapnp_attach_args *));
73 static void isapnp_print_pin __P((const char *, struct isapnp_pin *, size_t));
74 static int isapnp_print __P((void *, const char *));
75 #ifdef _KERNEL
76 static int isapnp_submatch __P((struct device *, struct cfdata *, void *));
77 #endif
78 static int isapnp_find __P((struct isapnp_softc *, int));
79 static int isapnp_match __P((struct device *, struct cfdata *, void *));
80 static void isapnp_attach __P((struct device *, struct device *, void *));
81 static void isapnp_callback __P((struct device *));
82
83 struct cfattach isapnp_ca = {
84 sizeof(struct isapnp_softc), isapnp_match, isapnp_attach
85 };
86
87 /*
88 * This keeps track if which ISA's we have been probed on.
89 */
90 struct isapnp_probe_cookie {
91 LIST_ENTRY(isapnp_probe_cookie) ipc_link;
92 struct device *ipc_parent;
93 };
94 LIST_HEAD(, isapnp_probe_cookie) isapnp_probes =
95 LIST_HEAD_INITIALIZER(isapnp_probes);
96
97 /* isapnp_init():
98 * Write the PNP initiation key to wake up the cards...
99 */
100 static void
101 isapnp_init(sc)
102 struct isapnp_softc *sc;
103 {
104 int i;
105 u_char v = ISAPNP_LFSR_INIT;
106
107 /* First write 0's twice to enter the Wait for Key state */
108 ISAPNP_WRITE_ADDR(sc, 0);
109 ISAPNP_WRITE_ADDR(sc, 0);
110
111 /* Send the 32 byte sequence to awake the logic */
112 for (i = 0; i < ISAPNP_LFSR_LENGTH; i++) {
113 ISAPNP_WRITE_ADDR(sc, v);
114 v = ISAPNP_LFSR_NEXT(v);
115 }
116 }
117
118
119 /* isapnp_shift_bit():
120 * Read a bit at a time from the config card.
121 */
122 static __inline u_char
123 isapnp_shift_bit(sc)
124 struct isapnp_softc *sc;
125 {
126 u_char c1, c2;
127
128 DELAY(250);
129 c1 = ISAPNP_READ_DATA(sc);
130 DELAY(250);
131 c2 = ISAPNP_READ_DATA(sc);
132
133 if (c1 == 0x55 && c2 == 0xAA)
134 return 0x80;
135 else
136 return 0;
137 }
138
139
140 /* isapnp_findcard():
141 * Attempt to read the vendor/serial/checksum for a card
142 * If a card is found [the checksum matches], assign the
143 * next card number to it and return 1
144 */
145 static int
146 isapnp_findcard(sc)
147 struct isapnp_softc *sc;
148 {
149 u_char v = ISAPNP_LFSR_INIT, csum, w;
150 int i, b;
151
152 if (sc->sc_ncards == ISAPNP_MAX_CARDS) {
153 printf("%s: Too many pnp cards\n", sc->sc_dev.dv_xname);
154 return 0;
155 }
156
157 /* Set the read port */
158 isapnp_write_reg(sc, ISAPNP_WAKE, 0);
159 isapnp_write_reg(sc, ISAPNP_SET_RD_PORT, sc->sc_read_port >> 2);
160 sc->sc_read_port |= 3;
161 DELAY(1000);
162
163 ISAPNP_WRITE_ADDR(sc, ISAPNP_SERIAL_ISOLATION);
164 DELAY(1000);
165
166 /* Read the 8 bytes of the Vendor ID and Serial Number */
167 for(i = 0; i < 8; i++) {
168 /* Read each bit separately */
169 for (w = 0, b = 0; b < 8; b++) {
170 u_char neg = isapnp_shift_bit(sc);
171
172 w >>= 1;
173 w |= neg;
174 v = ISAPNP_LFSR_NEXT(v) ^ neg;
175 }
176 sc->sc_id[sc->sc_ncards][i] = w;
177 }
178
179 /* Read the remaining checksum byte */
180 for (csum = 0, b = 0; b < 8; b++) {
181 u_char neg = isapnp_shift_bit(sc);
182
183 csum >>= 1;
184 csum |= neg;
185 }
186 sc->sc_id[sc->sc_ncards][8] = csum;
187
188 if (csum == v) {
189 sc->sc_ncards++;
190 isapnp_write_reg(sc, ISAPNP_CARD_SELECT_NUM, sc->sc_ncards);
191 return 1;
192 }
193 return 0;
194 }
195
196
197 /* isapnp_free_region():
198 * Free a region
199 */
200 static void
201 isapnp_free_region(t, r)
202 bus_space_tag_t t;
203 struct isapnp_region *r;
204 {
205 #ifdef _KERNEL
206 bus_space_unmap(t, r->h, r->length);
207 #endif
208 }
209
210
211 /* isapnp_alloc_region():
212 * Allocate a single region if possible
213 */
214 static int
215 isapnp_alloc_region(t, r)
216 bus_space_tag_t t;
217 struct isapnp_region *r;
218 {
219 int error = 0;
220
221 for (r->base = r->minbase; r->base <= r->maxbase;
222 r->base += r->align) {
223 #ifdef _KERNEL
224 error = bus_space_map(t, r->base, r->length, 0, &r->h);
225 #endif
226 if (error == 0)
227 return 0;
228 if (r->align == 0)
229 break;
230 }
231 return error;
232 }
233
234
235 /* isapnp_alloc_irq():
236 * Allocate an irq
237 */
238 static int
239 isapnp_alloc_irq(ic, i)
240 isa_chipset_tag_t ic;
241 struct isapnp_pin *i;
242 {
243 int irq;
244 #define LEVEL_IRQ (ISAPNP_IRQTYPE_LEVEL_PLUS|ISAPNP_IRQTYPE_LEVEL_MINUS)
245 i->type = (i->flags & LEVEL_IRQ) ? IST_LEVEL : IST_EDGE;
246
247 if (i->bits == 0) {
248 i->num = 0;
249 return 0;
250 }
251
252 if (isa_intr_alloc(ic, i->bits, i->type, &irq) == 0) {
253 i->num = irq;
254 return 0;
255 }
256
257 return EINVAL;
258 }
259
260 /* isapnp_alloc_drq():
261 * Allocate a drq
262 */
263 static int
264 isapnp_alloc_drq(ic, i)
265 isa_chipset_tag_t ic;
266 struct isapnp_pin *i;
267 {
268 #if NISADMA > 0
269 int b;
270
271 if (i->bits == 0) {
272 i->num = 0;
273 return 0;
274 }
275
276 for (b = 0; b < 8; b++)
277 if ((i->bits & (1 << b)) && isa_drq_isfree(ic, b)) {
278 i->num = b;
279 return 0;
280 }
281 #endif /* NISADMA > 0 */
282
283 return EINVAL;
284 }
285
286 /* isapnp_testconfig():
287 * Test/Allocate the regions used
288 */
289 static int
290 isapnp_testconfig(iot, memt, ipa, alloc)
291 bus_space_tag_t iot, memt;
292 struct isapnp_attach_args *ipa;
293 int alloc;
294 {
295 int nio = 0, nmem = 0, nmem32 = 0, nirq = 0, ndrq = 0;
296 int error = 0;
297
298 #ifdef DEBUG_ISAPNP
299 isapnp_print_attach(ipa);
300 #endif
301
302 for (; nio < ipa->ipa_nio; nio++) {
303 error = isapnp_alloc_region(iot, &ipa->ipa_io[nio]);
304 if (error)
305 goto bad;
306 }
307
308 for (; nmem < ipa->ipa_nmem; nmem++) {
309 error = isapnp_alloc_region(memt, &ipa->ipa_mem[nmem]);
310 if (error)
311 goto bad;
312 }
313
314 for (; nmem32 < ipa->ipa_nmem32; nmem32++) {
315 error = isapnp_alloc_region(memt, &ipa->ipa_mem32[nmem32]);
316 if (error)
317 goto bad;
318 }
319
320 for (; nirq < ipa->ipa_nirq; nirq++) {
321 error = isapnp_alloc_irq(ipa->ipa_ic, &ipa->ipa_irq[nirq]);
322 if (error)
323 goto bad;
324 }
325
326 for (; ndrq < ipa->ipa_ndrq; ndrq++) {
327 error = isapnp_alloc_drq(ipa->ipa_ic, &ipa->ipa_drq[ndrq]);
328 if (error)
329 goto bad;
330 }
331
332 if (alloc)
333 return error;
334
335 bad:
336 #ifdef notyet
337 for (ndrq--; ndrq >= 0; ndrq--)
338 isapnp_free_pin(&ipa->ipa_drq[ndrq]);
339
340 for (nirq--; nirq >= 0; nirq--)
341 isapnp_free_pin(&ipa->ipa_irq[nirq]);
342 #endif
343
344 for (nmem32--; nmem32 >= 0; nmem32--)
345 isapnp_free_region(memt, &ipa->ipa_mem32[nmem32]);
346
347 for (nmem--; nmem >= 0; nmem--)
348 isapnp_free_region(memt, &ipa->ipa_mem[nmem]);
349
350 for (nio--; nio >= 0; nio--)
351 isapnp_free_region(iot, &ipa->ipa_io[nio]);
352
353 return error;
354 }
355
356
357 /* isapnp_config():
358 * Test/Allocate the regions used
359 */
360 int
361 isapnp_config(iot, memt, ipa)
362 bus_space_tag_t iot, memt;
363 struct isapnp_attach_args *ipa;
364 {
365 return isapnp_testconfig(iot, memt, ipa, 1);
366 }
367
368
369 /* isapnp_unconfig():
370 * Free the regions used
371 */
372 void
373 isapnp_unconfig(iot, memt, ipa)
374 bus_space_tag_t iot, memt;
375 struct isapnp_attach_args *ipa;
376 {
377 int i;
378
379 #ifdef notyet
380 for (i = 0; i < ipa->ipa_ndrq; i++)
381 isapnp_free_pin(&ipa->ipa_drq[i]);
382
383 for (i = 0; i < ipa->ipa_nirq; i++)
384 isapnp_free_pin(&ipa->ipa_irq[i]);
385 #endif
386
387 for (i = 0; i < ipa->ipa_nmem32; i++)
388 isapnp_free_region(memt, &ipa->ipa_mem32[i]);
389
390 for (i = 0; i < ipa->ipa_nmem; i++)
391 isapnp_free_region(memt, &ipa->ipa_mem[i]);
392
393 for (i = 0; i < ipa->ipa_nio; i++)
394 isapnp_free_region(iot, &ipa->ipa_io[i]);
395 }
396
397
398 /* isapnp_bestconfig():
399 * Return the best configuration for each logical device, remove and
400 * free all other configurations.
401 */
402 static struct isapnp_attach_args *
403 isapnp_bestconfig(sc, ipa)
404 struct isapnp_softc *sc;
405 struct isapnp_attach_args **ipa;
406 {
407 struct isapnp_attach_args *c, *best, *f = *ipa;
408 int error;
409
410 for (;;) {
411 if (f == NULL)
412 return NULL;
413
414 #define SAMEDEV(a, b) (strcmp((a)->ipa_devlogic, (b)->ipa_devlogic) == 0)
415
416 /* Find the best config */
417 for (best = c = f; c != NULL; c = c->ipa_sibling) {
418 if (!SAMEDEV(c, f))
419 continue;
420 if (c->ipa_pref < best->ipa_pref)
421 best = c;
422 }
423
424 /*
425 * Make sure the ISA chipset is initialized! We need
426 * it to test the best config!
427 */
428 best->ipa_ic = sc->sc_ic;
429
430 /* Test the best config */
431 error = isapnp_testconfig(sc->sc_iot, sc->sc_memt, best, 0);
432
433 /* Remove this config from the list */
434 if (best == f)
435 f = f->ipa_sibling;
436 else {
437 for (c = f; c->ipa_sibling != best; c = c->ipa_sibling)
438 continue;
439 c->ipa_sibling = best->ipa_sibling;
440 }
441
442 if (error) {
443 best->ipa_pref = ISAPNP_DEP_CONFLICTING;
444
445 for (c = f; c != NULL; c = c->ipa_sibling)
446 if (c != best && SAMEDEV(c, best))
447 break;
448 /* Last config for this logical device is conflicting */
449 if (c == NULL) {
450 *ipa = f;
451 return best;
452 }
453
454 ISAPNP_FREE(best);
455 continue;
456 }
457 else {
458 /* Remove all other configs for this device */
459 struct isapnp_attach_args *l = NULL, *n = NULL, *d;
460
461 for (c = f; c; ) {
462 if (c == best)
463 continue;
464 d = c->ipa_sibling;
465 if (SAMEDEV(c, best))
466 ISAPNP_FREE(c);
467 else {
468 if (n)
469 n->ipa_sibling = c;
470
471 else
472 l = c;
473 n = c;
474 c->ipa_sibling = NULL;
475 }
476 c = d;
477 }
478 f = l;
479 }
480 *ipa = f;
481 return best;
482 }
483 }
484
485
486 /* isapnp_id_to_vendor():
487 * Convert a pnp ``compressed ascii'' vendor id to a string
488 */
489 char *
490 isapnp_id_to_vendor(v, id)
491 char *v;
492 const u_char *id;
493 {
494 static const char hex[] = "0123456789ABCDEF";
495 char *p = v;
496
497 *p++ = 'A' + (id[0] >> 2) - 1;
498 *p++ = 'A' + ((id[0] & 3) << 3) + (id[1] >> 5) - 1;
499 *p++ = 'A' + (id[1] & 0x1f) - 1;
500 *p++ = hex[id[2] >> 4];
501 *p++ = hex[id[2] & 0x0f];
502 *p++ = hex[id[3] >> 4];
503 *p++ = hex[id[3] & 0x0f];
504 *p = '\0';
505
506 return v;
507 }
508
509
510 /* isapnp_print_region():
511 * Print a region allocation
512 */
513 static void
514 isapnp_print_region(str, r, n)
515 const char *str;
516 struct isapnp_region *r;
517 size_t n;
518 {
519 size_t i;
520
521 if (n == 0)
522 return;
523
524 printf(" %s ", str);
525 for (i = 0; i < n; i++, r++) {
526 printf("0x%x", r->base);
527 if (r->length)
528 printf("/%d", r->length);
529 if (i != n - 1)
530 printf(",");
531 }
532 }
533
534
535 /* isapnp_print_pin():
536 * Print an irq/drq assignment
537 */
538 static void
539 isapnp_print_pin(str, p, n)
540 const char *str;
541 struct isapnp_pin *p;
542 size_t n;
543 {
544 size_t i;
545
546 if (n == 0)
547 return;
548
549 printf(" %s ", str);
550 for (i = 0; i < n; i++, p++) {
551 printf("%d", p->num);
552 if (i != n - 1)
553 printf(",");
554 }
555 }
556
557
558 /* isapnp_print():
559 * Print the configuration line for an ISA PnP card.
560 */
561 static int
562 isapnp_print(aux, str)
563 void *aux;
564 const char *str;
565 {
566 struct isapnp_attach_args *ipa = aux;
567
568 if (str != NULL)
569 printf("%s: <%s, %s, %s, %s>",
570 str, ipa->ipa_devident, ipa->ipa_devlogic,
571 ipa->ipa_devcompat, ipa->ipa_devclass);
572
573 isapnp_print_region("port", ipa->ipa_io, ipa->ipa_nio);
574 isapnp_print_region("mem", ipa->ipa_mem, ipa->ipa_nmem);
575 isapnp_print_region("mem32", ipa->ipa_mem32, ipa->ipa_nmem32);
576 isapnp_print_pin("irq", ipa->ipa_irq, ipa->ipa_nirq);
577 isapnp_print_pin("drq", ipa->ipa_drq, ipa->ipa_ndrq);
578
579 return UNCONF;
580 }
581
582
583 #ifdef _KERNEL
584 /* isapnp_submatch():
585 * Probe the logical device...
586 */
587 static int
588 isapnp_submatch(parent, match, aux)
589 struct device *parent;
590 struct cfdata *match;
591 void *aux;
592 {
593 struct cfdata *cf = (struct cfdata *) match;
594 return ((*cf->cf_attach->ca_match)(parent, match, aux));
595 }
596
597
598 /* isapnp_devmatch():
599 * Match a probed device with the information from the driver
600 */
601 int
602 isapnp_devmatch(ipa, dinfo)
603 const struct isapnp_attach_args *ipa;
604 const struct isapnp_devinfo *dinfo;
605 {
606 const char *const *name;
607
608 for (name = dinfo->devlogic; *name; name++)
609 if (strcmp(*name, ipa->ipa_devlogic) == 0)
610 return 1;
611
612 for (name = dinfo->devcompat; *name; name++)
613 if (strcmp(*name, ipa->ipa_devcompat) == 0)
614 return 1;
615
616 return 0;
617 }
618
619
620 /* isapnp_isa_attach_hook():
621 * This routine is called from the isa attach code and
622 * is a kludge; we are resetting all the cards here in order
623 * to undo any card configuration that the bios did for us, in order
624 * to avoid having the PnP devices match an isa probe. The correct
625 * way of doing this is to read the PnP BIOS and find the card settings
626 * from there. Unfortunately it is not as easy as it sounds.
627 */
628 void
629 isapnp_isa_attach_hook(isa_sc)
630 struct isa_softc *isa_sc;
631 {
632 struct isapnp_softc sc;
633
634 sc.sc_iot = isa_sc->sc_iot;
635 sc.sc_ncards = 0;
636
637 if (isapnp_map(&sc))
638 return;
639
640 isapnp_init(&sc);
641
642 isapnp_write_reg(&sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV);
643 DELAY(2000);
644
645 isapnp_unmap(&sc);
646 }
647 #endif
648
649
650 /* isapnp_find():
651 * Probe and add cards
652 */
653 static int
654 isapnp_find(sc, all)
655 struct isapnp_softc *sc;
656 int all;
657 {
658 int p;
659
660 isapnp_init(sc);
661
662 isapnp_write_reg(sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV);
663 DELAY(2000);
664
665 isapnp_init(sc);
666 DELAY(2000);
667
668 for (p = ISAPNP_RDDATA_MIN; p <= ISAPNP_RDDATA_MAX; p += 4) {
669 sc->sc_read_port = p;
670 if (isapnp_map_readport(sc))
671 continue;
672 DPRINTF(("%s: Trying port %x\r", sc->sc_dev.dv_xname, p));
673 if (isapnp_findcard(sc))
674 break;
675 isapnp_unmap_readport(sc);
676 }
677
678 if (p > ISAPNP_RDDATA_MAX) {
679 sc->sc_read_port = 0;
680 return 0;
681 }
682
683 if (all)
684 while (isapnp_findcard(sc))
685 continue;
686
687 return 1;
688 }
689
690
691 /* isapnp_configure():
692 * Configure a PnP card
693 * XXX: The memory configuration code is wrong. We need to check the
694 * range/length bit an do appropriate sets.
695 */
696 static void
697 isapnp_configure(sc, ipa)
698 struct isapnp_softc *sc;
699 const struct isapnp_attach_args *ipa;
700 {
701 int i;
702 static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC;
703 static u_char isapnp_io_range[] = ISAPNP_IO_DESC;
704 static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC;
705 static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC;
706 static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC;
707 const struct isapnp_region *r;
708 const struct isapnp_pin *p;
709 struct isapnp_region rz;
710 struct isapnp_pin pz;
711
712 memset(&pz, 0, sizeof(pz));
713 memset(&rz, 0, sizeof(rz));
714
715 #define B0(a) ((a) & 0xff)
716 #define B1(a) (((a) >> 8) & 0xff)
717 #define B2(a) (((a) >> 16) & 0xff)
718 #define B3(a) (((a) >> 24) & 0xff)
719
720 for (i = 0; i < sizeof(isapnp_io_range); i++) {
721 if (i < ipa->ipa_nio)
722 r = &ipa->ipa_io[i];
723 else
724 r = &rz;
725
726 isapnp_write_reg(sc,
727 isapnp_io_range[i] + ISAPNP_IO_BASE_15_8, B1(r->base));
728 isapnp_write_reg(sc,
729 isapnp_io_range[i] + ISAPNP_IO_BASE_7_0, B0(r->base));
730 }
731
732 for (i = 0; i < sizeof(isapnp_mem_range); i++) {
733 if (i < ipa->ipa_nmem)
734 r = &ipa->ipa_mem[i];
735 else
736 r = &rz;
737
738 isapnp_write_reg(sc,
739 isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16, B2(r->base));
740 isapnp_write_reg(sc,
741 isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8, B1(r->base));
742
743 isapnp_write_reg(sc,
744 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16,
745 B2(r->length));
746 isapnp_write_reg(sc,
747 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8,
748 B1(r->length));
749 }
750
751 for (i = 0; i < sizeof(isapnp_irq_range); i++) {
752 u_char v;
753
754 if (i < ipa->ipa_nirq)
755 p = &ipa->ipa_irq[i];
756 else
757 p = &pz;
758
759 isapnp_write_reg(sc,
760 isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER, p->num);
761
762 switch (p->flags) {
763 case ISAPNP_IRQTYPE_LEVEL_PLUS:
764 v = ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH;
765 break;
766
767 case ISAPNP_IRQTYPE_EDGE_PLUS:
768 v = ISAPNP_IRQ_HIGH;
769 break;
770
771 case ISAPNP_IRQTYPE_LEVEL_MINUS:
772 v = ISAPNP_IRQ_LEVEL;
773 break;
774
775 default:
776 case ISAPNP_IRQTYPE_EDGE_MINUS:
777 v = 0;
778 break;
779 }
780 isapnp_write_reg(sc,
781 isapnp_irq_range[i] + ISAPNP_IRQ_CONTROL, v);
782 }
783
784 for (i = 0; i < sizeof(isapnp_drq_range); i++) {
785 u_char v;
786
787 if (i < ipa->ipa_ndrq)
788 v = ipa->ipa_drq[i].num;
789 else
790 v = 4;
791
792 isapnp_write_reg(sc, isapnp_drq_range[i], v);
793 }
794
795 for (i = 0; i < sizeof(isapnp_mem32_range); i++) {
796 if (i < ipa->ipa_nmem32)
797 r = &ipa->ipa_mem32[i];
798 else
799 r = &rz;
800
801 isapnp_write_reg(sc,
802 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24,
803 B3(r->base));
804 isapnp_write_reg(sc,
805 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16,
806 B2(r->base));
807 isapnp_write_reg(sc,
808 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8,
809 B1(r->base));
810 isapnp_write_reg(sc,
811 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0,
812 B0(r->base));
813
814 isapnp_write_reg(sc,
815 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24,
816 B3(r->length));
817 isapnp_write_reg(sc,
818 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16,
819 B2(r->length));
820 isapnp_write_reg(sc,
821 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8,
822 B1(r->length));
823 isapnp_write_reg(sc,
824 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0,
825 B0(r->length));
826 }
827 }
828
829
830 /* isapnp_match():
831 * Probe routine
832 */
833 static int
834 isapnp_match(parent, match, aux)
835 struct device *parent;
836 struct cfdata *match;
837 void *aux;
838 {
839 struct isapnp_softc sc;
840 struct isa_attach_args *ia = aux;
841 struct isapnp_probe_cookie *ipc;
842
843 /*
844 * Ensure we only probe ISA PnP once; we don't actually consume
845 * bus resources, so we have to prevent being cloned forever.
846 */
847 for (ipc = LIST_FIRST(&isapnp_probes); ipc != NULL;
848 ipc = LIST_NEXT(ipc, ipc_link))
849 if (ipc->ipc_parent == parent)
850 return (0);
851
852 ipc = malloc(sizeof(*ipc), M_DEVBUF, M_NOWAIT);
853 if (ipc == NULL)
854 panic("isapnp_match: can't allocate probe cookie");
855
856 ipc->ipc_parent = parent;
857 LIST_INSERT_HEAD(&isapnp_probes, ipc, ipc_link);
858
859 sc.sc_iot = ia->ia_iot;
860 (void) strcpy(sc.sc_dev.dv_xname, "(isapnp probe)");
861
862 if (isapnp_map(&sc))
863 return 0;
864
865 isapnp_unmap(&sc);
866
867 /*
868 * We always match. We must let all legacy ISA devices map
869 * their address spaces before we look for a read port.
870 */
871 ia->ia_iobase = ISAPNP_ADDR;
872 ia->ia_iosize = 1;
873
874 return (1);
875 }
876
877
878 /* isapnp_attach
879 * Attach the PnP `bus'.
880 */
881 static void
882 isapnp_attach(parent, self, aux)
883 struct device *parent, *self;
884 void *aux;
885 {
886 struct isapnp_softc *sc = (struct isapnp_softc *) self;
887 struct isa_attach_args *ia = aux;
888
889 sc->sc_iot = ia->ia_iot;
890 sc->sc_memt = ia->ia_memt;
891 sc->sc_ic = ia->ia_ic;
892 sc->sc_dmat = ia->ia_dmat;
893 sc->sc_ncards = 0;
894
895 printf(": ISA Plug 'n Play device support\n");
896
897 if (isapnp_map(sc)) {
898 printf("%s: unable to map PnP register\n",
899 sc->sc_dev.dv_xname);
900 return;
901 }
902
903 #ifdef _KERNEL
904 /*
905 * Defer configuration until the rest of the ISA devices have
906 * attached themselves.
907 */
908 config_defer(self, isapnp_callback);
909 #else
910 isapnp_callback(self);
911 #endif
912 }
913
914 /* isapnp_callback
915 * Find and attach PnP cards.
916 */
917 void
918 isapnp_callback(self)
919 struct device *self;
920 {
921 struct isapnp_softc *sc = (struct isapnp_softc *)self;
922 struct isapnp_attach_args *ipa, *lpa;
923 int c, d;
924
925 /*
926 * Look for cards. If none are found, we say so and just return.
927 */
928 if (isapnp_find(sc, 1) == 0) {
929 printf("%s: no ISA Plug 'n Play devices found\n",
930 sc->sc_dev.dv_xname);
931 return;
932 }
933
934 printf("%s: read port 0x%x\n", sc->sc_dev.dv_xname, sc->sc_read_port);
935
936 /*
937 * Now configure all of the cards.
938 */
939 for (c = 0; c < sc->sc_ncards; c++) {
940 /* Good morning card c */
941 isapnp_write_reg(sc, ISAPNP_WAKE, c + 1);
942
943 if ((ipa = isapnp_get_resource(sc, c)) == NULL)
944 continue;
945
946 DPRINTF(("Selecting attachments\n"));
947 for (d = 0;
948 (lpa = isapnp_bestconfig(sc, &ipa)) != NULL; d++) {
949 isapnp_write_reg(sc, ISAPNP_LOGICAL_DEV_NUM, d);
950 isapnp_configure(sc, lpa);
951 #ifdef DEBUG_ISAPNP
952 {
953 struct isapnp_attach_args pa;
954
955 isapnp_get_config(sc, &pa);
956 isapnp_print_config(&pa);
957 }
958 #endif
959
960 DPRINTF(("%s: configuring <%s, %s, %s, %s>\n",
961 sc->sc_dev.dv_xname,
962 lpa->ipa_devident, lpa->ipa_devlogic,
963 lpa->ipa_devcompat, lpa->ipa_devclass));
964 if (lpa->ipa_pref == ISAPNP_DEP_CONFLICTING) {
965 printf("%s: <%s, %s, %s, %s> ignored; %s\n",
966 sc->sc_dev.dv_xname,
967 lpa->ipa_devident, lpa->ipa_devlogic,
968 lpa->ipa_devcompat, lpa->ipa_devclass,
969 "resource conflict");
970 ISAPNP_FREE(lpa);
971 continue;
972 }
973
974 lpa->ipa_ic = sc->sc_ic;
975 lpa->ipa_iot = sc->sc_iot;
976 lpa->ipa_memt = sc->sc_memt;
977 lpa->ipa_dmat = sc->sc_dmat;
978
979 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 1);
980 #ifdef _KERNEL
981 if (config_found_sm(self, lpa, isapnp_print,
982 isapnp_submatch) == NULL)
983 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 0);
984 #else
985 isapnp_print(lpa, NULL);
986 printf("\n");
987 #endif
988 ISAPNP_FREE(lpa);
989 }
990 isapnp_write_reg(sc, ISAPNP_WAKE, 0); /* Good night cards */
991 }
992 }
993