eisaconf.c revision 133059
1111072Sjake/*
2111072Sjake * EISA bus probe and attach routines
3167308Smarius *
4111072Sjake * Copyright (c) 1995, 1996 Justin T. Gibbs.
5111072Sjake * All rights reserved.
6111072Sjake *
7111072Sjake * Redistribution and use in source and binary forms, with or without
8111072Sjake * modification, are permitted provided that the following conditions
9111072Sjake * are met:
10111072Sjake * 1. Redistributions of source code must retain the above copyright
11111072Sjake *    notice immediately at the beginning of the file, without modification,
12111072Sjake *    this list of conditions, and the following disclaimer.
13111072Sjake * 2. Redistributions in binary form must reproduce the above copyright
14111072Sjake *    notice, this list of conditions and the following disclaimer in the
15111072Sjake *    documentation and/or other materials provided with the distribution.
16111072Sjake * 3. The name of the author may not be used to endorse or promote products
17111072Sjake *    derived from this software without specific prior written permission.
18111072Sjake *
19111072Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20111072Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21111072Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22111072Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23111072Sjake * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24111072Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25111072Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26111072Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27111072Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28143129Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29143129Smarius * SUCH DAMAGE.
30143129Smarius *
31111072Sjake */
32111072Sjake
33111072Sjake#include <sys/cdefs.h>
34111072Sjake__FBSDID("$FreeBSD: head/sys/dev/eisa/eisaconf.c 133059 2004-08-03 06:48:36Z njl $");
35111072Sjake
36167308Smarius#include "opt_eisa.h"
37111123Sjake
38111072Sjake#include <sys/param.h>
39143826Smarius#include <sys/systm.h>
40133589Smarius#include <sys/queue.h>
41152684Smarius#include <sys/limits.h>
42111072Sjake#include <sys/malloc.h>
43111072Sjake#include <sys/kernel.h>
44111072Sjake#include <sys/module.h>
45111072Sjake#include <sys/bus.h>
46111072Sjake
47111072Sjake#include <machine/bus.h>
48111072Sjake#include <machine/resource.h>
49111072Sjake#include <sys/rman.h>
50111072Sjake
51111072Sjake#include <dev/eisa/eisaconf.h>
52111072Sjake
53111072Sjaketypedef struct resvaddr {
54152684Smarius        u_long	addr;				/* start address */
55111072Sjake        u_long	size;				/* size of reserved area */
56111072Sjake	int	flags;
57111072Sjake	struct resource *res;			/* resource manager handle */
58167308Smarius	LIST_ENTRY(resvaddr) links;		/* List links */
59172066Smarius} resvaddr_t;
60167308Smarius
61167308SmariusLIST_HEAD(resvlist, resvaddr);
62167308Smarius
63167308Smariusstruct irq_node {
64167308Smarius	int	irq_no;
65167308Smarius	int	irq_trigger;
66167308Smarius	void	*idesc;
67167308Smarius	TAILQ_ENTRY(irq_node) links;
68167308Smarius};
69167308Smarius
70167308SmariusTAILQ_HEAD(irqlist, irq_node);
71167308Smarius
72167308Smariusstruct eisa_ioconf {
73167308Smarius	int		slot;
74167308Smarius	struct resvlist	ioaddrs;	/* list of reserved I/O ranges */
75172066Smarius	struct resvlist maddrs;		/* list of reserved memory ranges */
76172066Smarius	struct irqlist	irqs;		/* list of reserved irqs */
77178443Smarius};
78178443Smarius
79143826Smarius/* To be replaced by the "super device" generic device structure... */
80152684Smariusstruct eisa_device {
81111123Sjake	eisa_id_t		id;
82167308Smarius	struct eisa_ioconf	ioconf;
83167308Smarius};
84167308Smarius
85167308Smarius
86167308Smarius#define MAX_COL		79
87167308Smarius#ifndef EISA_SLOTS
88167308Smarius#define EISA_SLOTS 10   /* PCI clashes with higher ones.. fix later */
89167308Smarius#endif
90167308Smariusint num_eisa_slots = EISA_SLOTS;
91167308SmariusTUNABLE_INT("hw.eisa_slots", &num_eisa_slots);
92167308Smarius
93167308Smariusstatic devclass_t eisa_devclass;
94167308Smarius
95167308Smariusstatic int eisa_probe_slot(int slot, eisa_id_t *eisa_id);
96190098Smariusstatic void eisa_reg_print (device_t, char *, char *, int *);
97190098Smariusstatic struct irq_node * eisa_find_irq(struct eisa_device *e_dev, int rid);
98190098Smariusstatic struct resvaddr * eisa_find_maddr(struct eisa_device *e_dev, int rid);
99190098Smariusstatic struct resvaddr * eisa_find_ioaddr(struct eisa_device *e_dev, int rid);
100167308Smarius
101167308Smariusstatic int
102167308Smariusmainboard_probe(device_t dev)
103167308Smarius{
104167308Smarius	char *idstring;
105167308Smarius	eisa_id_t id = eisa_get_id(dev);
106167308Smarius
107167308Smarius	if (eisa_get_slot(dev) != 0)
108167308Smarius		return (ENXIO);
109167308Smarius
110190098Smarius	idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,
111167308Smarius				  M_DEVBUF, M_NOWAIT);
112167308Smarius	if (idstring == NULL) {
113167308Smarius		panic("Eisa probe unable to malloc");
114167308Smarius	}
115167308Smarius	sprintf(idstring, "%c%c%c%03x%01x (System Board)",
116167308Smarius		EISA_MFCTR_CHAR0(id),
117167308Smarius		EISA_MFCTR_CHAR1(id),
118167308Smarius		EISA_MFCTR_CHAR2(id),
119167308Smarius		EISA_PRODUCT_ID(id),
120167308Smarius		EISA_REVISION_ID(id));
121167308Smarius	device_set_desc(dev, idstring);
122167308Smarius
123182070Smarius	return (0);
124182070Smarius}
125167308Smarius
126172066Smariusstatic int
127172066Smariusmainboard_attach(device_t dev)
128172066Smarius{
129178443Smarius	return (0);
130178443Smarius}
131172066Smarius
132172066Smariusstatic device_method_t mainboard_methods[] = {
133172066Smarius	/* Device interface */
134172066Smarius	DEVMETHOD(device_probe,		mainboard_probe),
135172066Smarius	DEVMETHOD(device_attach,	mainboard_attach),
136172066Smarius
137172066Smarius	{ 0, 0 }
138167308Smarius};
139111072Sjake
140111072Sjakestatic driver_t mainboard_driver = {
141111072Sjake	"mainboard",
142167308Smarius	mainboard_methods,
143167308Smarius	1,
144167308Smarius};
145167308Smarius
146167308Smariusstatic devclass_t mainboard_devclass;
147111072Sjake
148111072SjakeDRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0);
149167308Smarius
150111072Sjake/*
151111072Sjake** probe for EISA devices
152143826Smarius*/
153111072Sjakestatic int
154172066Smariuseisa_probe(device_t dev)
155172066Smarius{
156111072Sjake	int devices_found, slot;
157111072Sjake	struct eisa_device *e_dev;
158111072Sjake	device_t child;
159111072Sjake	eisa_id_t eisa_id;
160167308Smarius
161111123Sjake	device_set_desc(dev, "EISA bus");
162143142Smarius
163143142Smarius	devices_found = 0;
164111072Sjake	for (slot = 0; slot < num_eisa_slots; slot++) {
165172066Smarius		eisa_id = 0;
166167308Smarius		if (eisa_probe_slot(slot, &eisa_id)) {
167167308Smarius			/*
168190098Smarius			 * If there's no card in the first slot (the
169111072Sjake			 * mainboard), then the system doesn't have EISA.
170111072Sjake			 * We abort the probe early in this case since
171167308Smarius			 * continuing on causes a hang on some systems.
172111072Sjake			 * Interestingly enough, the inb has been seen to
173172066Smarius			 * cause the hang.  However, aborting here causes
174167308Smarius			 * the Adaptec 2842 probe to fail so that driver
175172066Smarius			 * needs to be fixed separately.
176167308Smarius			 */
177167308Smarius			if (slot == 0)
178190098Smarius				break;
179167308Smarius			continue;
180190098Smarius		}
181167308Smarius
182167308Smarius		devices_found++;
183167308Smarius
184167308Smarius		/* Prepare an eisa_device_node for this slot */
185167308Smarius		e_dev = (struct eisa_device *)malloc(sizeof(*e_dev),
186167308Smarius						     M_DEVBUF, M_NOWAIT|M_ZERO);
187167308Smarius		if (!e_dev) {
188172066Smarius			device_printf(dev, "cannot malloc eisa_device");
189172066Smarius			break; /* Try to attach what we have already */
190172066Smarius		}
191167308Smarius
192172066Smarius		e_dev->id = eisa_id;
193167308Smarius		e_dev->ioconf.slot = slot;
194167308Smarius
195167308Smarius		/* Initialize our lists of reserved addresses */
196167308Smarius		LIST_INIT(&(e_dev->ioconf.ioaddrs));
197167308Smarius		LIST_INIT(&(e_dev->ioconf.maddrs));
198167308Smarius		TAILQ_INIT(&(e_dev->ioconf.irqs));
199172066Smarius
200143129Smarius		child = device_add_child(dev, NULL, -1);
201143826Smarius		device_set_ivars(child, e_dev);
202143129Smarius	}
203143826Smarius
204143826Smarius	/*
205143129Smarius	 * EISA busses themselves are not easily detectable, the easiest way
206111072Sjake	 * to tell if there is an eisa bus is if we found something - there
207172066Smarius	 * should be a motherboard "card" there somewhere.
208172066Smarius	 */
209111072Sjake	return devices_found ? 0 : ENXIO;
210111072Sjake}
211172066Smarius
212172066Smariusstatic int
213172066Smariuseisa_probe_slot(int slot, eisa_id_t *eisa_id)
214111123Sjake{
215172066Smarius	eisa_id_t probe_id;
216172066Smarius	int base, i, id_size, ret;
217111123Sjake
218111123Sjake	ret = ENXIO;
219172066Smarius	probe_id = 0;
220172066Smarius	id_size = sizeof(probe_id);
221111123Sjake	base = 0x0c80 + (slot * 0x1000);
222111072Sjake
223111072Sjake	for (i = 0; i < id_size; i++) {
224111072Sjake		outb(base, 0x80 + i); /* Some cards require priming. */
225167308Smarius		probe_id |= inb(base + i) << ((id_size - i - 1) * CHAR_BIT);
226167308Smarius	}
227167308Smarius
228111072Sjake	/* If we found a card, return its EISA id. */
229111072Sjake	if ((probe_id & 0x80000000) == 0) {
230172066Smarius		*eisa_id = probe_id;
231172066Smarius		ret = 0;
232172066Smarius	}
233172066Smarius
234172066Smarius	return (ret);
235172066Smarius}
236172066Smarius
237172066Smariusstatic void
238172066Smariuseisa_probe_nomatch(device_t dev, device_t child)
239172066Smarius{
240190098Smarius	u_int32_t	eisa_id = eisa_get_id(child);
241190098Smarius	u_int8_t	slot = eisa_get_slot(child);
242172066Smarius
243172066Smarius	device_printf(dev, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n",
244172066Smarius		EISA_MFCTR_CHAR0(eisa_id),
245172066Smarius		EISA_MFCTR_CHAR1(eisa_id),
246172066Smarius		EISA_MFCTR_CHAR2(eisa_id),
247172066Smarius		EISA_PRODUCT_ID(eisa_id),
248172066Smarius		EISA_REVISION_ID(eisa_id),
249172066Smarius		eisa_id,
250172066Smarius		slot);
251172066Smarius
252172066Smarius	return;
253172066Smarius}
254172066Smarius
255172066Smariusstatic void
256172066Smariuseisa_reg_print (dev, string, separator, column)
257172066Smarius	device_t	dev;
258172066Smarius	char *		string;
259172066Smarius	char *		separator;
260172066Smarius	int *		column;
261190098Smarius{
262172066Smarius	int length = strlen(string);
263190098Smarius
264190098Smarius	length += (separator ? 2 : 1);
265190098Smarius
266190098Smarius	if (((*column) + length) >= MAX_COL) {
267190098Smarius		printf("\n");
268172066Smarius		(*column) = 0;
269172066Smarius	} else if ((*column) != 0) {
270172066Smarius		if (separator) {
271143826Smarius			printf("%c", *separator);
272143826Smarius			(*column)++;
273143826Smarius		}
274111072Sjake		printf(" ");
275152684Smarius		(*column)++;
276152684Smarius	}
277152684Smarius
278111072Sjake	if ((*column) == 0) {
279152684Smarius		(*column) += device_printf(dev, "%s", string);
280190098Smarius	} else {
281152684Smarius		(*column) += printf("%s", string);
282190098Smarius	}
283152684Smarius
284152684Smarius	return;
285152684Smarius}
286152684Smarius
287152684Smariusstatic int
288152684Smariuseisa_print_child(device_t dev, device_t child)
289152684Smarius{
290190098Smarius	char			buf[81];
291190098Smarius	struct eisa_device *	e_dev = device_get_ivars(child);
292190098Smarius	int			rid;
293190098Smarius	struct irq_node *	irq;
294152684Smarius	struct resvaddr *	resv;
295172066Smarius	char			separator = ',';
296190098Smarius	int			column = 0;
297172066Smarius	int			retval = 0;
298190098Smarius
299190098Smarius	if (device_get_desc(child)) {
300190098Smarius		snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child));
301172066Smarius		eisa_reg_print(child, buf, NULL, &column);
302190098Smarius	}
303172066Smarius
304172066Smarius	rid = 0;
305152684Smarius	while ((resv = eisa_find_ioaddr(e_dev, rid++))) {
306152684Smarius		if ((resv->size == 1) ||
307111072Sjake		    (resv->flags & RESVADDR_BITMASK)) {
308152684Smarius			snprintf(buf, sizeof(buf), "%s%lx",
309152684Smarius				((rid == 1) ? "at 0x" : "0x"),
310152684Smarius				resv->addr);
311152684Smarius		} else {
312152684Smarius			snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
313152684Smarius				((rid == 1) ? "at 0x" : "0x"),
314152684Smarius				resv->addr,
315152684Smarius				(resv->addr + (resv->size - 1)));
316152684Smarius		}
317111072Sjake		eisa_reg_print(child, buf,
318111072Sjake			((rid == 2) ? &separator : NULL), &column);
319111072Sjake	}
320167308Smarius
321167308Smarius	rid = 0;
322167308Smarius	while ((resv = eisa_find_maddr(e_dev, rid++))) {
323167308Smarius		if ((resv->size == 1) ||
324167308Smarius		    (resv->flags & RESVADDR_BITMASK)) {
325167308Smarius			snprintf(buf, sizeof(buf), "%s%lx",
326182070Smarius				((rid == 1) ? "at 0x" : "0x"),
327111072Sjake				resv->addr);
328111072Sjake		} else {
329167308Smarius			snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
330111072Sjake				((rid == 1) ? "at 0x" : "0x"),
331111072Sjake				resv->addr,
332111072Sjake				(resv->addr + (resv->size - 1)));
333111072Sjake		}
334111072Sjake		eisa_reg_print(child, buf,
335152684Smarius			((rid == 2) ? &separator : NULL), &column);
336111072Sjake	}
337111072Sjake
338111072Sjake	rid = 0;
339111072Sjake	while ((irq = eisa_find_irq(e_dev, rid++)) != NULL) {
340167308Smarius		snprintf(buf, sizeof(buf), "irq %d (%s)", irq->irq_no,
341111072Sjake			 (irq->irq_trigger ? "level" : "edge"));
342111072Sjake		eisa_reg_print(child, buf,
343152684Smarius			((rid == 1) ? &separator : NULL), &column);
344111072Sjake	}
345152684Smarius
346152684Smarius	snprintf(buf, sizeof(buf), "on %s slot %d\n",
347152684Smarius		device_get_nameunit(dev), eisa_get_slot(child));
348111072Sjake	eisa_reg_print(child, buf, NULL, &column);
349152684Smarius
350111072Sjake	return (retval);
351111072Sjake}
352172066Smarius
353172066Smariusstatic struct irq_node *
354111072Sjakeeisa_find_irq(struct eisa_device *e_dev, int rid)
355172066Smarius{
356172066Smarius	int i;
357111072Sjake	struct irq_node *irq;
358172066Smarius
359172066Smarius	for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs);
360172066Smarius	     i < rid && irq;
361111072Sjake	     i++, irq = TAILQ_NEXT(irq, links))
362111072Sjake		;
363172066Smarius
364172066Smarius	if (irq)
365111072Sjake		return (irq);
366172066Smarius	else
367172066Smarius		return (NULL);
368111072Sjake}
369172066Smarius
370172066Smariusstatic struct resvaddr *
371111072Sjakeeisa_find_maddr(struct eisa_device *e_dev, int rid)
372111072Sjake{
373172066Smarius	int i;
374178443Smarius	struct resvaddr *resv;
375170387Spiso
376172066Smarius	for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs);
377172066Smarius	     i < rid && resv;
378170387Spiso	     i++, resv = LIST_NEXT(resv, links))
379178443Smarius		;
380178443Smarius
381178443Smarius	return resv;
382178443Smarius}
383178443Smarius
384178443Smariusstatic struct resvaddr *
385178443Smariuseisa_find_ioaddr(struct eisa_device *e_dev, int rid)
386178443Smarius{
387178443Smarius	int i;
388178443Smarius	struct resvaddr *resv;
389178443Smarius
390172066Smarius	for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs);
391172066Smarius	     i < rid && resv;
392170387Spiso	     i++, resv = LIST_NEXT(resv, links))
393170387Spiso		;
394172066Smarius
395172066Smarius	return resv;
396172066Smarius}
397111123Sjake
398172066Smariusstatic int
399172066Smariuseisa_read_ivar(device_t dev, device_t child, int which, u_long *result)
400111123Sjake{
401172066Smarius	struct eisa_device *e_dev = device_get_ivars(child);
402172066Smarius	struct irq_node *irq;
403172066Smarius
404172066Smarius	switch (which) {
405182070Smarius	case EISA_IVAR_SLOT:
406172066Smarius		*result = e_dev->ioconf.slot;
407172066Smarius		break;
408172066Smarius
409182070Smarius	case EISA_IVAR_ID:
410182070Smarius		*result = e_dev->id;
411172066Smarius		break;
412172066Smarius
413111123Sjake	case EISA_IVAR_IRQ:
414111123Sjake		/* XXX only first irq */
415167308Smarius		if ((irq = eisa_find_irq(e_dev, 0)) != NULL) {
416111072Sjake			*result = irq->irq_no;
417111072Sjake		} else {
418111072Sjake			*result = -1;
419143826Smarius		}
420111072Sjake		break;
421111072Sjake
422111072Sjake	default:
423111072Sjake		return (ENOENT);
424111072Sjake	}
425111072Sjake
426111072Sjake	return (0);
427143826Smarius}
428111072Sjake
429111072Sjakestatic int
430111072Sjakeeisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
431143826Smarius{
432111072Sjake	return (EINVAL);
433143826Smarius}
434143826Smarius
435111072Sjakestatic struct resource *
436111072Sjakeeisa_alloc_resource(device_t dev, device_t child, int type, int *rid,
437111072Sjake		    u_long start, u_long end, u_long count, u_int flags)
438143826Smarius{
439143826Smarius	int isdefault;
440111072Sjake	struct eisa_device *e_dev = device_get_ivars(child);
441143826Smarius	struct resource *rv, **rvp = 0;
442172066Smarius
443143826Smarius	isdefault = (device_get_parent(child) == dev
444143826Smarius		     && start == 0UL && end == ~0UL && count == 1);
445143826Smarius
446143826Smarius	switch (type) {
447143826Smarius	case SYS_RES_IRQ:
448143826Smarius		if (isdefault) {
449143826Smarius			struct irq_node * irq = eisa_find_irq(e_dev, *rid);
450143826Smarius			if (irq == NULL)
451143826Smarius				return 0;
452143826Smarius			start = end = irq->irq_no;
453111072Sjake			count = 1;
454111072Sjake			if (irq->irq_trigger == EISA_TRIGGER_LEVEL) {
455111072Sjake				flags |= RF_SHAREABLE;
456111072Sjake			} else {
457111072Sjake				flags &= ~RF_SHAREABLE;
458111072Sjake			}
459111072Sjake		}
460111072Sjake		break;
461111072Sjake
462111072Sjake	case SYS_RES_MEMORY:
463111072Sjake		if (isdefault) {
464143826Smarius			struct resvaddr *resv;
465143826Smarius
466111072Sjake			resv = eisa_find_maddr(e_dev, *rid);
467111072Sjake			if (!resv)
468111072Sjake				return 0;
469111072Sjake
470111072Sjake			start = resv->addr;
471111072Sjake			end = resv->addr + (resv->size - 1);
472111072Sjake			count = resv->size;
473111072Sjake			rvp = &resv->res;
474167308Smarius		}
475143826Smarius		break;
476111072Sjake
477111072Sjake	case SYS_RES_IOPORT:
478111072Sjake		if (isdefault) {
479111072Sjake			struct resvaddr *resv;
480143826Smarius
481111072Sjake			resv = eisa_find_ioaddr(e_dev, *rid);
482133589Smarius			if (!resv)
483167308Smarius				return 0;
484152684Smarius
485152684Smarius			start = resv->addr;
486152684Smarius			end = resv->addr + (resv->size - 1);
487152684Smarius			count = resv->size;
488152684Smarius			rvp = &resv->res;
489152684Smarius		}
490152684Smarius		break;
491152684Smarius
492143826Smarius	default:
493143826Smarius		return 0;
494143826Smarius	}
495143826Smarius
496143826Smarius	rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
497143826Smarius				 type, rid, start, end, count, flags);
498143826Smarius	if (rvp)
499143826Smarius		*rvp = rv;
500172066Smarius
501143826Smarius	return rv;
502143826Smarius}
503143826Smarius
504143826Smariusstatic int
505143826Smariuseisa_release_resource(device_t dev, device_t child, int type, int rid,
506172066Smarius		      struct resource *r)
507172066Smarius{
508143826Smarius	int rv;
509143826Smarius	struct eisa_device *e_dev = device_get_ivars(child);
510152684Smarius	struct resvaddr *resv = 0;
511152684Smarius
512133589Smarius	switch (type) {
513152684Smarius	case SYS_RES_IRQ:
514133589Smarius		if (eisa_find_irq(e_dev, rid) == NULL)
515152684Smarius			return EINVAL;
516152684Smarius		break;
517152684Smarius
518152684Smarius	case SYS_RES_MEMORY:
519152684Smarius		if (device_get_parent(child) == dev)
520133589Smarius			resv = eisa_find_maddr(e_dev, rid);
521		break;
522
523
524	case SYS_RES_IOPORT:
525		if (device_get_parent(child) == dev)
526			resv = eisa_find_ioaddr(e_dev, rid);
527		break;
528
529	default:
530		return (ENOENT);
531	}
532
533	rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r);
534
535	if (rv == 0) {
536		if (resv)
537			resv->res = 0;
538	}
539
540	return rv;
541}
542
543static int
544eisa_add_intr_m(device_t eisa, device_t dev, int irq, int trigger)
545{
546	struct eisa_device *e_dev = device_get_ivars(dev);
547	struct irq_node *irq_info;
548
549	irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF,
550					     M_NOWAIT);
551	if (irq_info == NULL)
552		return (1);
553
554	irq_info->irq_no = irq;
555	irq_info->irq_trigger = trigger;
556	irq_info->idesc = NULL;
557	TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links);
558	return 0;
559}
560
561static int
562eisa_add_resvaddr(struct eisa_device *e_dev, struct resvlist *head, u_long base,
563		  u_long size, int flags)
564{
565	resvaddr_t *reservation;
566
567	reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t),
568					   M_DEVBUF, M_NOWAIT);
569	if(!reservation)
570		return (ENOMEM);
571
572	reservation->addr = base;
573	reservation->size = size;
574	reservation->flags = flags;
575
576	if (!LIST_FIRST(head)) {
577		LIST_INSERT_HEAD(head, reservation, links);
578	}
579	else {
580		resvaddr_t *node;
581		LIST_FOREACH(node, head, links) {
582			if (node->addr > reservation->addr) {
583				/*
584				 * List is sorted in increasing
585				 * address order.
586				 */
587				LIST_INSERT_BEFORE(node, reservation, links);
588				break;
589			}
590
591			if (node->addr == reservation->addr) {
592				/*
593				 * If the entry we want to add
594				 * matches any already in here,
595				 * fail.
596				 */
597				free(reservation, M_DEVBUF);
598				return (EEXIST);
599			}
600
601			if (!LIST_NEXT(node, links)) {
602				LIST_INSERT_AFTER(node, reservation, links);
603				break;
604			}
605		}
606	}
607	return (0);
608}
609
610static int
611eisa_add_mspace_m(device_t eisa, device_t dev, u_long mbase, u_long msize,
612    int flags)
613{
614	struct eisa_device *e_dev = device_get_ivars(dev);
615
616	return	eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
617				  flags);
618}
619
620static int
621eisa_add_iospace_m(device_t eisa, device_t dev, u_long iobase, u_long iosize,
622    int flags)
623{
624	struct eisa_device *e_dev = device_get_ivars(dev);
625
626	return	eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
627				  iosize, flags);
628}
629
630static device_method_t eisa_methods[] = {
631	/* Device interface */
632	DEVMETHOD(device_probe,		eisa_probe),
633	DEVMETHOD(device_attach,	bus_generic_attach),
634	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
635	DEVMETHOD(device_suspend,	bus_generic_suspend),
636	DEVMETHOD(device_resume,	bus_generic_resume),
637
638	/* Bus interface */
639	DEVMETHOD(bus_print_child,	eisa_print_child),
640	DEVMETHOD(bus_probe_nomatch,	eisa_probe_nomatch),
641	DEVMETHOD(bus_read_ivar,	eisa_read_ivar),
642	DEVMETHOD(bus_write_ivar,	eisa_write_ivar),
643	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
644	DEVMETHOD(bus_alloc_resource,	eisa_alloc_resource),
645	DEVMETHOD(bus_release_resource,	eisa_release_resource),
646	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
647	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
648	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
649	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
650
651	/* EISA interface */
652	DEVMETHOD(eisa_add_intr,	eisa_add_intr_m),
653	DEVMETHOD(eisa_add_iospace,	eisa_add_iospace_m),
654	DEVMETHOD(eisa_add_mspace,	eisa_add_mspace_m),
655
656	{ 0, 0 }
657};
658
659static driver_t eisa_driver = {
660	"eisa",
661	eisa_methods,
662	1,			/* no softc */
663};
664
665DRIVER_MODULE(eisa, eisab, eisa_driver, eisa_devclass, 0, 0);
666DRIVER_MODULE(eisa, legacy, eisa_driver, eisa_devclass, 0, 0);
667