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