isa_common.c revision 140647
147398Sdfr/*- 247398Sdfr * Copyright (c) 1999 Doug Rabson 347398Sdfr * All rights reserved. 447398Sdfr * 547398Sdfr * Redistribution and use in source and binary forms, with or without 647398Sdfr * modification, are permitted provided that the following conditions 747398Sdfr * are met: 847398Sdfr * 1. Redistributions of source code must retain the above copyright 947398Sdfr * notice, this list of conditions and the following disclaimer. 1047398Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1147398Sdfr * notice, this list of conditions and the following disclaimer in the 1247398Sdfr * documentation and/or other materials provided with the distribution. 1347398Sdfr * 1447398Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1547398Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1647398Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1747398Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1847398Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1947398Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2047398Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2147398Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2247398Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2347398Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2447398Sdfr * SUCH DAMAGE. 2547398Sdfr */ 2647398Sdfr/* 2747398Sdfr * Modifications for Intel architecture by Garrett A. Wollman. 2847398Sdfr * Copyright 1998 Massachusetts Institute of Technology 2947398Sdfr * 3047398Sdfr * Permission to use, copy, modify, and distribute this software and 3147398Sdfr * its documentation for any purpose and without fee is hereby 3247398Sdfr * granted, provided that both the above copyright notice and this 3347398Sdfr * permission notice appear in all copies, that both the above 3447398Sdfr * copyright notice and this permission notice appear in all 3547398Sdfr * supporting documentation, and that the name of M.I.T. not be used 3647398Sdfr * in advertising or publicity pertaining to distribution of the 3747398Sdfr * software without specific, written prior permission. M.I.T. makes 3847398Sdfr * no representations about the suitability of this software for any 3947398Sdfr * purpose. It is provided "as is" without express or implied 4047398Sdfr * warranty. 4147398Sdfr * 4247398Sdfr * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 4347398Sdfr * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 4447398Sdfr * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 4547398Sdfr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 4647398Sdfr * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4747398Sdfr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 4847398Sdfr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 4947398Sdfr * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 5047398Sdfr * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 5147398Sdfr * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 5247398Sdfr * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5347398Sdfr * SUCH DAMAGE. 5447398Sdfr */ 5547398Sdfr 5647398Sdfr/* 5747398Sdfr * Parts of the ISA bus implementation common to all architectures. 5847398Sdfr */ 5947398Sdfr 60116181Sobrien#include <sys/cdefs.h> 61116181Sobrien__FBSDID("$FreeBSD: head/sys/isa/isa_common.c 140647 2005-01-23 03:03:58Z imp $"); 62116181Sobrien 6347398Sdfr#include <sys/param.h> 6447398Sdfr#include <sys/systm.h> 6547398Sdfr#include <sys/kernel.h> 6647398Sdfr#include <sys/bus.h> 6747398Sdfr#include <sys/malloc.h> 6847398Sdfr#include <sys/module.h> 6947398Sdfr#include <machine/bus.h> 7047398Sdfr#include <sys/rman.h> 7147398Sdfr 7247398Sdfr#include <machine/resource.h> 7347398Sdfr 7447398Sdfr#include <isa/isavar.h> 7547398Sdfr#include <isa/isa_common.h> 7647398Sdfr#ifdef __alpha__ /* XXX workaround a stupid warning */ 7747398Sdfr#include <alpha/isa/isavar.h> 7847398Sdfr#endif 7947398Sdfr 8062987Sjhbstatic int isa_print_child(device_t bus, device_t dev); 8162987Sjhb 8269774Sphkstatic MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); 8347398Sdfr 8453094Sdfrstatic int isa_running; 8547398Sdfr 8647398Sdfr/* 8747398Sdfr * At 'probe' time, we add all the devices which we know about to the 8847398Sdfr * bus. The generic attach routine will probe and attach them if they 8947398Sdfr * are alive. 9047398Sdfr */ 9147398Sdfrstatic int 9247398Sdfrisa_probe(device_t dev) 9347398Sdfr{ 9447398Sdfr device_set_desc(dev, "ISA bus"); 9588376Stmm isa_init(dev); /* Allow machdep code to initialise */ 96139273Simp return (0); 9747398Sdfr} 9847398Sdfr 9947398Sdfrextern device_t isa_bus_device; 10047398Sdfr 10147398Sdfrstatic int 10247398Sdfrisa_attach(device_t dev) 10347398Sdfr{ 10447398Sdfr /* 10550769Sdfr * Arrange for isa_probe_children(dev) to be called later. XXX 10647398Sdfr */ 10747398Sdfr isa_bus_device = dev; 108139273Simp return (0); 10947398Sdfr} 11047398Sdfr 11147398Sdfr/* 11250769Sdfr * Find a working set of memory regions for a child using the ranges 11350769Sdfr * in *config and return the regions in *result. Returns non-zero if 11450769Sdfr * a set of ranges was found. 11550769Sdfr */ 11650769Sdfrstatic int 117139273Simpisa_find_memory(device_t child, struct isa_config *config, 118139273Simp struct isa_config *result) 11950769Sdfr{ 12050769Sdfr int success, i; 12150769Sdfr struct resource *res[ISA_NMEM]; 12250769Sdfr 12350769Sdfr /* 12450769Sdfr * First clear out any existing resource definitions. 12550769Sdfr */ 12650769Sdfr for (i = 0; i < ISA_NMEM; i++) { 12752174Sdfr bus_delete_resource(child, SYS_RES_MEMORY, i); 12850769Sdfr res[i] = NULL; 12950769Sdfr } 13050769Sdfr 13150769Sdfr success = 1; 13250769Sdfr result->ic_nmem = config->ic_nmem; 13350769Sdfr for (i = 0; i < config->ic_nmem; i++) { 134139273Simp uint32_t start, end, size, align; 13583051Syokota 13683051Syokota size = config->ic_mem[i].ir_size; 13783051Syokota 13883051Syokota /* the PnP device may have a null resource as filler */ 13983051Syokota if (size == 0) { 14083051Syokota result->ic_mem[i].ir_start = 0; 14183051Syokota result->ic_mem[i].ir_end = 0; 14283051Syokota result->ic_mem[i].ir_size = 0; 14383051Syokota result->ic_mem[i].ir_align = 0; 14483051Syokota continue; 14583051Syokota } 14683051Syokota 14750769Sdfr for (start = config->ic_mem[i].ir_start, 14850769Sdfr end = config->ic_mem[i].ir_end, 14950769Sdfr align = config->ic_mem[i].ir_align; 150140647Simp start + size - 1 <= end && start + size > start; 15150769Sdfr start += align) { 15252174Sdfr bus_set_resource(child, SYS_RES_MEMORY, i, 15350769Sdfr start, size); 154139360Simp res[i] = bus_alloc_resource(child, 155139360Simp SYS_RES_MEMORY, &i, 0, ~0, 1, 156139360Simp rman_make_alignment_flags(align) /* !RF_ACTIVE */); 15750769Sdfr if (res[i]) { 15850769Sdfr result->ic_mem[i].ir_start = start; 15950769Sdfr result->ic_mem[i].ir_end = start + size - 1; 16050769Sdfr result->ic_mem[i].ir_size = size; 16150769Sdfr result->ic_mem[i].ir_align = align; 16250769Sdfr break; 16350769Sdfr } 16450769Sdfr } 16550769Sdfr 16650769Sdfr /* 16750769Sdfr * If we didn't find a place for memory range i, then 16850769Sdfr * give up now. 16950769Sdfr */ 17050769Sdfr if (!res[i]) { 17150769Sdfr success = 0; 17250769Sdfr break; 17350769Sdfr } 17450769Sdfr } 17550769Sdfr 17650769Sdfr for (i = 0; i < ISA_NMEM; i++) { 17750769Sdfr if (res[i]) 17850769Sdfr bus_release_resource(child, SYS_RES_MEMORY, 17950769Sdfr i, res[i]); 18050769Sdfr } 18150769Sdfr 182139273Simp return (success); 18350769Sdfr} 18450769Sdfr 18550769Sdfr/* 18650769Sdfr * Find a working set of port regions for a child using the ranges 18750769Sdfr * in *config and return the regions in *result. Returns non-zero if 18850769Sdfr * a set of ranges was found. 18950769Sdfr */ 19050769Sdfrstatic int 191139273Simpisa_find_port(device_t child, struct isa_config *config, 192139273Simp struct isa_config *result) 19350769Sdfr{ 19450769Sdfr int success, i; 19550769Sdfr struct resource *res[ISA_NPORT]; 19650769Sdfr 19750769Sdfr /* 19850769Sdfr * First clear out any existing resource definitions. 19950769Sdfr */ 20050769Sdfr for (i = 0; i < ISA_NPORT; i++) { 20152174Sdfr bus_delete_resource(child, SYS_RES_IOPORT, i); 20250769Sdfr res[i] = NULL; 20350769Sdfr } 20450769Sdfr 20550769Sdfr success = 1; 20650769Sdfr result->ic_nport = config->ic_nport; 20750769Sdfr for (i = 0; i < config->ic_nport; i++) { 208139273Simp uint32_t start, end, size, align; 20983051Syokota 21083051Syokota size = config->ic_port[i].ir_size; 21183051Syokota 21283051Syokota /* the PnP device may have a null resource as filler */ 21383051Syokota if (size == 0) { 21483051Syokota result->ic_port[i].ir_start = 0; 21583051Syokota result->ic_port[i].ir_end = 0; 21683051Syokota result->ic_port[i].ir_size = 0; 21783051Syokota result->ic_port[i].ir_align = 0; 21883051Syokota continue; 21983051Syokota } 22083051Syokota 22150769Sdfr for (start = config->ic_port[i].ir_start, 22250769Sdfr end = config->ic_port[i].ir_end, 22350769Sdfr align = config->ic_port[i].ir_align; 22450769Sdfr start + size - 1 <= end; 22550769Sdfr start += align) { 22652174Sdfr bus_set_resource(child, SYS_RES_IOPORT, i, 22750769Sdfr start, size); 228139360Simp res[i] = bus_alloc_resource(child, 229139360Simp SYS_RES_IOPORT, &i, 0, ~0, 1, 230139360Simp rman_make_alignment_flags(align) /* !RF_ACTIVE */); 23150769Sdfr if (res[i]) { 23250769Sdfr result->ic_port[i].ir_start = start; 23350769Sdfr result->ic_port[i].ir_end = start + size - 1; 23450769Sdfr result->ic_port[i].ir_size = size; 23550769Sdfr result->ic_port[i].ir_align = align; 23650769Sdfr break; 23750769Sdfr } 23850769Sdfr } 23950769Sdfr 24050769Sdfr /* 24150769Sdfr * If we didn't find a place for port range i, then 24250769Sdfr * give up now. 24350769Sdfr */ 24450769Sdfr if (!res[i]) { 24550769Sdfr success = 0; 24650769Sdfr break; 24750769Sdfr } 24850769Sdfr } 24950769Sdfr 25050769Sdfr for (i = 0; i < ISA_NPORT; i++) { 25150769Sdfr if (res[i]) 25250769Sdfr bus_release_resource(child, SYS_RES_IOPORT, 25350769Sdfr i, res[i]); 25450769Sdfr } 25550769Sdfr 25650769Sdfr return success; 25750769Sdfr} 25850769Sdfr 25950769Sdfr/* 26050769Sdfr * Return the index of the first bit in the mask (or -1 if mask is empty. 26150769Sdfr */ 26250769Sdfrstatic int 263139273Simpfind_first_bit(uint32_t mask) 26450769Sdfr{ 265139273Simp return (ffs(mask) - 1); 26650769Sdfr} 26750769Sdfr 26850769Sdfr/* 26950769Sdfr * Return the index of the next bit in the mask, or -1 if there are no more. 27050769Sdfr */ 27150769Sdfrstatic int 272139273Simpfind_next_bit(uint32_t mask, int bit) 27350769Sdfr{ 27450769Sdfr bit++; 27550769Sdfr while (bit < 32 && !(mask & (1 << bit))) 27650769Sdfr bit++; 27750769Sdfr if (bit != 32) 278139273Simp return (bit); 279139273Simp return (-1); 28050769Sdfr} 28150769Sdfr 28250769Sdfr/* 28350769Sdfr * Find a working set of irqs for a child using the masks in *config 28450769Sdfr * and return the regions in *result. Returns non-zero if a set of 28550769Sdfr * irqs was found. 28650769Sdfr */ 28750769Sdfrstatic int 288139273Simpisa_find_irq(device_t child, struct isa_config *config, 289139273Simp struct isa_config *result) 29050769Sdfr{ 29150769Sdfr int success, i; 29250769Sdfr struct resource *res[ISA_NIRQ]; 29350769Sdfr 29450769Sdfr /* 29550769Sdfr * First clear out any existing resource definitions. 29650769Sdfr */ 29750769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 29852174Sdfr bus_delete_resource(child, SYS_RES_IRQ, i); 29950769Sdfr res[i] = NULL; 30050769Sdfr } 30150769Sdfr 30250769Sdfr success = 1; 30350769Sdfr result->ic_nirq = config->ic_nirq; 30450769Sdfr for (i = 0; i < config->ic_nirq; i++) { 305139273Simp uint32_t mask = config->ic_irqmask[i]; 30650769Sdfr int irq; 30783051Syokota 30883051Syokota /* the PnP device may have a null resource as filler */ 30983051Syokota if (mask == 0) { 31083051Syokota result->ic_irqmask[i] = 0; 31183051Syokota continue; 31283051Syokota } 31383051Syokota 31450769Sdfr for (irq = find_first_bit(mask); 31550769Sdfr irq != -1; 31650769Sdfr irq = find_next_bit(mask, irq)) { 31752174Sdfr bus_set_resource(child, SYS_RES_IRQ, i, 31850769Sdfr irq, 1); 319127135Snjl res[i] = bus_alloc_resource_any(child, 320127135Snjl SYS_RES_IRQ, &i, 321127135Snjl 0 /* !RF_ACTIVE */ ); 32250769Sdfr if (res[i]) { 32350769Sdfr result->ic_irqmask[i] = (1 << irq); 32450769Sdfr break; 32550769Sdfr } 32650769Sdfr } 32750769Sdfr 32850769Sdfr /* 32950769Sdfr * If we didn't find a place for irq range i, then 33050769Sdfr * give up now. 33150769Sdfr */ 33250769Sdfr if (!res[i]) { 33350769Sdfr success = 0; 33450769Sdfr break; 33550769Sdfr } 33650769Sdfr } 33750769Sdfr 33850769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 33950769Sdfr if (res[i]) 34050769Sdfr bus_release_resource(child, SYS_RES_IRQ, 34150769Sdfr i, res[i]); 34250769Sdfr } 34350769Sdfr 344139273Simp return (success); 34550769Sdfr} 34650769Sdfr 34750769Sdfr/* 34850769Sdfr * Find a working set of drqs for a child using the masks in *config 34950769Sdfr * and return the regions in *result. Returns non-zero if a set of 35050769Sdfr * drqs was found. 35150769Sdfr */ 35250769Sdfrstatic int 353139273Simpisa_find_drq(device_t child, struct isa_config *config, 354139273Simp struct isa_config *result) 35550769Sdfr{ 35650769Sdfr int success, i; 35750769Sdfr struct resource *res[ISA_NDRQ]; 35850769Sdfr 35950769Sdfr /* 36050769Sdfr * First clear out any existing resource definitions. 36150769Sdfr */ 36250769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 36352174Sdfr bus_delete_resource(child, SYS_RES_DRQ, i); 36450769Sdfr res[i] = NULL; 36550769Sdfr } 36650769Sdfr 36750769Sdfr success = 1; 36850769Sdfr result->ic_ndrq = config->ic_ndrq; 36950769Sdfr for (i = 0; i < config->ic_ndrq; i++) { 370139273Simp uint32_t mask = config->ic_drqmask[i]; 37150769Sdfr int drq; 37283051Syokota 37383051Syokota /* the PnP device may have a null resource as filler */ 37483051Syokota if (mask == 0) { 37583051Syokota result->ic_drqmask[i] = 0; 37683051Syokota continue; 37783051Syokota } 37883051Syokota 37950769Sdfr for (drq = find_first_bit(mask); 38050769Sdfr drq != -1; 38150769Sdfr drq = find_next_bit(mask, drq)) { 38252174Sdfr bus_set_resource(child, SYS_RES_DRQ, i, 38350769Sdfr drq, 1); 384127135Snjl res[i] = bus_alloc_resource_any(child, 385127135Snjl SYS_RES_DRQ, &i, 386127135Snjl 0 /* !RF_ACTIVE */); 38750769Sdfr if (res[i]) { 38850769Sdfr result->ic_drqmask[i] = (1 << drq); 38950769Sdfr break; 39050769Sdfr } 39150769Sdfr } 39250769Sdfr 39350769Sdfr /* 39450769Sdfr * If we didn't find a place for drq range i, then 39550769Sdfr * give up now. 39650769Sdfr */ 39750769Sdfr if (!res[i]) { 39850769Sdfr success = 0; 39950769Sdfr break; 40050769Sdfr } 40150769Sdfr } 40250769Sdfr 40350769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 40450769Sdfr if (res[i]) 40550769Sdfr bus_release_resource(child, SYS_RES_DRQ, 40650769Sdfr i, res[i]); 40750769Sdfr } 40850769Sdfr 409139273Simp return (success); 41050769Sdfr} 41150769Sdfr 41250769Sdfr/* 41350769Sdfr * Attempt to find a working set of resources for a device. Return 41450769Sdfr * non-zero if a working configuration is found. 41550769Sdfr */ 41650769Sdfrstatic int 41750769Sdfrisa_assign_resources(device_t child) 41850769Sdfr{ 41950769Sdfr struct isa_device *idev = DEVTOISA(child); 42050769Sdfr struct isa_config_entry *ice; 42181401Sjulian struct isa_config *cfg; 42291206Salfred const char *reason; 42391206Salfred 42491206Salfred reason = "Empty ISA id_configs"; 42581401Sjulian cfg = malloc(sizeof(struct isa_config), M_TEMP, M_NOWAIT|M_ZERO); 42681401Sjulian if (cfg == NULL) 42781401Sjulian return(0); 42850769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 42991202Salfred reason = "memory"; 43081401Sjulian if (!isa_find_memory(child, &ice->ice_config, cfg)) 43150769Sdfr continue; 43291202Salfred reason = "port"; 43381401Sjulian if (!isa_find_port(child, &ice->ice_config, cfg)) 43450769Sdfr continue; 43591202Salfred reason = "irq"; 43681401Sjulian if (!isa_find_irq(child, &ice->ice_config, cfg)) 43750769Sdfr continue; 43891202Salfred reason = "drq"; 43981401Sjulian if (!isa_find_drq(child, &ice->ice_config, cfg)) 44050769Sdfr continue; 44150769Sdfr 44250769Sdfr /* 44350769Sdfr * A working configuration was found enable the device 44450769Sdfr * with this configuration. 44550769Sdfr */ 44691202Salfred reason = "no callback"; 44750769Sdfr if (idev->id_config_cb) { 44850769Sdfr idev->id_config_cb(idev->id_config_arg, 44981401Sjulian cfg, 1); 45081401Sjulian free(cfg, M_TEMP); 451139273Simp return (1); 45250769Sdfr } 45350769Sdfr } 45450769Sdfr 45550769Sdfr /* 45650769Sdfr * Disable the device. 45750769Sdfr */ 45862987Sjhb bus_print_child_header(device_get_parent(child), child); 45991202Salfred printf(" can't assign resources (%s)\n", reason); 46062987Sjhb if (bootverbose) 461139273Simp isa_print_child(device_get_parent(child), child); 46281401Sjulian bzero(cfg, sizeof (*cfg)); 46350769Sdfr if (idev->id_config_cb) 46481401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 46550769Sdfr device_disable(child); 46650769Sdfr 46781401Sjulian free(cfg, M_TEMP); 468139273Simp return (0); 46950769Sdfr} 47050769Sdfr 47150769Sdfr/* 47283051Syokota * Return non-zero if the device has a single configuration, that is, 47383051Syokota * a fixed set of resoruces. 47483051Syokota */ 47583051Syokotastatic int 47683051Syokotaisa_has_single_config(device_t dev) 47783051Syokota{ 47883051Syokota struct isa_device *idev = DEVTOISA(dev); 47983051Syokota struct isa_config_entry *ice; 480139273Simp uint32_t mask; 48183051Syokota int i; 48283051Syokota 48383051Syokota ice = TAILQ_FIRST(&idev->id_configs); 48483051Syokota if (TAILQ_NEXT(ice, ice_link)) 485139273Simp return (0); 48683051Syokota 48783051Syokota for (i = 0; i < ice->ice_config.ic_nmem; ++i) { 48883051Syokota if (ice->ice_config.ic_mem[i].ir_size == 0) 48983051Syokota continue; 49083051Syokota if (ice->ice_config.ic_mem[i].ir_end != 49183051Syokota ice->ice_config.ic_mem[i].ir_start + 49283051Syokota ice->ice_config.ic_mem[i].ir_size - 1) 493139273Simp return (0); 49483051Syokota } 49583051Syokota for (i = 0; i < ice->ice_config.ic_nport; ++i) { 49683051Syokota if (ice->ice_config.ic_port[i].ir_size == 0) 49783051Syokota continue; 49883051Syokota if (ice->ice_config.ic_port[i].ir_end != 49983051Syokota ice->ice_config.ic_port[i].ir_start + 50083051Syokota ice->ice_config.ic_port[i].ir_size - 1) 501139273Simp return (0); 50283051Syokota } 50383051Syokota for (i = 0; i < ice->ice_config.ic_nirq; ++i) { 50483051Syokota mask = ice->ice_config.ic_irqmask[i]; 50583051Syokota if (mask == 0) 50683051Syokota continue; 50783051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 508139273Simp return (0); 50983051Syokota } 51083051Syokota for (i = 0; i < ice->ice_config.ic_ndrq; ++i) { 51183051Syokota mask = ice->ice_config.ic_drqmask[i]; 51283051Syokota if (mask == 0) 51383051Syokota continue; 51483051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 515139273Simp return (0); 51683051Syokota } 517139273Simp return (1); 51883051Syokota} 51983051Syokota 52083051Syokota/* 52150769Sdfr * Called after other devices have initialised to probe for isa devices. 52250769Sdfr */ 52350769Sdfrvoid 52450769Sdfrisa_probe_children(device_t dev) 52550769Sdfr{ 52650769Sdfr device_t *children; 52781401Sjulian struct isa_config *cfg; 52850769Sdfr int nchildren, i; 52950769Sdfr 53053094Sdfr /* 53153094Sdfr * Create all the children by calling driver's identify methods. 53253094Sdfr */ 53353094Sdfr bus_generic_probe(dev); 53453094Sdfr 53550769Sdfr if (device_get_children(dev, &children, &nchildren)) 53650769Sdfr return; 53750769Sdfr 53850769Sdfr /* 53951905Sdfr * First disable all pnp devices so that they don't get 54051905Sdfr * matched by legacy probes. 54151905Sdfr */ 54253094Sdfr if (bootverbose) 54353094Sdfr printf("isa_probe_children: disabling PnP devices\n"); 54481401Sjulian 54581401Sjulian cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 54681401Sjulian if (cfg == NULL) { 54781401Sjulian free(children, M_TEMP); 54881401Sjulian return; 54981401Sjulian } 55081401Sjulian 55151905Sdfr for (i = 0; i < nchildren; i++) { 55251905Sdfr device_t child = children[i]; 55351905Sdfr struct isa_device *idev = DEVTOISA(child); 55451905Sdfr 55581401Sjulian bzero(cfg, sizeof(*cfg)); 55651905Sdfr if (idev->id_config_cb) 55781401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 55851905Sdfr } 55951905Sdfr 56081401Sjulian free(cfg, M_TEMP); 56181401Sjulian 56251905Sdfr /* 56351905Sdfr * Next probe all non-pnp devices so that they claim their 56450769Sdfr * resources first. 56550769Sdfr */ 56653094Sdfr if (bootverbose) 56753094Sdfr printf("isa_probe_children: probing non-PnP devices\n"); 56850769Sdfr for (i = 0; i < nchildren; i++) { 56950769Sdfr device_t child = children[i]; 57050769Sdfr struct isa_device *idev = DEVTOISA(child); 57150769Sdfr 57250769Sdfr if (TAILQ_FIRST(&idev->id_configs)) 57350769Sdfr continue; 57450769Sdfr 57550769Sdfr device_probe_and_attach(child); 57650769Sdfr } 57750769Sdfr 57850769Sdfr /* 57951905Sdfr * Finally assign resource to pnp devices and probe them. 58050769Sdfr */ 58153094Sdfr if (bootverbose) 58253094Sdfr printf("isa_probe_children: probing PnP devices\n"); 58350769Sdfr for (i = 0; i < nchildren; i++) { 58450769Sdfr device_t child = children[i]; 58550769Sdfr struct isa_device* idev = DEVTOISA(child); 58650769Sdfr 58750769Sdfr if (!TAILQ_FIRST(&idev->id_configs)) 58850769Sdfr continue; 58950769Sdfr 59050769Sdfr if (isa_assign_resources(child)) { 59152174Sdfr struct resource_list *rl = &idev->id_resources; 59250769Sdfr struct resource_list_entry *rle; 59350769Sdfr 59450769Sdfr device_probe_and_attach(child); 59550769Sdfr 59650769Sdfr /* 59750769Sdfr * Claim any unallocated resources to keep other 59850769Sdfr * devices from using them. 59950769Sdfr */ 60052174Sdfr SLIST_FOREACH(rle, rl, link) { 60150769Sdfr if (!rle->res) { 60250769Sdfr int rid = rle->rid; 60352174Sdfr resource_list_alloc(rl, dev, child, 60450769Sdfr rle->type, 60550769Sdfr &rid, 60662059Sdfr 0, ~0, 1, 0); 60750769Sdfr } 60850769Sdfr } 60950769Sdfr } 61050769Sdfr } 61150769Sdfr 61250769Sdfr free(children, M_TEMP); 61353094Sdfr 61453094Sdfr isa_running = 1; 61550769Sdfr} 61650769Sdfr 61750769Sdfr/* 61847398Sdfr * Add a new child with default ivars. 61947398Sdfr */ 62047398Sdfrstatic device_t 62147578Sdfrisa_add_child(device_t dev, int order, const char *name, int unit) 62247398Sdfr{ 62354073Smdodd device_t child; 62447398Sdfr struct isa_device *idev; 62547398Sdfr 626104179Sphk child = device_add_child_ordered(dev, order, name, unit); 627104179Sphk if (child == NULL) 628104179Sphk return (child); 629104179Sphk 63069781Sdwmalone idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 63147398Sdfr if (!idev) 632139273Simp return (0); 63347398Sdfr 63447398Sdfr resource_list_init(&idev->id_resources); 63550769Sdfr TAILQ_INIT(&idev->id_configs); 63647398Sdfr 637104179Sphk device_set_ivars(child, idev); 63854073Smdodd 639104179Sphk return (child); 64047398Sdfr} 64147398Sdfr 64262059Sdfrstatic int 64362059Sdfrisa_print_all_resources(device_t dev) 64447398Sdfr{ 64547398Sdfr struct isa_device *idev = DEVTOISA(dev); 64647398Sdfr struct resource_list *rl = &idev->id_resources; 64749195Smdodd int retval = 0; 64847398Sdfr 64951052Sdfr if (SLIST_FIRST(rl) || device_get_flags(dev)) 65049195Smdodd retval += printf(" at"); 65147398Sdfr 65288376Stmm retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 65388376Stmm retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 65488376Stmm retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 65588376Stmm retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld"); 65651052Sdfr if (device_get_flags(dev)) 65751052Sdfr retval += printf(" flags %#x", device_get_flags(dev)); 65847398Sdfr 659139273Simp return (retval); 66062059Sdfr} 66162059Sdfr 66262059Sdfrstatic int 66362059Sdfrisa_print_child(device_t bus, device_t dev) 66462059Sdfr{ 66562059Sdfr int retval = 0; 66662059Sdfr 66762059Sdfr retval += bus_print_child_header(bus, dev); 66862059Sdfr retval += isa_print_all_resources(dev); 66949195Smdodd retval += bus_print_child_footer(bus, dev); 67049195Smdodd 67149195Smdodd return (retval); 67247398Sdfr} 67347398Sdfr 67462059Sdfrstatic void 67562059Sdfrisa_probe_nomatch(device_t dev, device_t child) 67662059Sdfr{ 67762987Sjhb if (bootverbose) { 67862987Sjhb bus_print_child_header(dev, child); 67962987Sjhb printf(" failed to probe"); 68062059Sdfr isa_print_all_resources(child); 68162987Sjhb bus_print_child_footer(dev, child); 68262987Sjhb } 68362059Sdfr 68462059Sdfr return; 68562059Sdfr} 68662059Sdfr 68747398Sdfrstatic int 68847398Sdfrisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 68947398Sdfr{ 69047398Sdfr struct isa_device* idev = DEVTOISA(dev); 69147398Sdfr struct resource_list *rl = &idev->id_resources; 69247398Sdfr struct resource_list_entry *rle; 69347398Sdfr 69447398Sdfr switch (index) { 69547398Sdfr case ISA_IVAR_PORT_0: 69647398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 69747398Sdfr if (rle) 69847398Sdfr *result = rle->start; 69947398Sdfr else 70047398Sdfr *result = -1; 70147398Sdfr break; 70247398Sdfr 70347398Sdfr case ISA_IVAR_PORT_1: 70447398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 70547398Sdfr if (rle) 70647398Sdfr *result = rle->start; 70747398Sdfr else 70847398Sdfr *result = -1; 70947398Sdfr break; 71047398Sdfr 71147398Sdfr case ISA_IVAR_PORTSIZE_0: 71247398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 71347398Sdfr if (rle) 71447398Sdfr *result = rle->count; 71547398Sdfr else 71647398Sdfr *result = 0; 71747398Sdfr break; 71847398Sdfr 71947398Sdfr case ISA_IVAR_PORTSIZE_1: 72047398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 72147398Sdfr if (rle) 72247398Sdfr *result = rle->count; 72347398Sdfr else 72447398Sdfr *result = 0; 72547398Sdfr break; 72647398Sdfr 72747398Sdfr case ISA_IVAR_MADDR_0: 72847398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 72947398Sdfr if (rle) 73047398Sdfr *result = rle->start; 73147398Sdfr else 73247398Sdfr *result = -1; 73347398Sdfr break; 73447398Sdfr 73547398Sdfr case ISA_IVAR_MADDR_1: 73647398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 73747398Sdfr if (rle) 73847398Sdfr *result = rle->start; 73947398Sdfr else 74047398Sdfr *result = -1; 74147398Sdfr break; 74247398Sdfr 743105139Sjhb case ISA_IVAR_MEMSIZE_0: 74447398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 74547398Sdfr if (rle) 74647398Sdfr *result = rle->count; 74747398Sdfr else 74847398Sdfr *result = 0; 74947398Sdfr break; 75047398Sdfr 751105139Sjhb case ISA_IVAR_MEMSIZE_1: 75247398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 75347398Sdfr if (rle) 75447398Sdfr *result = rle->count; 75547398Sdfr else 75647398Sdfr *result = 0; 75747398Sdfr break; 75847398Sdfr 75947398Sdfr case ISA_IVAR_IRQ_0: 76047398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 0); 76147398Sdfr if (rle) 76247398Sdfr *result = rle->start; 76347398Sdfr else 76447398Sdfr *result = -1; 76547398Sdfr break; 76647398Sdfr 76747398Sdfr case ISA_IVAR_IRQ_1: 76847398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 1); 76947398Sdfr if (rle) 77047398Sdfr *result = rle->start; 77147398Sdfr else 77247398Sdfr *result = -1; 77347398Sdfr break; 77447398Sdfr 77547398Sdfr case ISA_IVAR_DRQ_0: 77647398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 0); 77747398Sdfr if (rle) 77847398Sdfr *result = rle->start; 77947398Sdfr else 78047398Sdfr *result = -1; 78147398Sdfr break; 78247398Sdfr 78347398Sdfr case ISA_IVAR_DRQ_1: 78447398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 1); 78547398Sdfr if (rle) 78647398Sdfr *result = rle->start; 78747398Sdfr else 78847398Sdfr *result = -1; 78947398Sdfr break; 79047398Sdfr 79147613Sdfr case ISA_IVAR_VENDORID: 79247613Sdfr *result = idev->id_vendorid; 79347613Sdfr break; 79447613Sdfr 79547613Sdfr case ISA_IVAR_SERIAL: 79647613Sdfr *result = idev->id_serial; 79747613Sdfr break; 79847613Sdfr 79947613Sdfr case ISA_IVAR_LOGICALID: 80047613Sdfr *result = idev->id_logicalid; 80147613Sdfr break; 80247613Sdfr 80347613Sdfr case ISA_IVAR_COMPATID: 80447613Sdfr *result = idev->id_compatid; 80547613Sdfr break; 80647613Sdfr 80782863Syokota case ISA_IVAR_CONFIGATTR: 80882863Syokota *result = idev->id_config_attr; 80982863Syokota break; 81082863Syokota 81147613Sdfr default: 812139273Simp return (ENOENT); 81347398Sdfr } 81447613Sdfr 815139273Simp return (0); 81647398Sdfr} 81747398Sdfr 81847398Sdfrstatic int 819139273Simpisa_write_ivar(device_t bus, device_t dev, int index, uintptr_t value) 82047398Sdfr{ 82147398Sdfr struct isa_device* idev = DEVTOISA(dev); 82247398Sdfr 82347398Sdfr switch (index) { 82447398Sdfr case ISA_IVAR_PORT_0: 82547398Sdfr case ISA_IVAR_PORT_1: 82647398Sdfr case ISA_IVAR_PORTSIZE_0: 82747398Sdfr case ISA_IVAR_PORTSIZE_1: 82847398Sdfr case ISA_IVAR_MADDR_0: 82947398Sdfr case ISA_IVAR_MADDR_1: 830105139Sjhb case ISA_IVAR_MEMSIZE_0: 831105139Sjhb case ISA_IVAR_MEMSIZE_1: 83247398Sdfr case ISA_IVAR_IRQ_0: 83347398Sdfr case ISA_IVAR_IRQ_1: 83447398Sdfr case ISA_IVAR_DRQ_0: 83547398Sdfr case ISA_IVAR_DRQ_1: 836139273Simp return (EINVAL); 83747398Sdfr 83847613Sdfr case ISA_IVAR_VENDORID: 83947613Sdfr idev->id_vendorid = value; 84047613Sdfr break; 84147613Sdfr 84247613Sdfr case ISA_IVAR_SERIAL: 84347613Sdfr idev->id_serial = value; 84447613Sdfr break; 84547613Sdfr 84647613Sdfr case ISA_IVAR_LOGICALID: 84747613Sdfr idev->id_logicalid = value; 84847613Sdfr break; 84947613Sdfr 85047613Sdfr case ISA_IVAR_COMPATID: 85147613Sdfr idev->id_compatid = value; 85247613Sdfr break; 85347613Sdfr 85482863Syokota case ISA_IVAR_CONFIGATTR: 85582863Syokota idev->id_config_attr = value; 85682863Syokota break; 85782863Syokota 85847398Sdfr default: 85947398Sdfr return (ENOENT); 86047398Sdfr } 86147613Sdfr 86247398Sdfr return (0); 86347398Sdfr} 86447398Sdfr 86550769Sdfr/* 86650769Sdfr * Free any resources which the driver missed or which we were holding for 86750769Sdfr * it (see isa_probe_children). 86850769Sdfr */ 86950769Sdfrstatic void 87050769Sdfrisa_child_detached(device_t dev, device_t child) 87150769Sdfr{ 87250769Sdfr struct isa_device* idev = DEVTOISA(child); 87352174Sdfr struct resource_list *rl = &idev->id_resources; 87450769Sdfr struct resource_list_entry *rle; 87550769Sdfr 87662059Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 87762059Sdfr /* 87862059Sdfr * Claim any unallocated resources to keep other 87962059Sdfr * devices from using them. 88062059Sdfr */ 88162059Sdfr SLIST_FOREACH(rle, rl, link) { 88262059Sdfr if (!rle->res) { 88362059Sdfr int rid = rle->rid; 88462059Sdfr resource_list_alloc(rl, dev, child, 88562059Sdfr rle->type, 88662059Sdfr &rid, 0, ~0, 1, 0); 88762059Sdfr } 88862059Sdfr } 88950769Sdfr } 89050769Sdfr} 89150769Sdfr 89253094Sdfrstatic void 89353094Sdfrisa_driver_added(device_t dev, driver_t *driver) 89453094Sdfr{ 89553094Sdfr device_t *children; 89653094Sdfr int nchildren, i; 89753094Sdfr 89853094Sdfr /* 89953094Sdfr * Don't do anything if drivers are dynamically 90053094Sdfr * added during autoconfiguration (cf. ymf724). 90153094Sdfr * since that would end up calling identify 90253094Sdfr * twice. 90353094Sdfr */ 90453094Sdfr if (!isa_running) 90553094Sdfr return; 90653094Sdfr 90753094Sdfr DEVICE_IDENTIFY(driver, dev); 90853094Sdfr if (device_get_children(dev, &children, &nchildren)) 90953094Sdfr return; 91053094Sdfr 91153094Sdfr for (i = 0; i < nchildren; i++) { 91253094Sdfr device_t child = children[i]; 91353094Sdfr struct isa_device *idev = DEVTOISA(child); 91453094Sdfr struct resource_list *rl = &idev->id_resources; 91553094Sdfr struct resource_list_entry *rle; 91653094Sdfr 91753094Sdfr if (device_get_state(child) != DS_NOTPRESENT) 91853094Sdfr continue; 91962059Sdfr if (!device_is_enabled(child)) 92062059Sdfr continue; 92153094Sdfr 92262059Sdfr /* 92362059Sdfr * Free resources which we were holding on behalf of 92462059Sdfr * the device. 92562059Sdfr */ 92662059Sdfr SLIST_FOREACH(rle, &idev->id_resources, link) { 92762059Sdfr if (rle->res) 92862059Sdfr resource_list_release(rl, dev, child, 92962059Sdfr rle->type, 93062059Sdfr rle->rid, 93162059Sdfr rle->res); 93262059Sdfr } 93362059Sdfr 93453094Sdfr if (TAILQ_FIRST(&idev->id_configs)) 93553094Sdfr if (!isa_assign_resources(child)) 93653094Sdfr continue; 93753094Sdfr 93853094Sdfr device_probe_and_attach(child); 93953094Sdfr 94053094Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 94153094Sdfr /* 94253094Sdfr * Claim any unallocated resources to keep other 94353094Sdfr * devices from using them. 94453094Sdfr */ 94553094Sdfr SLIST_FOREACH(rle, rl, link) { 94653094Sdfr if (!rle->res) { 94753094Sdfr int rid = rle->rid; 94853094Sdfr resource_list_alloc(rl, dev, child, 94953094Sdfr rle->type, 95062059Sdfr &rid, 0, ~0, 1, 0); 95153094Sdfr } 95253094Sdfr } 95353094Sdfr } 95453094Sdfr } 95553094Sdfr 95653094Sdfr free(children, M_TEMP); 95753094Sdfr} 95853094Sdfr 95947398Sdfrstatic int 96047398Sdfrisa_set_resource(device_t dev, device_t child, int type, int rid, 961139273Simp u_long start, u_long count) 96247398Sdfr{ 96347398Sdfr struct isa_device* idev = DEVTOISA(child); 96447398Sdfr struct resource_list *rl = &idev->id_resources; 96547398Sdfr 96647398Sdfr if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 96747398Sdfr && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 968139273Simp return (EINVAL); 96950769Sdfr if (rid < 0) 970139273Simp return (EINVAL); 97150769Sdfr if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 972139273Simp return (EINVAL); 97350769Sdfr if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 974139273Simp return (EINVAL); 97550769Sdfr if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 976139273Simp return (EINVAL); 97750769Sdfr if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 978139273Simp return (EINVAL); 97947398Sdfr 98047398Sdfr resource_list_add(rl, type, rid, start, start + count - 1, count); 98147398Sdfr 982139273Simp return (0); 98347398Sdfr} 98447398Sdfr 98569295Smdoddstatic struct resource_list * 98669295Smdoddisa_get_resource_list (device_t dev, device_t child) 98747398Sdfr{ 98847398Sdfr struct isa_device* idev = DEVTOISA(child); 98947398Sdfr struct resource_list *rl = &idev->id_resources; 99047398Sdfr 99169295Smdodd if (!rl) 99269295Smdodd return (NULL); 99347398Sdfr 99469295Smdodd return (rl); 99547398Sdfr} 99647398Sdfr 99750769Sdfrstatic int 998139273Simpisa_add_config(device_t dev, device_t child, int priority, 999139273Simp struct isa_config *config) 100050769Sdfr{ 100150769Sdfr struct isa_device* idev = DEVTOISA(child); 100250769Sdfr struct isa_config_entry *newice, *ice; 100350769Sdfr 100450769Sdfr newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 100550769Sdfr if (!newice) 1006139273Simp return (ENOMEM); 100750769Sdfr 100850769Sdfr newice->ice_priority = priority; 100950769Sdfr newice->ice_config = *config; 101050769Sdfr 101150769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 101250769Sdfr if (ice->ice_priority > priority) 101350769Sdfr break; 101450769Sdfr } 101550769Sdfr if (ice) 101650769Sdfr TAILQ_INSERT_BEFORE(ice, newice, ice_link); 101750769Sdfr else 101850769Sdfr TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 101950769Sdfr 102083051Syokota if (isa_has_single_config(child)) 102183051Syokota idev->id_config_attr &= ~ISACFGATTR_MULTI; 102283051Syokota else 102383051Syokota idev->id_config_attr |= ISACFGATTR_MULTI; 102483051Syokota 1025139273Simp return (0); 102650769Sdfr} 102750769Sdfr 102850769Sdfrstatic void 1029139273Simpisa_set_config_callback(device_t dev, device_t child, isa_config_cb *fn, 1030139273Simp void *arg) 103150769Sdfr{ 103250769Sdfr struct isa_device* idev = DEVTOISA(child); 103350769Sdfr 103450769Sdfr idev->id_config_cb = fn; 103550769Sdfr idev->id_config_arg = arg; 103650769Sdfr} 103750769Sdfr 103850769Sdfrstatic int 103950769Sdfrisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 104050769Sdfr{ 104150769Sdfr struct isa_device* idev = DEVTOISA(child); 104250769Sdfr 104350769Sdfr if (!idev->id_vendorid) 1044139273Simp return (ENOENT); 104550769Sdfr 104682553Smsmith while (ids && ids->ip_id) { 104750769Sdfr /* 104850769Sdfr * Really ought to support >1 compat id per device. 104950769Sdfr */ 105050769Sdfr if (idev->id_logicalid == ids->ip_id 105150769Sdfr || idev->id_compatid == ids->ip_id) { 105250910Sdfr if (ids->ip_desc) 105350910Sdfr device_set_desc(child, ids->ip_desc); 1054139273Simp return (0); 105550769Sdfr } 105650769Sdfr ids++; 105750769Sdfr } 105850769Sdfr 1059139273Simp return (ENXIO); 106050769Sdfr} 106150769Sdfr 106247398Sdfrstatic device_method_t isa_methods[] = { 106347398Sdfr /* Device interface */ 106447398Sdfr DEVMETHOD(device_probe, isa_probe), 106547398Sdfr DEVMETHOD(device_attach, isa_attach), 106647398Sdfr DEVMETHOD(device_detach, bus_generic_detach), 106747398Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 106847398Sdfr DEVMETHOD(device_suspend, bus_generic_suspend), 106947398Sdfr DEVMETHOD(device_resume, bus_generic_resume), 107047398Sdfr 107147398Sdfr /* Bus interface */ 107247398Sdfr DEVMETHOD(bus_add_child, isa_add_child), 107347398Sdfr DEVMETHOD(bus_print_child, isa_print_child), 107462059Sdfr DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 107547398Sdfr DEVMETHOD(bus_read_ivar, isa_read_ivar), 107647398Sdfr DEVMETHOD(bus_write_ivar, isa_write_ivar), 107750769Sdfr DEVMETHOD(bus_child_detached, isa_child_detached), 107853094Sdfr DEVMETHOD(bus_driver_added, isa_driver_added), 107969295Smdodd DEVMETHOD(bus_setup_intr, isa_setup_intr), 108069295Smdodd DEVMETHOD(bus_teardown_intr, isa_teardown_intr), 108169295Smdodd 108269295Smdodd DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 108347398Sdfr DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 108447398Sdfr DEVMETHOD(bus_release_resource, isa_release_resource), 108569295Smdodd DEVMETHOD(bus_set_resource, isa_set_resource), 108669295Smdodd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 108769295Smdodd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 108847398Sdfr DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 108947398Sdfr DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 109047398Sdfr 109147398Sdfr /* ISA interface */ 109250769Sdfr DEVMETHOD(isa_add_config, isa_add_config), 109350769Sdfr DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 109450769Sdfr DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 109547398Sdfr 109647398Sdfr { 0, 0 } 109747398Sdfr}; 109847398Sdfr 1099139279Simpdriver_t isa_driver = { 110047398Sdfr "isa", 110147398Sdfr isa_methods, 110247398Sdfr 1, /* no softc */ 110347398Sdfr}; 110447398Sdfr 1105139279Simpdevclass_t isa_devclass; 1106139279Simp 110747398Sdfr/* 1108139279Simp * ISA can be attached to a PCI-ISA bridge, or other locations on some 1109139279Simp * platforms. 111047398Sdfr */ 111147398SdfrDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 111269942SmsmithDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 1113113498SmdoddMODULE_VERSION(isa, 1); 1114117337Sjhb 1115117337Sjhb/* 1116117337Sjhb * Code common to ISA bridges. 1117117337Sjhb */ 1118117337Sjhb 1119117337Sjhbdevclass_t isab_devclass; 1120117337Sjhb 1121117337Sjhbint 1122117337Sjhbisab_attach(device_t dev) 1123117337Sjhb{ 1124117337Sjhb device_t child; 1125117337Sjhb 1126117337Sjhb child = device_add_child(dev, "isa", 0); 1127117337Sjhb if (child != NULL) 1128117337Sjhb return (bus_generic_attach(dev)); 1129117337Sjhb return (ENXIO); 1130117337Sjhb} 1131