2 * EISA bus probe and attach routines
4 * Copyright (c) 1995, 1996 Justin T. Gibbs.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 * $FreeBSD: src/sys/dev/eisa/eisaconf.c,v 1.55 2000/01/14 07:13:57 peter Exp $
32 * $DragonFly: src/sys/bus/eisa/eisaconf.c,v 1.9 2006/10/25 20:55:51 dillon Exp $
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/queue.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
45 #include <machine/limits.h>
50 typedef struct resvaddr
{
51 u_long addr
; /* start address */
52 u_long size
; /* size of reserved area */
54 struct resource
*res
; /* resource manager handle */
55 LIST_ENTRY(resvaddr
) links
; /* List links */
58 LIST_HEAD(resvlist
, resvaddr
);
64 TAILQ_ENTRY(irq_node
) links
;
67 TAILQ_HEAD(irqlist
, irq_node
);
71 struct resvlist ioaddrs
; /* list of reserved I/O ranges */
72 struct resvlist maddrs
; /* list of reserved memory ranges */
73 struct irqlist irqs
; /* list of reserved irqs */
76 /* To be replaced by the "super device" generic device structure... */
79 struct eisa_ioconf ioconf
;
83 /* Global variable, so UserConfig can change it. */
86 #define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
88 int num_eisa_slots
= EISA_SLOTS
;
90 static devclass_t eisa_devclass
;
92 static void eisa_reg_print(device_t
, char *, char *, int *);
93 static struct irq_node
* eisa_find_irq(struct eisa_device
*e_dev
, int rid
);
94 static struct resvaddr
* eisa_find_maddr(struct eisa_device
*e_dev
, int rid
);
95 static struct resvaddr
* eisa_find_ioaddr(struct eisa_device
*e_dev
, int rid
);
98 mainboard_probe(device_t dev
)
101 eisa_id_t id
= eisa_get_id(dev
);
103 if (eisa_get_slot(dev
) != 0)
106 idstring
= kmalloc(8 + sizeof(" (System Board)") + 1,
107 M_DEVBUF
, M_INTWAIT
);
108 sprintf(idstring
, "%c%c%c%03x%01x (System Board)",
109 EISA_MFCTR_CHAR0(id
),
110 EISA_MFCTR_CHAR1(id
),
111 EISA_MFCTR_CHAR2(id
),
113 EISA_REVISION_ID(id
));
114 device_set_desc(dev
, idstring
);
120 mainboard_attach(device_t dev
)
125 static device_method_t mainboard_methods
[] = {
126 /* Device interface */
127 DEVMETHOD(device_probe
, mainboard_probe
),
128 DEVMETHOD(device_attach
, mainboard_attach
),
133 static driver_t mainboard_driver
= {
139 static devclass_t mainboard_devclass
;
141 DRIVER_MODULE(mainboard
, eisa
, mainboard_driver
, mainboard_devclass
, 0, 0);
144 ** probe for EISA devices
147 eisa_probe(device_t dev
)
150 struct eisa_device
*e_dev
;
152 int eisaBase
= 0xc80;
154 int devices_found
= 0;
156 device_set_desc(dev
, "EISA bus");
158 for (slot
= 0; slot
< num_eisa_slots
; eisaBase
+=0x1000, slot
++) {
159 int id_size
= sizeof(eisa_id
);
161 for( i
= 0; i
< id_size
; i
++ ) {
162 outb(eisaBase
,0x80 + i
); /*Some cards require priming*/
163 eisa_id
|= inb(eisaBase
+i
) << ((id_size
-i
-1)*CHAR_BIT
);
165 if (eisa_id
& 0x80000000) {
168 continue; /* no EISA card in slot */
173 /* Prepare an eisa_device_node for this slot */
174 e_dev
= kmalloc(sizeof(*e_dev
), M_DEVBUF
, M_INTWAIT
| M_ZERO
);
177 e_dev
->ioconf
.slot
= slot
;
179 /* Initialize our lists of reserved addresses */
180 LIST_INIT(&(e_dev
->ioconf
.ioaddrs
));
181 LIST_INIT(&(e_dev
->ioconf
.maddrs
));
182 TAILQ_INIT(&(e_dev
->ioconf
.irqs
));
184 child
= device_add_child(dev
, NULL
, -1);
185 device_set_ivars(child
, e_dev
);
189 * EISA busses themselves are not easily detectable, the easiest way
190 * to tell if there is an eisa bus is if we found something - there
191 * should be a motherboard "card" there somewhere.
193 return devices_found
? 0 : ENXIO
;
197 eisa_probe_nomatch(device_t dev
, device_t child
)
199 u_int32_t eisa_id
= eisa_get_id(child
);
200 u_int8_t slot
= eisa_get_slot(child
);
202 device_printf(dev
, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n",
203 EISA_MFCTR_CHAR0(eisa_id
),
204 EISA_MFCTR_CHAR1(eisa_id
),
205 EISA_MFCTR_CHAR2(eisa_id
),
206 EISA_PRODUCT_ID(eisa_id
),
207 EISA_REVISION_ID(eisa_id
),
215 eisa_reg_print(device_t dev
, char *string
, char *separator
, int *column
)
217 int length
= strlen(string
);
219 length
+= (separator
? 2 : 1);
221 if (((*column
) + length
) >= MAX_COL
) {
224 } else if ((*column
) != 0) {
226 printf("%c", *separator
);
233 if ((*column
) == 0) {
234 (*column
) += device_printf(dev
, "%s", string
);
236 (*column
) += printf("%s", string
);
243 eisa_print_child(device_t dev
, device_t child
)
246 struct eisa_device
* e_dev
= device_get_ivars(child
);
248 struct irq_node
* irq
;
249 struct resvaddr
* resv
;
250 char separator
= ',';
254 if (device_get_desc(child
)) {
255 snprintf(buf
, sizeof(buf
), "<%s>", device_get_desc(child
));
256 eisa_reg_print(child
, buf
, NULL
, &column
);
260 while ((resv
= eisa_find_ioaddr(e_dev
, rid
++))) {
261 if ((resv
->size
== 1) ||
262 (resv
->flags
& RESVADDR_BITMASK
)) {
263 snprintf(buf
, sizeof(buf
), "%s%lx",
264 ((rid
== 1) ? "at 0x" : "0x"),
267 snprintf(buf
, sizeof(buf
), "%s%lx-0x%lx",
268 ((rid
== 1) ? "at 0x" : "0x"),
270 (resv
->addr
+ (resv
->size
- 1)));
272 eisa_reg_print(child
, buf
,
273 ((rid
== 2) ? &separator
: NULL
), &column
);
277 while ((resv
= eisa_find_maddr(e_dev
, rid
++))) {
278 if ((resv
->size
== 1) ||
279 (resv
->flags
& RESVADDR_BITMASK
)) {
280 snprintf(buf
, sizeof(buf
), "%s%lx",
281 ((rid
== 1) ? "at 0x" : "0x"),
284 snprintf(buf
, sizeof(buf
), "%s%lx-0x%lx",
285 ((rid
== 1) ? "at 0x" : "0x"),
287 (resv
->addr
+ (resv
->size
- 1)));
289 eisa_reg_print(child
, buf
,
290 ((rid
== 2) ? &separator
: NULL
), &column
);
294 while ((irq
= eisa_find_irq(e_dev
, rid
++)) != NULL
) {
295 snprintf(buf
, sizeof(buf
), "irq %d (%s)", irq
->irq_no
,
296 (irq
->irq_trigger
? "level" : "edge"));
297 eisa_reg_print(child
, buf
,
298 ((rid
== 1) ? &separator
: NULL
), &column
);
301 snprintf(buf
, sizeof(buf
), "on %s slot %d\n",
302 device_get_nameunit(dev
), eisa_get_slot(child
));
303 eisa_reg_print(child
, buf
, NULL
, &column
);
308 static struct irq_node
*
309 eisa_find_irq(struct eisa_device
*e_dev
, int rid
)
312 struct irq_node
*irq
;
314 for (i
= 0, irq
= TAILQ_FIRST(&e_dev
->ioconf
.irqs
);
316 i
++, irq
= TAILQ_NEXT(irq
, links
))
325 static struct resvaddr
*
326 eisa_find_maddr(struct eisa_device
*e_dev
, int rid
)
329 struct resvaddr
*resv
;
331 for (i
= 0, resv
= LIST_FIRST(&e_dev
->ioconf
.maddrs
);
333 i
++, resv
= LIST_NEXT(resv
, links
))
339 static struct resvaddr
*
340 eisa_find_ioaddr(struct eisa_device
*e_dev
, int rid
)
343 struct resvaddr
*resv
;
345 for (i
= 0, resv
= LIST_FIRST(&e_dev
->ioconf
.ioaddrs
);
347 i
++, resv
= LIST_NEXT(resv
, links
))
354 eisa_read_ivar(device_t dev
, device_t child
, int which
, u_long
*result
)
356 struct eisa_device
*e_dev
= device_get_ivars(child
);
357 struct irq_node
*irq
;
361 *result
= e_dev
->ioconf
.slot
;
369 /* XXX only first irq */
370 if ((irq
= eisa_find_irq(e_dev
, 0)) != NULL
) {
371 *result
= irq
->irq_no
;
385 eisa_write_ivar(device_t dev
, device_t child
, int which
, uintptr_t value
)
390 static struct resource
*
391 eisa_alloc_resource(device_t dev
, device_t child
, int type
, int *rid
,
392 u_long start
, u_long end
, u_long count
, u_int flags
)
395 struct eisa_device
*e_dev
= device_get_ivars(child
);
396 struct resource
*rv
, **rvp
= 0;
398 isdefault
= (device_get_parent(child
) == dev
399 && start
== 0UL && end
== ~0UL && count
== 1);
404 struct irq_node
* irq
= eisa_find_irq(e_dev
, *rid
);
407 start
= end
= irq
->irq_no
;
409 if (irq
->irq_trigger
== EISA_TRIGGER_LEVEL
) {
410 flags
|= RF_SHAREABLE
;
412 flags
&= ~RF_SHAREABLE
;
419 struct resvaddr
*resv
;
421 resv
= eisa_find_maddr(e_dev
, *rid
);
426 end
= resv
->addr
+ (resv
->size
- 1);
434 struct resvaddr
*resv
;
436 resv
= eisa_find_ioaddr(e_dev
, *rid
);
441 end
= resv
->addr
+ (resv
->size
- 1);
451 rv
= BUS_ALLOC_RESOURCE(device_get_parent(dev
), child
,
452 type
, rid
, start
, end
, count
, flags
);
460 eisa_release_resource(device_t dev
, device_t child
, int type
, int rid
,
464 struct eisa_device
*e_dev
= device_get_ivars(child
);
465 struct resvaddr
*resv
= 0;
469 if (eisa_find_irq(e_dev
, rid
) == NULL
)
474 if (device_get_parent(child
) == dev
)
475 resv
= eisa_find_maddr(e_dev
, rid
);
480 if (device_get_parent(child
) == dev
)
481 resv
= eisa_find_ioaddr(e_dev
, rid
);
488 rv
= BUS_RELEASE_RESOURCE(device_get_parent(dev
), child
, type
, rid
, r
);
499 eisa_add_intr(device_t dev
, int irq
, int trigger
)
501 struct eisa_device
*e_dev
= device_get_ivars(dev
);
502 struct irq_node
*irq_info
;
504 irq_info
= kmalloc(sizeof(*irq_info
), M_DEVBUF
, M_INTWAIT
);
505 irq_info
->irq_no
= irq
;
506 irq_info
->irq_trigger
= trigger
;
507 irq_info
->idesc
= NULL
;
508 TAILQ_INSERT_TAIL(&e_dev
->ioconf
.irqs
, irq_info
, links
);
513 eisa_add_resvaddr(struct eisa_device
*e_dev
, struct resvlist
*head
, u_long base
,
514 u_long size
, int flags
)
516 resvaddr_t
*reservation
;
518 reservation
= kmalloc(sizeof(resvaddr_t
), M_DEVBUF
, M_INTWAIT
);
519 reservation
->addr
= base
;
520 reservation
->size
= size
;
521 reservation
->flags
= flags
;
523 if (!head
->lh_first
) {
524 LIST_INSERT_HEAD(head
, reservation
, links
);
528 for(node
= head
->lh_first
; node
; node
= node
->links
.le_next
) {
529 if (node
->addr
> reservation
->addr
) {
531 * List is sorted in increasing
534 LIST_INSERT_BEFORE(node
, reservation
, links
);
538 if (node
->addr
== reservation
->addr
) {
540 * If the entry we want to add
541 * matches any already in here,
544 kfree(reservation
, M_DEVBUF
);
548 if (!node
->links
.le_next
) {
549 LIST_INSERT_AFTER(node
, reservation
, links
);
558 eisa_add_mspace(device_t dev
, u_long mbase
, u_long msize
, int flags
)
560 struct eisa_device
*e_dev
= device_get_ivars(dev
);
562 return eisa_add_resvaddr(e_dev
, &(e_dev
->ioconf
.maddrs
), mbase
, msize
,
567 eisa_add_iospace(device_t dev
, u_long iobase
, u_long iosize
, int flags
)
569 struct eisa_device
*e_dev
= device_get_ivars(dev
);
571 return eisa_add_resvaddr(e_dev
, &(e_dev
->ioconf
.ioaddrs
), iobase
,
575 static device_method_t eisa_methods
[] = {
576 /* Device interface */
577 DEVMETHOD(device_probe
, eisa_probe
),
578 DEVMETHOD(device_attach
, bus_generic_attach
),
579 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
580 DEVMETHOD(device_suspend
, bus_generic_suspend
),
581 DEVMETHOD(device_resume
, bus_generic_resume
),
584 DEVMETHOD(bus_print_child
, eisa_print_child
),
585 DEVMETHOD(bus_probe_nomatch
, eisa_probe_nomatch
),
586 DEVMETHOD(bus_read_ivar
, eisa_read_ivar
),
587 DEVMETHOD(bus_write_ivar
, eisa_write_ivar
),
588 DEVMETHOD(bus_driver_added
, bus_generic_driver_added
),
589 DEVMETHOD(bus_alloc_resource
, eisa_alloc_resource
),
590 DEVMETHOD(bus_release_resource
, eisa_release_resource
),
591 DEVMETHOD(bus_activate_resource
, bus_generic_activate_resource
),
592 DEVMETHOD(bus_deactivate_resource
, bus_generic_deactivate_resource
),
593 DEVMETHOD(bus_setup_intr
, bus_generic_setup_intr
),
594 DEVMETHOD(bus_teardown_intr
, bus_generic_teardown_intr
),
599 static driver_t eisa_driver
= {
605 DRIVER_MODULE(eisa
, isab
, eisa_driver
, eisa_devclass
, 0, 0);
606 DRIVER_MODULE(eisa
, nexus
, eisa_driver
, eisa_devclass
, 0, 0);