1 /*-
2 * EISA bus probe and attach routines
3 *
4 * Copyright (c) 1995, 1996 Justin T. Gibbs.
5 * 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 immediately at the beginning of the file, without modification,
12 * this list of conditions, and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "opt_eisa.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/queue.h>
41 #include <sys/limits.h>
42 #include <sys/malloc.h>
43 #include <sys/kernel.h>
44 #include <sys/module.h>
45 #include <sys/bus.h>
46
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <sys/rman.h>
50
51 #include <dev/eisa/eisaconf.h>
52
53 typedef struct resvaddr {
54 u_long addr; /* start address */
55 u_long size; /* size of reserved area */
56 int flags;
57 struct resource *res; /* resource manager handle */
58 LIST_ENTRY(resvaddr) links; /* List links */
59 } resvaddr_t;
60
61 LIST_HEAD(resvlist, resvaddr);
62
63 struct irq_node {
64 int irq_no;
65 int irq_trigger;
66 void *idesc;
67 TAILQ_ENTRY(irq_node) links;
68 };
69
70 TAILQ_HEAD(irqlist, irq_node);
71
72 struct eisa_ioconf {
73 int slot;
74 struct resvlist ioaddrs; /* list of reserved I/O ranges */
75 struct resvlist maddrs; /* list of reserved memory ranges */
76 struct irqlist irqs; /* list of reserved irqs */
77 };
78
79 /* To be replaced by the "super device" generic device structure... */
80 struct eisa_device {
81 eisa_id_t id;
82 struct eisa_ioconf ioconf;
83 };
84
85
86 #define MAX_COL 79
87 #ifndef EISA_SLOTS
88 #define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
89 #endif
90 int num_eisa_slots = EISA_SLOTS;
91 TUNABLE_INT("hw.eisa_slots", &num_eisa_slots);
92
93 static devclass_t eisa_devclass;
94
95 static int eisa_probe_slot(int slot, eisa_id_t *eisa_id);
96 static void eisa_reg_print (device_t, char *, char *, int *);
97 static struct irq_node * eisa_find_irq(struct eisa_device *e_dev, int rid);
98 static struct resvaddr * eisa_find_maddr(struct eisa_device *e_dev, int rid);
99 static struct resvaddr * eisa_find_ioaddr(struct eisa_device *e_dev, int rid);
100
101 static int
102 mainboard_probe(device_t dev)
103 {
104 char *idstring;
105 eisa_id_t id = eisa_get_id(dev);
106
107 if (eisa_get_slot(dev) != 0)
108 return (ENXIO);
109
110 idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,
111 M_DEVBUF, M_NOWAIT);
112 if (idstring == NULL) {
113 panic("Eisa probe unable to malloc");
114 }
115 sprintf(idstring, "%c%c%c%03x%01x (System Board)",
116 EISA_MFCTR_CHAR0(id),
117 EISA_MFCTR_CHAR1(id),
118 EISA_MFCTR_CHAR2(id),
119 EISA_PRODUCT_ID(id),
120 EISA_REVISION_ID(id));
121 device_set_desc(dev, idstring);
122
123 return (0);
124 }
125
126 static int
127 mainboard_attach(device_t dev)
128 {
129 return (0);
130 }
131
132 static device_method_t mainboard_methods[] = {
133 /* Device interface */
134 DEVMETHOD(device_probe, mainboard_probe),
135 DEVMETHOD(device_attach, mainboard_attach),
136
137 { 0, 0 }
138 };
139
140 static driver_t mainboard_driver = {
141 "mainboard",
142 mainboard_methods,
143 1,
144 };
145
146 static devclass_t mainboard_devclass;
147
148 DRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0);
149
150 /*
151 ** probe for EISA devices
152 */
153 static int
154 eisa_probe(device_t dev)
155 {
156 int devices_found, slot;
157 struct eisa_device *e_dev;
158 device_t child;
159 eisa_id_t eisa_id;
160
161 device_set_desc(dev, "EISA bus");
162
163 devices_found = 0;
164 for (slot = 0; slot < num_eisa_slots; slot++) {
165 eisa_id = 0;
166 if (eisa_probe_slot(slot, &eisa_id)) {
167 /*
168 * If there's no card in the first slot (the
169 * mainboard), then the system doesn't have EISA.
170 * We abort the probe early in this case since
171 * continuing on causes a hang on some systems.
172 * Interestingly enough, the inb has been seen to
173 * cause the hang. However, aborting here causes
174 * the Adaptec 2842 probe to fail so that driver
175 * needs to be fixed separately.
176 */
177 if (slot == 0)
178 break;
179 continue;
180 }
181
182 devices_found++;
183
184 /* Prepare an eisa_device_node for this slot */
185 e_dev = (struct eisa_device *)malloc(sizeof(*e_dev),
186 M_DEVBUF, M_NOWAIT|M_ZERO);
187 if (!e_dev) {
188 device_printf(dev, "cannot malloc eisa_device");
189 break; /* Try to attach what we have already */
190 }
191
192 e_dev->id = eisa_id;
193 e_dev->ioconf.slot = slot;
194
195 /* Initialize our lists of reserved addresses */
196 LIST_INIT(&(e_dev->ioconf.ioaddrs));
197 LIST_INIT(&(e_dev->ioconf.maddrs));
198 TAILQ_INIT(&(e_dev->ioconf.irqs));
199
200 child = device_add_child(dev, NULL, -1);
201 device_set_ivars(child, e_dev);
202 }
203
204 /*
205 * EISA busses themselves are not easily detectable, the easiest way
206 * to tell if there is an eisa bus is if we found something - there
207 * should be a motherboard "card" there somewhere.
208 */
209 return devices_found ? 0 : ENXIO;
210 }
211
212 static int
213 eisa_probe_slot(int slot, eisa_id_t *eisa_id)
214 {
215 eisa_id_t probe_id;
216 int base, i, id_size;
217
218 probe_id = 0;
219 id_size = sizeof(probe_id);
220 base = 0x0c80 + (slot * 0x1000);
221
222 for (i = 0; i < id_size; i++)
223 probe_id |= inb(base + i) << ((id_size - i - 1) * CHAR_BIT);
224
225 /* If we found a card, return its EISA id. */
226 if ((probe_id & 0x80000000) == 0) {
227 *eisa_id = probe_id;
228 return (0);
229 }
230
231 return (ENXIO);
232 }
233
234 static void
235 eisa_probe_nomatch(device_t dev, device_t child)
236 {
237 u_int32_t eisa_id = eisa_get_id(child);
238 u_int8_t slot = eisa_get_slot(child);
239
240 device_printf(dev, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n",
241 EISA_MFCTR_CHAR0(eisa_id),
242 EISA_MFCTR_CHAR1(eisa_id),
243 EISA_MFCTR_CHAR2(eisa_id),
244 EISA_PRODUCT_ID(eisa_id),
245 EISA_REVISION_ID(eisa_id),
246 eisa_id,
247 slot);
248
249 return;
250 }
251
252 static void
253 eisa_reg_print (dev, string, separator, column)
254 device_t dev;
255 char * string;
256 char * separator;
257 int * column;
258 {
259 int length = strlen(string);
260
261 length += (separator ? 2 : 1);
262
263 if (((*column) + length) >= MAX_COL) {
264 printf("\n");
265 (*column) = 0;
266 } else if ((*column) != 0) {
267 if (separator) {
268 printf("%c", *separator);
269 (*column)++;
270 }
271 printf(" ");
272 (*column)++;
273 }
274
275 if ((*column) == 0) {
276 (*column) += device_printf(dev, "%s", string);
277 } else {
278 (*column) += printf("%s", string);
279 }
280
281 return;
282 }
283
284 static int
285 eisa_print_child(device_t dev, device_t child)
286 {
287 char buf[81];
288 struct eisa_device * e_dev = device_get_ivars(child);
289 int rid;
290 struct irq_node * irq;
291 struct resvaddr * resv;
292 char separator = ',';
293 int column = 0;
294 int retval = 0;
295
296 if (device_get_desc(child)) {
297 snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child));
298 eisa_reg_print(child, buf, NULL, &column);
299 }
300
301 rid = 0;
302 while ((resv = eisa_find_ioaddr(e_dev, rid++))) {
303 if ((resv->size == 1) ||
304 (resv->flags & RESVADDR_BITMASK)) {
305 snprintf(buf, sizeof(buf), "%s%lx",
306 ((rid == 1) ? "at 0x" : "0x"),
307 resv->addr);
308 } else {
309 snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
310 ((rid == 1) ? "at 0x" : "0x"),
311 resv->addr,
312 (resv->addr + (resv->size - 1)));
313 }
314 eisa_reg_print(child, buf,
315 ((rid == 2) ? &separator : NULL), &column);
316 }
317
318 rid = 0;
319 while ((resv = eisa_find_maddr(e_dev, rid++))) {
320 if ((resv->size == 1) ||
321 (resv->flags & RESVADDR_BITMASK)) {
322 snprintf(buf, sizeof(buf), "%s%lx",
323 ((rid == 1) ? "at 0x" : "0x"),
324 resv->addr);
325 } else {
326 snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
327 ((rid == 1) ? "at 0x" : "0x"),
328 resv->addr,
329 (resv->addr + (resv->size - 1)));
330 }
331 eisa_reg_print(child, buf,
332 ((rid == 2) ? &separator : NULL), &column);
333 }
334
335 rid = 0;
336 while ((irq = eisa_find_irq(e_dev, rid++)) != NULL) {
337 snprintf(buf, sizeof(buf), "irq %d (%s)", irq->irq_no,
338 (irq->irq_trigger ? "level" : "edge"));
339 eisa_reg_print(child, buf,
340 ((rid == 1) ? &separator : NULL), &column);
341 }
342
343 snprintf(buf, sizeof(buf), "on %s slot %d\n",
344 device_get_nameunit(dev), eisa_get_slot(child));
345 eisa_reg_print(child, buf, NULL, &column);
346
347 return (retval);
348 }
349
350 static struct irq_node *
351 eisa_find_irq(struct eisa_device *e_dev, int rid)
352 {
353 int i;
354 struct irq_node *irq;
355
356 for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs);
357 i < rid && irq;
358 i++, irq = TAILQ_NEXT(irq, links))
359 ;
360
361 if (irq)
362 return (irq);
363 else
364 return (NULL);
365 }
366
367 static struct resvaddr *
368 eisa_find_maddr(struct eisa_device *e_dev, int rid)
369 {
370 int i;
371 struct resvaddr *resv;
372
373 for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs);
374 i < rid && resv;
375 i++, resv = LIST_NEXT(resv, links))
376 ;
377
378 return resv;
379 }
380
381 static struct resvaddr *
382 eisa_find_ioaddr(struct eisa_device *e_dev, int rid)
383 {
384 int i;
385 struct resvaddr *resv;
386
387 for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs);
388 i < rid && resv;
389 i++, resv = LIST_NEXT(resv, links))
390 ;
391
392 return resv;
393 }
394
395 static int
396 eisa_read_ivar(device_t dev, device_t child, int which, u_long *result)
397 {
398 struct eisa_device *e_dev = device_get_ivars(child);
399 struct irq_node *irq;
400
401 switch (which) {
402 case EISA_IVAR_SLOT:
403 *result = e_dev->ioconf.slot;
404 break;
405
406 case EISA_IVAR_ID:
407 *result = e_dev->id;
408 break;
409
410 case EISA_IVAR_IRQ:
411 /* XXX only first irq */
412 if ((irq = eisa_find_irq(e_dev, 0)) != NULL) {
413 *result = irq->irq_no;
414 } else {
415 *result = -1;
416 }
417 break;
418
419 default:
420 return (ENOENT);
421 }
422
423 return (0);
424 }
425
426 static int
427 eisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
428 {
429 return (EINVAL);
430 }
431
432 static struct resource *
433 eisa_alloc_resource(device_t dev, device_t child, int type, int *rid,
434 u_long start, u_long end, u_long count, u_int flags)
435 {
436 int isdefault;
437 struct eisa_device *e_dev = device_get_ivars(child);
438 struct resource *rv, **rvp = 0;
439
440 isdefault = (device_get_parent(child) == dev
441 && start == 0UL && end == ~0UL && count == 1);
442
443 switch (type) {
444 case SYS_RES_IRQ:
445 if (isdefault) {
446 struct irq_node * irq = eisa_find_irq(e_dev, *rid);
447 if (irq == NULL)
448 return 0;
449 start = end = irq->irq_no;
450 count = 1;
451 if (irq->irq_trigger == EISA_TRIGGER_LEVEL) {
452 flags |= RF_SHAREABLE;
453 } else {
454 flags &= ~RF_SHAREABLE;
455 }
456 }
457 break;
458
459 case SYS_RES_MEMORY:
460 if (isdefault) {
461 struct resvaddr *resv;
462
463 resv = eisa_find_maddr(e_dev, *rid);
464 if (!resv)
465 return 0;
466
467 start = resv->addr;
468 end = resv->addr + (resv->size - 1);
469 count = resv->size;
470 rvp = &resv->res;
471 }
472 break;
473
474 case SYS_RES_IOPORT:
475 if (isdefault) {
476 struct resvaddr *resv;
477
478 resv = eisa_find_ioaddr(e_dev, *rid);
479 if (!resv)
480 return 0;
481
482 start = resv->addr;
483 end = resv->addr + (resv->size - 1);
484 count = resv->size;
485 rvp = &resv->res;
486 }
487 break;
488
489 default:
490 return 0;
491 }
492
493 rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
494 type, rid, start, end, count, flags);
495 if (rvp)
496 *rvp = rv;
497
498 return rv;
499 }
500
501 static int
502 eisa_release_resource(device_t dev, device_t child, int type, int rid,
503 struct resource *r)
504 {
505 int rv;
506 struct eisa_device *e_dev = device_get_ivars(child);
507 struct resvaddr *resv = 0;
508
509 switch (type) {
510 case SYS_RES_IRQ:
511 if (eisa_find_irq(e_dev, rid) == NULL)
512 return EINVAL;
513 break;
514
515 case SYS_RES_MEMORY:
516 if (device_get_parent(child) == dev)
517 resv = eisa_find_maddr(e_dev, rid);
518 break;
519
520
521 case SYS_RES_IOPORT:
522 if (device_get_parent(child) == dev)
523 resv = eisa_find_ioaddr(e_dev, rid);
524 break;
525
526 default:
527 return (ENOENT);
528 }
529
530 rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r);
531
532 if (rv == 0) {
533 if (resv)
534 resv->res = 0;
535 }
536
537 return rv;
538 }
539
540 static int
541 eisa_add_intr_m(device_t eisa, device_t dev, int irq, int trigger)
542 {
543 struct eisa_device *e_dev = device_get_ivars(dev);
544 struct irq_node *irq_info;
545
546 irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF,
547 M_NOWAIT);
548 if (irq_info == NULL)
549 return (1);
550
551 irq_info->irq_no = irq;
552 irq_info->irq_trigger = trigger;
553 irq_info->idesc = NULL;
554 TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links);
555 return 0;
556 }
557
558 static int
559 eisa_add_resvaddr(struct eisa_device *e_dev, struct resvlist *head, u_long base,
560 u_long size, int flags)
561 {
562 resvaddr_t *reservation;
563
564 reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t),
565 M_DEVBUF, M_NOWAIT);
566 if(!reservation)
567 return (ENOMEM);
568
569 reservation->addr = base;
570 reservation->size = size;
571 reservation->flags = flags;
572
573 if (!LIST_FIRST(head)) {
574 LIST_INSERT_HEAD(head, reservation, links);
575 }
576 else {
577 resvaddr_t *node;
578 LIST_FOREACH(node, head, links) {
579 if (node->addr > reservation->addr) {
580 /*
581 * List is sorted in increasing
582 * address order.
583 */
584 LIST_INSERT_BEFORE(node, reservation, links);
585 break;
586 }
587
588 if (node->addr == reservation->addr) {
589 /*
590 * If the entry we want to add
591 * matches any already in here,
592 * fail.
593 */
594 free(reservation, M_DEVBUF);
595 return (EEXIST);
596 }
597
598 if (!LIST_NEXT(node, links)) {
599 LIST_INSERT_AFTER(node, reservation, links);
600 break;
601 }
602 }
603 }
604 return (0);
605 }
606
607 static int
608 eisa_add_mspace_m(device_t eisa, device_t dev, u_long mbase, u_long msize,
609 int flags)
610 {
611 struct eisa_device *e_dev = device_get_ivars(dev);
612
613 return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
614 flags);
615 }
616
617 static int
618 eisa_add_iospace_m(device_t eisa, device_t dev, u_long iobase, u_long iosize,
619 int flags)
620 {
621 struct eisa_device *e_dev = device_get_ivars(dev);
622
623 return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
624 iosize, flags);
625 }
626
627 static device_method_t eisa_methods[] = {
628 /* Device interface */
629 DEVMETHOD(device_probe, eisa_probe),
630 DEVMETHOD(device_attach, bus_generic_attach),
631 DEVMETHOD(device_shutdown, bus_generic_shutdown),
632 DEVMETHOD(device_suspend, bus_generic_suspend),
633 DEVMETHOD(device_resume, bus_generic_resume),
634
635 /* Bus interface */
636 DEVMETHOD(bus_print_child, eisa_print_child),
637 DEVMETHOD(bus_probe_nomatch, eisa_probe_nomatch),
638 DEVMETHOD(bus_read_ivar, eisa_read_ivar),
639 DEVMETHOD(bus_write_ivar, eisa_write_ivar),
640 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
641 DEVMETHOD(bus_alloc_resource, eisa_alloc_resource),
642 DEVMETHOD(bus_release_resource, eisa_release_resource),
643 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
644 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
645 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
646 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
647
648 /* EISA interface */
649 DEVMETHOD(eisa_add_intr, eisa_add_intr_m),
650 DEVMETHOD(eisa_add_iospace, eisa_add_iospace_m),
651 DEVMETHOD(eisa_add_mspace, eisa_add_mspace_m),
652
653 { 0, 0 }
654 };
655
656 static driver_t eisa_driver = {
657 "eisa",
658 eisa_methods,
659 1, /* no softc */
660 };
661
662 DRIVER_MODULE(eisa, eisab, eisa_driver, eisa_devclass, 0, 0);
663 DRIVER_MODULE(eisa, legacy, eisa_driver, eisa_devclass, 0, 0);
Cache object: 98828645c3f4250a902785baa6354e75
|