147178Sdfr/*-
247178Sdfr * Copyright (c) 1999 Doug Rabson
347178Sdfr * All rights reserved.
447178Sdfr *
547178Sdfr * Redistribution and use in source and binary forms, with or without
647178Sdfr * modification, are permitted provided that the following conditions
747178Sdfr * are met:
847178Sdfr * 1. Redistributions of source code must retain the above copyright
947178Sdfr *    notice, this list of conditions and the following disclaimer.
1047178Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1147178Sdfr *    notice, this list of conditions and the following disclaimer in the
1247178Sdfr *    documentation and/or other materials provided with the distribution.
1347178Sdfr *
1447178Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1547178Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1647178Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1747178Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1847178Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1947178Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2047178Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2147178Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2247178Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2347178Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2447178Sdfr * SUCH DAMAGE.
2547178Sdfr */
2647178Sdfr
27116181Sobrien#include <sys/cdefs.h>
28116181Sobrien__FBSDID("$FreeBSD$");
29116181Sobrien
3047178Sdfr#include <sys/param.h>
3147178Sdfr#include <sys/systm.h>
3247178Sdfr#include <sys/kernel.h>
3347178Sdfr#include <sys/bus.h>
3447178Sdfr#include <sys/module.h>
3547178Sdfr#include <isa/isavar.h>
36185059Sjhb#include <isa/isa_common.h>
3747398Sdfr#include <machine/resource.h>
3847178Sdfr
39185059Sjhbvoid
40185059Sjhbisa_hinted_child(device_t parent, const char *name, int unit)
4147178Sdfr{
4247178Sdfr	device_t	child;
43136520Snjl	int		sensitive, start, count;
4447578Sdfr	int		order;
4547178Sdfr
4647178Sdfr	/* device-specific flag overrides any wildcard */
4747178Sdfr	sensitive = 0;
4847178Sdfr	if (resource_int_value(name, unit, "sensitive", &sensitive) != 0)
4947178Sdfr		resource_int_value(name, -1, "sensitive", &sensitive);
5047178Sdfr
5147178Sdfr	if (sensitive)
5247578Sdfr		order = ISA_ORDER_SENSITIVE;
5347178Sdfr	else
5447578Sdfr		order = ISA_ORDER_SPECULATIVE;
5547578Sdfr
5647578Sdfr	child = BUS_ADD_CHILD(parent, order, name, unit);
5747178Sdfr	if (child == 0)
5847178Sdfr		return;
5947178Sdfr
6047398Sdfr	start = 0;
6147398Sdfr	count = 0;
6274378Snyan	resource_int_value(name, unit, "port", &start);
6374378Snyan	resource_int_value(name, unit, "portsize", &count);
6474378Snyan	if (start > 0 || count > 0)
6552174Sdfr		bus_set_resource(child, SYS_RES_IOPORT, 0, start, count);
6647178Sdfr
6747398Sdfr	start = 0;
6847398Sdfr	count = 0;
6974378Snyan	resource_int_value(name, unit, "maddr", &start);
7074378Snyan	resource_int_value(name, unit, "msize", &count);
7174378Snyan	if (start > 0 || count > 0)
7252174Sdfr		bus_set_resource(child, SYS_RES_MEMORY, 0, start, count);
7347178Sdfr
7449048Syokota	if (resource_int_value(name, unit, "irq", &start) == 0 && start > 0)
7552174Sdfr		bus_set_resource(child, SYS_RES_IRQ, 0, start, 1);
7647178Sdfr
7753585Sgallatin	if (resource_int_value(name, unit, "drq", &start) == 0 && start >= 0)
7852174Sdfr		bus_set_resource(child, SYS_RES_DRQ, 0, start, 1);
7947178Sdfr
80117167Sjhb	if (resource_disabled(name, unit))
8147178Sdfr		device_disable(child);
82144985Smdodd
83144985Smdodd	isa_set_configattr(child, (isa_get_configattr(child)|ISACFGATTR_HINTS));
8447178Sdfr}
8547178Sdfr
86185059Sjhbstatic int
87185059Sjhbisa_match_resource_hint(device_t dev, int type, long value)
8847178Sdfr{
89185059Sjhb	struct isa_device* idev = DEVTOISA(dev);
90185059Sjhb	struct resource_list *rl = &idev->id_resources;
91185059Sjhb	struct resource_list_entry *rle;
9247178Sdfr
93185059Sjhb	STAILQ_FOREACH(rle, rl, link) {
94185059Sjhb		if (rle->type != type)
95185059Sjhb			continue;
96185059Sjhb		if (rle->start <= value && rle->end >= value)
97185059Sjhb			return (1);
98185059Sjhb	}
99185059Sjhb	return (0);
10047178Sdfr}
10147178Sdfr
102185059Sjhbvoid
103185059Sjhbisa_hint_device_unit(device_t bus, device_t child, const char *name, int *unitp)
104185059Sjhb{
105185059Sjhb	const char *s;
106185059Sjhb	long value;
107185059Sjhb	int line, matches, unit;
10847178Sdfr
109185059Sjhb	line = 0;
110185059Sjhb	for (;;) {
111185059Sjhb		if (resource_find_dev(&line, name, &unit, "at", NULL) != 0)
112185059Sjhb			break;
11347178Sdfr
114185059Sjhb		/* Must have an "at" for isa. */
115185059Sjhb		resource_string_value(name, unit, "at", &s);
116185059Sjhb		if (!(strcmp(s, device_get_nameunit(bus)) == 0 ||
117185059Sjhb		    strcmp(s, device_get_name(bus)) == 0))
118185059Sjhb			continue;
11947178Sdfr
120185059Sjhb		/*
121196520Sjhb		 * Check for matching resources.  We must have at
122196520Sjhb		 * least one match.  Since I/O and memory resources
123196520Sjhb		 * cannot be shared, if we get a match on either of
124196520Sjhb		 * those, ignore any mismatches in IRQs or DRQs.
125185059Sjhb		 *
126196520Sjhb		 * XXX: We may want to revisit this to be more lenient
127196520Sjhb		 * and wire as long as it gets one match.
128185059Sjhb		 */
129185059Sjhb		matches = 0;
130185059Sjhb		if (resource_long_value(name, unit, "port", &value) == 0) {
131196520Sjhb			/*
132196520Sjhb			 * Floppy drive controllers are notorious for
133196520Sjhb			 * having a wide variety of resources not all
134196520Sjhb			 * of which include the first port that is
135196520Sjhb			 * specified by the hint (typically 0x3f0)
136196520Sjhb			 * (see the comment above
137196520Sjhb			 * fdc_isa_alloc_resources() in fdc_isa.c).
138196520Sjhb			 * However, they do all seem to include port +
139196520Sjhb			 * 2 (e.g. 0x3f2) so for a floppy device, look
140196520Sjhb			 * for 'value + 2' in the port resources
141196520Sjhb			 * instead of the hint value.
142196520Sjhb			 */
143196520Sjhb			if (strcmp(name, "fdc") == 0)
144196520Sjhb				value += 2;
145185059Sjhb			if (isa_match_resource_hint(child, SYS_RES_IOPORT,
146185059Sjhb			    value))
147185059Sjhb				matches++;
148185059Sjhb			else
149185059Sjhb				continue;
150185059Sjhb		}
151185059Sjhb		if (resource_long_value(name, unit, "maddr", &value) == 0) {
152185059Sjhb			if (isa_match_resource_hint(child, SYS_RES_MEMORY,
153185059Sjhb			    value))
154185059Sjhb				matches++;
155185059Sjhb			else
156185059Sjhb				continue;
157185059Sjhb		}
158196520Sjhb		if (matches > 0)
159196520Sjhb			goto matched;
160185059Sjhb		if (resource_long_value(name, unit, "irq", &value) == 0) {
161185059Sjhb			if (isa_match_resource_hint(child, SYS_RES_IRQ, value))
162185059Sjhb				matches++;
163185059Sjhb			else
164185059Sjhb				continue;
165185059Sjhb		}
166185059Sjhb		if (resource_long_value(name, unit, "drq", &value) == 0) {
167185059Sjhb			if (isa_match_resource_hint(child, SYS_RES_DRQ, value))
168185059Sjhb				matches++;
169185059Sjhb			else
170185059Sjhb				continue;
171185059Sjhb		}
17247178Sdfr
173196520Sjhb	matched:
174185059Sjhb		if (matches > 0) {
175185059Sjhb			/* We have a winner! */
176185059Sjhb			*unitp = unit;
177185059Sjhb			break;
178185059Sjhb		}
179185059Sjhb	}
180185059Sjhb}
181