isa_common.c revision 104179
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 * 2650477Speter * $FreeBSD: head/sys/isa/isa_common.c 104179 2002-09-30 07:56:12Z phk $ 2747398Sdfr */ 2847398Sdfr/* 2947398Sdfr * Modifications for Intel architecture by Garrett A. Wollman. 3047398Sdfr * Copyright 1998 Massachusetts Institute of Technology 3147398Sdfr * 3247398Sdfr * Permission to use, copy, modify, and distribute this software and 3347398Sdfr * its documentation for any purpose and without fee is hereby 3447398Sdfr * granted, provided that both the above copyright notice and this 3547398Sdfr * permission notice appear in all copies, that both the above 3647398Sdfr * copyright notice and this permission notice appear in all 3747398Sdfr * supporting documentation, and that the name of M.I.T. not be used 3847398Sdfr * in advertising or publicity pertaining to distribution of the 3947398Sdfr * software without specific, written prior permission. M.I.T. makes 4047398Sdfr * no representations about the suitability of this software for any 4147398Sdfr * purpose. It is provided "as is" without express or implied 4247398Sdfr * warranty. 4347398Sdfr * 4447398Sdfr * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 4547398Sdfr * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 4647398Sdfr * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 4747398Sdfr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 4847398Sdfr * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4947398Sdfr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 5047398Sdfr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 5147398Sdfr * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 5247398Sdfr * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 5347398Sdfr * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 5447398Sdfr * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5547398Sdfr * SUCH DAMAGE. 5647398Sdfr */ 5747398Sdfr 5847398Sdfr/* 5947398Sdfr * Parts of the ISA bus implementation common to all architectures. 6047398Sdfr */ 6147398Sdfr 6247398Sdfr#include <sys/param.h> 6347398Sdfr#include <sys/systm.h> 6447398Sdfr#include <sys/kernel.h> 6547398Sdfr#include <sys/bus.h> 6647398Sdfr#include <sys/malloc.h> 6747398Sdfr#include <sys/module.h> 6847398Sdfr#include <machine/bus.h> 6947398Sdfr#include <sys/rman.h> 7047398Sdfr 7147398Sdfr#include <machine/resource.h> 7247398Sdfr 7347398Sdfr#include <isa/isavar.h> 7447398Sdfr#include <isa/isa_common.h> 7547398Sdfr#ifdef __alpha__ /* XXX workaround a stupid warning */ 7647398Sdfr#include <alpha/isa/isavar.h> 7747398Sdfr#endif 7847398Sdfr 7962987Sjhbstatic int isa_print_child(device_t bus, device_t dev); 8062987Sjhb 8169774Sphkstatic MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); 8247398Sdfr 8347398Sdfrstatic devclass_t isa_devclass; 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 */ 9653094Sdfr 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; 10847398Sdfr 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 11750769Sdfrisa_find_memory(device_t child, 11850769Sdfr struct isa_config *config, 11950769Sdfr struct isa_config *result) 12050769Sdfr{ 12150769Sdfr int success, i; 12250769Sdfr struct resource *res[ISA_NMEM]; 12350769Sdfr 12450769Sdfr /* 12550769Sdfr * First clear out any existing resource definitions. 12650769Sdfr */ 12750769Sdfr for (i = 0; i < ISA_NMEM; i++) { 12852174Sdfr bus_delete_resource(child, SYS_RES_MEMORY, i); 12950769Sdfr res[i] = NULL; 13050769Sdfr } 13150769Sdfr 13250769Sdfr success = 1; 13350769Sdfr result->ic_nmem = config->ic_nmem; 13450769Sdfr for (i = 0; i < config->ic_nmem; i++) { 13550769Sdfr u_int32_t start, end, size, align; 13683051Syokota 13783051Syokota size = config->ic_mem[i].ir_size; 13883051Syokota 13983051Syokota /* the PnP device may have a null resource as filler */ 14083051Syokota if (size == 0) { 14183051Syokota result->ic_mem[i].ir_start = 0; 14283051Syokota result->ic_mem[i].ir_end = 0; 14383051Syokota result->ic_mem[i].ir_size = 0; 14483051Syokota result->ic_mem[i].ir_align = 0; 14583051Syokota continue; 14683051Syokota } 14783051Syokota 14850769Sdfr for (start = config->ic_mem[i].ir_start, 14950769Sdfr end = config->ic_mem[i].ir_end, 15050769Sdfr align = config->ic_mem[i].ir_align; 15150769Sdfr start + size - 1 <= end; 15250769Sdfr start += align) { 15352174Sdfr bus_set_resource(child, SYS_RES_MEMORY, i, 15450769Sdfr start, size); 15550769Sdfr res[i] = bus_alloc_resource(child, 15650769Sdfr SYS_RES_MEMORY, &i, 15757132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */); 15850769Sdfr if (res[i]) { 15950769Sdfr result->ic_mem[i].ir_start = start; 16050769Sdfr result->ic_mem[i].ir_end = start + size - 1; 16150769Sdfr result->ic_mem[i].ir_size = size; 16250769Sdfr result->ic_mem[i].ir_align = align; 16350769Sdfr break; 16450769Sdfr } 16550769Sdfr } 16650769Sdfr 16750769Sdfr /* 16850769Sdfr * If we didn't find a place for memory range i, then 16950769Sdfr * give up now. 17050769Sdfr */ 17150769Sdfr if (!res[i]) { 17250769Sdfr success = 0; 17350769Sdfr break; 17450769Sdfr } 17550769Sdfr } 17650769Sdfr 17750769Sdfr for (i = 0; i < ISA_NMEM; i++) { 17850769Sdfr if (res[i]) 17950769Sdfr bus_release_resource(child, SYS_RES_MEMORY, 18050769Sdfr i, res[i]); 18150769Sdfr } 18250769Sdfr 18350769Sdfr return success; 18450769Sdfr} 18550769Sdfr 18650769Sdfr/* 18750769Sdfr * Find a working set of port regions for a child using the ranges 18850769Sdfr * in *config and return the regions in *result. Returns non-zero if 18950769Sdfr * a set of ranges was found. 19050769Sdfr */ 19150769Sdfrstatic int 19250769Sdfrisa_find_port(device_t child, 19350769Sdfr struct isa_config *config, 19450769Sdfr struct isa_config *result) 19550769Sdfr{ 19650769Sdfr int success, i; 19750769Sdfr struct resource *res[ISA_NPORT]; 19850769Sdfr 19950769Sdfr /* 20050769Sdfr * First clear out any existing resource definitions. 20150769Sdfr */ 20250769Sdfr for (i = 0; i < ISA_NPORT; i++) { 20352174Sdfr bus_delete_resource(child, SYS_RES_IOPORT, i); 20450769Sdfr res[i] = NULL; 20550769Sdfr } 20650769Sdfr 20750769Sdfr success = 1; 20850769Sdfr result->ic_nport = config->ic_nport; 20950769Sdfr for (i = 0; i < config->ic_nport; i++) { 21050769Sdfr u_int32_t start, end, size, align; 21183051Syokota 21283051Syokota size = config->ic_port[i].ir_size; 21383051Syokota 21483051Syokota /* the PnP device may have a null resource as filler */ 21583051Syokota if (size == 0) { 21683051Syokota result->ic_port[i].ir_start = 0; 21783051Syokota result->ic_port[i].ir_end = 0; 21883051Syokota result->ic_port[i].ir_size = 0; 21983051Syokota result->ic_port[i].ir_align = 0; 22083051Syokota continue; 22183051Syokota } 22283051Syokota 22350769Sdfr for (start = config->ic_port[i].ir_start, 22450769Sdfr end = config->ic_port[i].ir_end, 22550769Sdfr align = config->ic_port[i].ir_align; 22650769Sdfr start + size - 1 <= end; 22750769Sdfr start += align) { 22852174Sdfr bus_set_resource(child, SYS_RES_IOPORT, i, 22950769Sdfr start, size); 23050769Sdfr res[i] = bus_alloc_resource(child, 23150769Sdfr SYS_RES_IOPORT, &i, 23257132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */); 23350769Sdfr if (res[i]) { 23450769Sdfr result->ic_port[i].ir_start = start; 23550769Sdfr result->ic_port[i].ir_end = start + size - 1; 23650769Sdfr result->ic_port[i].ir_size = size; 23750769Sdfr result->ic_port[i].ir_align = align; 23850769Sdfr break; 23950769Sdfr } 24050769Sdfr } 24150769Sdfr 24250769Sdfr /* 24350769Sdfr * If we didn't find a place for port range i, then 24450769Sdfr * give up now. 24550769Sdfr */ 24650769Sdfr if (!res[i]) { 24750769Sdfr success = 0; 24850769Sdfr break; 24950769Sdfr } 25050769Sdfr } 25150769Sdfr 25250769Sdfr for (i = 0; i < ISA_NPORT; i++) { 25350769Sdfr if (res[i]) 25450769Sdfr bus_release_resource(child, SYS_RES_IOPORT, 25550769Sdfr i, res[i]); 25650769Sdfr } 25750769Sdfr 25850769Sdfr return success; 25950769Sdfr} 26050769Sdfr 26150769Sdfr/* 26250769Sdfr * Return the index of the first bit in the mask (or -1 if mask is empty. 26350769Sdfr */ 26450769Sdfrstatic int 26550769Sdfrfind_first_bit(u_int32_t mask) 26650769Sdfr{ 26750769Sdfr return ffs(mask) - 1; 26850769Sdfr} 26950769Sdfr 27050769Sdfr/* 27150769Sdfr * Return the index of the next bit in the mask, or -1 if there are no more. 27250769Sdfr */ 27350769Sdfrstatic int 27450769Sdfrfind_next_bit(u_int32_t mask, int bit) 27550769Sdfr{ 27650769Sdfr bit++; 27750769Sdfr while (bit < 32 && !(mask & (1 << bit))) 27850769Sdfr bit++; 27950769Sdfr if (bit != 32) 28050769Sdfr return bit; 28150769Sdfr return -1; 28250769Sdfr} 28350769Sdfr 28450769Sdfr/* 28550769Sdfr * Find a working set of irqs for a child using the masks in *config 28650769Sdfr * and return the regions in *result. Returns non-zero if a set of 28750769Sdfr * irqs was found. 28850769Sdfr */ 28950769Sdfrstatic int 29050769Sdfrisa_find_irq(device_t child, 29150769Sdfr struct isa_config *config, 29250769Sdfr struct isa_config *result) 29350769Sdfr{ 29450769Sdfr int success, i; 29550769Sdfr struct resource *res[ISA_NIRQ]; 29650769Sdfr 29750769Sdfr /* 29850769Sdfr * First clear out any existing resource definitions. 29950769Sdfr */ 30050769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 30152174Sdfr bus_delete_resource(child, SYS_RES_IRQ, i); 30250769Sdfr res[i] = NULL; 30350769Sdfr } 30450769Sdfr 30550769Sdfr success = 1; 30650769Sdfr result->ic_nirq = config->ic_nirq; 30750769Sdfr for (i = 0; i < config->ic_nirq; i++) { 30850769Sdfr u_int32_t mask = config->ic_irqmask[i]; 30950769Sdfr int irq; 31083051Syokota 31183051Syokota /* the PnP device may have a null resource as filler */ 31283051Syokota if (mask == 0) { 31383051Syokota result->ic_irqmask[i] = 0; 31483051Syokota continue; 31583051Syokota } 31683051Syokota 31750769Sdfr for (irq = find_first_bit(mask); 31850769Sdfr irq != -1; 31950769Sdfr irq = find_next_bit(mask, irq)) { 32052174Sdfr bus_set_resource(child, SYS_RES_IRQ, i, 32150769Sdfr irq, 1); 32250769Sdfr res[i] = bus_alloc_resource(child, 32350769Sdfr SYS_RES_IRQ, &i, 32457132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */ ); 32550769Sdfr if (res[i]) { 32650769Sdfr result->ic_irqmask[i] = (1 << irq); 32750769Sdfr break; 32850769Sdfr } 32950769Sdfr } 33050769Sdfr 33150769Sdfr /* 33250769Sdfr * If we didn't find a place for irq range i, then 33350769Sdfr * give up now. 33450769Sdfr */ 33550769Sdfr if (!res[i]) { 33650769Sdfr success = 0; 33750769Sdfr break; 33850769Sdfr } 33950769Sdfr } 34050769Sdfr 34150769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 34250769Sdfr if (res[i]) 34350769Sdfr bus_release_resource(child, SYS_RES_IRQ, 34450769Sdfr i, res[i]); 34550769Sdfr } 34650769Sdfr 34750769Sdfr return success; 34850769Sdfr} 34950769Sdfr 35050769Sdfr/* 35150769Sdfr * Find a working set of drqs for a child using the masks in *config 35250769Sdfr * and return the regions in *result. Returns non-zero if a set of 35350769Sdfr * drqs was found. 35450769Sdfr */ 35550769Sdfrstatic int 35650769Sdfrisa_find_drq(device_t child, 35750769Sdfr struct isa_config *config, 35850769Sdfr struct isa_config *result) 35950769Sdfr{ 36050769Sdfr int success, i; 36150769Sdfr struct resource *res[ISA_NDRQ]; 36250769Sdfr 36350769Sdfr /* 36450769Sdfr * First clear out any existing resource definitions. 36550769Sdfr */ 36650769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 36752174Sdfr bus_delete_resource(child, SYS_RES_DRQ, i); 36850769Sdfr res[i] = NULL; 36950769Sdfr } 37050769Sdfr 37150769Sdfr success = 1; 37250769Sdfr result->ic_ndrq = config->ic_ndrq; 37350769Sdfr for (i = 0; i < config->ic_ndrq; i++) { 37450769Sdfr u_int32_t mask = config->ic_drqmask[i]; 37550769Sdfr int drq; 37683051Syokota 37783051Syokota /* the PnP device may have a null resource as filler */ 37883051Syokota if (mask == 0) { 37983051Syokota result->ic_drqmask[i] = 0; 38083051Syokota continue; 38183051Syokota } 38283051Syokota 38350769Sdfr for (drq = find_first_bit(mask); 38450769Sdfr drq != -1; 38550769Sdfr drq = find_next_bit(mask, drq)) { 38652174Sdfr bus_set_resource(child, SYS_RES_DRQ, i, 38750769Sdfr drq, 1); 38850769Sdfr res[i] = bus_alloc_resource(child, 38950769Sdfr SYS_RES_DRQ, &i, 39057132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */); 39150769Sdfr if (res[i]) { 39250769Sdfr result->ic_drqmask[i] = (1 << drq); 39350769Sdfr break; 39450769Sdfr } 39550769Sdfr } 39650769Sdfr 39750769Sdfr /* 39850769Sdfr * If we didn't find a place for drq range i, then 39950769Sdfr * give up now. 40050769Sdfr */ 40150769Sdfr if (!res[i]) { 40250769Sdfr success = 0; 40350769Sdfr break; 40450769Sdfr } 40550769Sdfr } 40650769Sdfr 40750769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 40850769Sdfr if (res[i]) 40950769Sdfr bus_release_resource(child, SYS_RES_DRQ, 41050769Sdfr i, res[i]); 41150769Sdfr } 41250769Sdfr 41350769Sdfr return success; 41450769Sdfr} 41550769Sdfr 41650769Sdfr/* 41750769Sdfr * Attempt to find a working set of resources for a device. Return 41850769Sdfr * non-zero if a working configuration is found. 41950769Sdfr */ 42050769Sdfrstatic int 42150769Sdfrisa_assign_resources(device_t child) 42250769Sdfr{ 42350769Sdfr struct isa_device *idev = DEVTOISA(child); 42450769Sdfr struct isa_config_entry *ice; 42581401Sjulian struct isa_config *cfg; 42691206Salfred const char *reason; 42791206Salfred 42891206Salfred reason = "Empty ISA id_configs"; 42981401Sjulian cfg = malloc(sizeof(struct isa_config), M_TEMP, M_NOWAIT|M_ZERO); 43081401Sjulian if (cfg == NULL) 43181401Sjulian return(0); 43250769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 43391202Salfred reason = "memory"; 43481401Sjulian if (!isa_find_memory(child, &ice->ice_config, cfg)) 43550769Sdfr continue; 43691202Salfred reason = "port"; 43781401Sjulian if (!isa_find_port(child, &ice->ice_config, cfg)) 43850769Sdfr continue; 43991202Salfred reason = "irq"; 44081401Sjulian if (!isa_find_irq(child, &ice->ice_config, cfg)) 44150769Sdfr continue; 44291202Salfred reason = "drq"; 44381401Sjulian if (!isa_find_drq(child, &ice->ice_config, cfg)) 44450769Sdfr continue; 44550769Sdfr 44650769Sdfr /* 44750769Sdfr * A working configuration was found enable the device 44850769Sdfr * with this configuration. 44950769Sdfr */ 45091202Salfred reason = "no callback"; 45150769Sdfr if (idev->id_config_cb) { 45250769Sdfr idev->id_config_cb(idev->id_config_arg, 45381401Sjulian cfg, 1); 45481401Sjulian free(cfg, M_TEMP); 45550769Sdfr return 1; 45650769Sdfr } 45750769Sdfr } 45850769Sdfr 45950769Sdfr /* 46050769Sdfr * Disable the device. 46150769Sdfr */ 46262987Sjhb bus_print_child_header(device_get_parent(child), child); 46391202Salfred printf(" can't assign resources (%s)\n", reason); 46462987Sjhb if (bootverbose) 46562987Sjhb isa_print_child(device_get_parent(child), child); 46681401Sjulian bzero(cfg, sizeof (*cfg)); 46750769Sdfr if (idev->id_config_cb) 46881401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 46950769Sdfr device_disable(child); 47050769Sdfr 47181401Sjulian free(cfg, M_TEMP); 47250769Sdfr return 0; 47350769Sdfr} 47450769Sdfr 47550769Sdfr/* 47683051Syokota * Return non-zero if the device has a single configuration, that is, 47783051Syokota * a fixed set of resoruces. 47883051Syokota */ 47983051Syokotastatic int 48083051Syokotaisa_has_single_config(device_t dev) 48183051Syokota{ 48283051Syokota struct isa_device *idev = DEVTOISA(dev); 48383051Syokota struct isa_config_entry *ice; 48483051Syokota u_int32_t mask; 48583051Syokota int i; 48683051Syokota 48783051Syokota ice = TAILQ_FIRST(&idev->id_configs); 48883051Syokota if (TAILQ_NEXT(ice, ice_link)) 48983051Syokota return 0; 49083051Syokota 49183051Syokota for (i = 0; i < ice->ice_config.ic_nmem; ++i) { 49283051Syokota if (ice->ice_config.ic_mem[i].ir_size == 0) 49383051Syokota continue; 49483051Syokota if (ice->ice_config.ic_mem[i].ir_end != 49583051Syokota ice->ice_config.ic_mem[i].ir_start + 49683051Syokota ice->ice_config.ic_mem[i].ir_size - 1) 49783051Syokota return 0; 49883051Syokota } 49983051Syokota for (i = 0; i < ice->ice_config.ic_nport; ++i) { 50083051Syokota if (ice->ice_config.ic_port[i].ir_size == 0) 50183051Syokota continue; 50283051Syokota if (ice->ice_config.ic_port[i].ir_end != 50383051Syokota ice->ice_config.ic_port[i].ir_start + 50483051Syokota ice->ice_config.ic_port[i].ir_size - 1) 50583051Syokota return 0; 50683051Syokota } 50783051Syokota for (i = 0; i < ice->ice_config.ic_nirq; ++i) { 50883051Syokota mask = ice->ice_config.ic_irqmask[i]; 50983051Syokota if (mask == 0) 51083051Syokota continue; 51183051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 51283051Syokota return 0; 51383051Syokota } 51483051Syokota for (i = 0; i < ice->ice_config.ic_ndrq; ++i) { 51583051Syokota mask = ice->ice_config.ic_drqmask[i]; 51683051Syokota if (mask == 0) 51783051Syokota continue; 51883051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 51983051Syokota return 0; 52083051Syokota } 52183051Syokota return 1; 52283051Syokota} 52383051Syokota 52483051Syokota/* 52550769Sdfr * Called after other devices have initialised to probe for isa devices. 52650769Sdfr */ 52750769Sdfrvoid 52850769Sdfrisa_probe_children(device_t dev) 52950769Sdfr{ 53050769Sdfr device_t *children; 53181401Sjulian struct isa_config *cfg; 53250769Sdfr int nchildren, i; 53350769Sdfr 53453094Sdfr /* 53553094Sdfr * Create all the children by calling driver's identify methods. 53653094Sdfr */ 53753094Sdfr bus_generic_probe(dev); 53853094Sdfr 53950769Sdfr if (device_get_children(dev, &children, &nchildren)) 54050769Sdfr return; 54150769Sdfr 54250769Sdfr /* 54351905Sdfr * First disable all pnp devices so that they don't get 54451905Sdfr * matched by legacy probes. 54551905Sdfr */ 54653094Sdfr if (bootverbose) 54753094Sdfr printf("isa_probe_children: disabling PnP devices\n"); 54881401Sjulian 54981401Sjulian cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 55081401Sjulian if (cfg == NULL) { 55181401Sjulian free(children, M_TEMP); 55281401Sjulian return; 55381401Sjulian } 55481401Sjulian 55551905Sdfr for (i = 0; i < nchildren; i++) { 55651905Sdfr device_t child = children[i]; 55751905Sdfr struct isa_device *idev = DEVTOISA(child); 55851905Sdfr 55981401Sjulian bzero(cfg, sizeof(*cfg)); 56051905Sdfr if (idev->id_config_cb) 56181401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 56251905Sdfr } 56351905Sdfr 56481401Sjulian free(cfg, M_TEMP); 56581401Sjulian 56651905Sdfr /* 56751905Sdfr * Next probe all non-pnp devices so that they claim their 56850769Sdfr * resources first. 56950769Sdfr */ 57053094Sdfr if (bootverbose) 57153094Sdfr printf("isa_probe_children: probing non-PnP devices\n"); 57250769Sdfr for (i = 0; i < nchildren; i++) { 57350769Sdfr device_t child = children[i]; 57450769Sdfr struct isa_device *idev = DEVTOISA(child); 57550769Sdfr 57650769Sdfr if (TAILQ_FIRST(&idev->id_configs)) 57750769Sdfr continue; 57850769Sdfr 57950769Sdfr device_probe_and_attach(child); 58050769Sdfr } 58150769Sdfr 58250769Sdfr /* 58351905Sdfr * Finally assign resource to pnp devices and probe them. 58450769Sdfr */ 58553094Sdfr if (bootverbose) 58653094Sdfr printf("isa_probe_children: probing PnP devices\n"); 58750769Sdfr for (i = 0; i < nchildren; i++) { 58850769Sdfr device_t child = children[i]; 58950769Sdfr struct isa_device* idev = DEVTOISA(child); 59050769Sdfr 59150769Sdfr if (!TAILQ_FIRST(&idev->id_configs)) 59250769Sdfr continue; 59350769Sdfr 59450769Sdfr if (isa_assign_resources(child)) { 59552174Sdfr struct resource_list *rl = &idev->id_resources; 59650769Sdfr struct resource_list_entry *rle; 59750769Sdfr 59850769Sdfr device_probe_and_attach(child); 59950769Sdfr 60050769Sdfr /* 60150769Sdfr * Claim any unallocated resources to keep other 60250769Sdfr * devices from using them. 60350769Sdfr */ 60452174Sdfr SLIST_FOREACH(rle, rl, link) { 60550769Sdfr if (!rle->res) { 60650769Sdfr int rid = rle->rid; 60752174Sdfr resource_list_alloc(rl, dev, child, 60850769Sdfr rle->type, 60950769Sdfr &rid, 61062059Sdfr 0, ~0, 1, 0); 61150769Sdfr } 61250769Sdfr } 61350769Sdfr } 61450769Sdfr } 61550769Sdfr 61650769Sdfr free(children, M_TEMP); 61753094Sdfr 61853094Sdfr isa_running = 1; 61950769Sdfr} 62050769Sdfr 62150769Sdfr/* 62247398Sdfr * Add a new child with default ivars. 62347398Sdfr */ 62447398Sdfrstatic device_t 62547578Sdfrisa_add_child(device_t dev, int order, const char *name, int unit) 62647398Sdfr{ 62754073Smdodd device_t child; 62847398Sdfr struct isa_device *idev; 62947398Sdfr 630104179Sphk child = device_add_child_ordered(dev, order, name, unit); 631104179Sphk if (child == NULL) 632104179Sphk return (child); 633104179Sphk 63469781Sdwmalone idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 63547398Sdfr if (!idev) 63647398Sdfr return 0; 63747398Sdfr 63847398Sdfr resource_list_init(&idev->id_resources); 63950769Sdfr TAILQ_INIT(&idev->id_configs); 64047398Sdfr 641104179Sphk device_set_ivars(child, idev); 64254073Smdodd 643104179Sphk return (child); 64447398Sdfr} 64547398Sdfr 64662059Sdfrstatic int 64762059Sdfrisa_print_all_resources(device_t dev) 64847398Sdfr{ 64947398Sdfr struct isa_device *idev = DEVTOISA(dev); 65047398Sdfr struct resource_list *rl = &idev->id_resources; 65149195Smdodd int retval = 0; 65247398Sdfr 65351052Sdfr if (SLIST_FIRST(rl) || device_get_flags(dev)) 65449195Smdodd retval += printf(" at"); 65547398Sdfr 65688376Stmm retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 65788376Stmm retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 65888376Stmm retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 65988376Stmm retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld"); 66051052Sdfr if (device_get_flags(dev)) 66151052Sdfr retval += printf(" flags %#x", device_get_flags(dev)); 66247398Sdfr 66362059Sdfr return retval; 66462059Sdfr} 66562059Sdfr 66662059Sdfrstatic int 66762059Sdfrisa_print_child(device_t bus, device_t dev) 66862059Sdfr{ 66962059Sdfr int retval = 0; 67062059Sdfr 67162059Sdfr retval += bus_print_child_header(bus, dev); 67262059Sdfr retval += isa_print_all_resources(dev); 67349195Smdodd retval += bus_print_child_footer(bus, dev); 67449195Smdodd 67549195Smdodd return (retval); 67647398Sdfr} 67747398Sdfr 67862059Sdfrstatic void 67962059Sdfrisa_probe_nomatch(device_t dev, device_t child) 68062059Sdfr{ 68162987Sjhb if (bootverbose) { 68262987Sjhb bus_print_child_header(dev, child); 68362987Sjhb printf(" failed to probe"); 68462059Sdfr isa_print_all_resources(child); 68562987Sjhb bus_print_child_footer(dev, child); 68662987Sjhb } 68762059Sdfr 68862059Sdfr return; 68962059Sdfr} 69062059Sdfr 69147398Sdfrstatic int 69247398Sdfrisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 69347398Sdfr{ 69447398Sdfr struct isa_device* idev = DEVTOISA(dev); 69547398Sdfr struct resource_list *rl = &idev->id_resources; 69647398Sdfr struct resource_list_entry *rle; 69747398Sdfr 69847398Sdfr switch (index) { 69947398Sdfr case ISA_IVAR_PORT_0: 70047398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 70147398Sdfr if (rle) 70247398Sdfr *result = rle->start; 70347398Sdfr else 70447398Sdfr *result = -1; 70547398Sdfr break; 70647398Sdfr 70747398Sdfr case ISA_IVAR_PORT_1: 70847398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 70947398Sdfr if (rle) 71047398Sdfr *result = rle->start; 71147398Sdfr else 71247398Sdfr *result = -1; 71347398Sdfr break; 71447398Sdfr 71547398Sdfr case ISA_IVAR_PORTSIZE_0: 71647398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 71747398Sdfr if (rle) 71847398Sdfr *result = rle->count; 71947398Sdfr else 72047398Sdfr *result = 0; 72147398Sdfr break; 72247398Sdfr 72347398Sdfr case ISA_IVAR_PORTSIZE_1: 72447398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 72547398Sdfr if (rle) 72647398Sdfr *result = rle->count; 72747398Sdfr else 72847398Sdfr *result = 0; 72947398Sdfr break; 73047398Sdfr 73147398Sdfr case ISA_IVAR_MADDR_0: 73247398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 73347398Sdfr if (rle) 73447398Sdfr *result = rle->start; 73547398Sdfr else 73647398Sdfr *result = -1; 73747398Sdfr break; 73847398Sdfr 73947398Sdfr case ISA_IVAR_MADDR_1: 74047398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 74147398Sdfr if (rle) 74247398Sdfr *result = rle->start; 74347398Sdfr else 74447398Sdfr *result = -1; 74547398Sdfr break; 74647398Sdfr 74747398Sdfr case ISA_IVAR_MSIZE_0: 74847398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 74947398Sdfr if (rle) 75047398Sdfr *result = rle->count; 75147398Sdfr else 75247398Sdfr *result = 0; 75347398Sdfr break; 75447398Sdfr 75547398Sdfr case ISA_IVAR_MSIZE_1: 75647398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 75747398Sdfr if (rle) 75847398Sdfr *result = rle->count; 75947398Sdfr else 76047398Sdfr *result = 0; 76147398Sdfr break; 76247398Sdfr 76347398Sdfr case ISA_IVAR_IRQ_0: 76447398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 0); 76547398Sdfr if (rle) 76647398Sdfr *result = rle->start; 76747398Sdfr else 76847398Sdfr *result = -1; 76947398Sdfr break; 77047398Sdfr 77147398Sdfr case ISA_IVAR_IRQ_1: 77247398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 1); 77347398Sdfr if (rle) 77447398Sdfr *result = rle->start; 77547398Sdfr else 77647398Sdfr *result = -1; 77747398Sdfr break; 77847398Sdfr 77947398Sdfr case ISA_IVAR_DRQ_0: 78047398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 0); 78147398Sdfr if (rle) 78247398Sdfr *result = rle->start; 78347398Sdfr else 78447398Sdfr *result = -1; 78547398Sdfr break; 78647398Sdfr 78747398Sdfr case ISA_IVAR_DRQ_1: 78847398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 1); 78947398Sdfr if (rle) 79047398Sdfr *result = rle->start; 79147398Sdfr else 79247398Sdfr *result = -1; 79347398Sdfr break; 79447398Sdfr 79547613Sdfr case ISA_IVAR_VENDORID: 79647613Sdfr *result = idev->id_vendorid; 79747613Sdfr break; 79847613Sdfr 79947613Sdfr case ISA_IVAR_SERIAL: 80047613Sdfr *result = idev->id_serial; 80147613Sdfr break; 80247613Sdfr 80347613Sdfr case ISA_IVAR_LOGICALID: 80447613Sdfr *result = idev->id_logicalid; 80547613Sdfr break; 80647613Sdfr 80747613Sdfr case ISA_IVAR_COMPATID: 80847613Sdfr *result = idev->id_compatid; 80947613Sdfr break; 81047613Sdfr 81182863Syokota case ISA_IVAR_CONFIGATTR: 81282863Syokota *result = idev->id_config_attr; 81382863Syokota break; 81482863Syokota 81547613Sdfr default: 81647613Sdfr return ENOENT; 81747398Sdfr } 81847613Sdfr 81947613Sdfr return 0; 82047398Sdfr} 82147398Sdfr 82247398Sdfrstatic int 82347398Sdfrisa_write_ivar(device_t bus, device_t dev, 82447398Sdfr int index, uintptr_t value) 82547398Sdfr{ 82647398Sdfr struct isa_device* idev = DEVTOISA(dev); 82747398Sdfr 82847398Sdfr switch (index) { 82947398Sdfr case ISA_IVAR_PORT_0: 83047398Sdfr case ISA_IVAR_PORT_1: 83147398Sdfr case ISA_IVAR_PORTSIZE_0: 83247398Sdfr case ISA_IVAR_PORTSIZE_1: 83347398Sdfr case ISA_IVAR_MADDR_0: 83447398Sdfr case ISA_IVAR_MADDR_1: 83547398Sdfr case ISA_IVAR_MSIZE_0: 83647398Sdfr case ISA_IVAR_MSIZE_1: 83747398Sdfr case ISA_IVAR_IRQ_0: 83847398Sdfr case ISA_IVAR_IRQ_1: 83947398Sdfr case ISA_IVAR_DRQ_0: 84047398Sdfr case ISA_IVAR_DRQ_1: 84147398Sdfr return EINVAL; 84247398Sdfr 84347613Sdfr case ISA_IVAR_VENDORID: 84447613Sdfr idev->id_vendorid = value; 84547613Sdfr break; 84647613Sdfr 84747613Sdfr case ISA_IVAR_SERIAL: 84847613Sdfr idev->id_serial = value; 84947613Sdfr break; 85047613Sdfr 85147613Sdfr case ISA_IVAR_LOGICALID: 85247613Sdfr idev->id_logicalid = value; 85347613Sdfr break; 85447613Sdfr 85547613Sdfr case ISA_IVAR_COMPATID: 85647613Sdfr idev->id_compatid = value; 85747613Sdfr break; 85847613Sdfr 85982863Syokota case ISA_IVAR_CONFIGATTR: 86082863Syokota idev->id_config_attr = value; 86182863Syokota break; 86282863Syokota 86347398Sdfr default: 86447398Sdfr return (ENOENT); 86547398Sdfr } 86647613Sdfr 86747398Sdfr return (0); 86847398Sdfr} 86947398Sdfr 87050769Sdfr/* 87150769Sdfr * Free any resources which the driver missed or which we were holding for 87250769Sdfr * it (see isa_probe_children). 87350769Sdfr */ 87450769Sdfrstatic void 87550769Sdfrisa_child_detached(device_t dev, device_t child) 87650769Sdfr{ 87750769Sdfr struct isa_device* idev = DEVTOISA(child); 87852174Sdfr struct resource_list *rl = &idev->id_resources; 87950769Sdfr struct resource_list_entry *rle; 88050769Sdfr 88162059Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 88262059Sdfr /* 88362059Sdfr * Claim any unallocated resources to keep other 88462059Sdfr * devices from using them. 88562059Sdfr */ 88662059Sdfr SLIST_FOREACH(rle, rl, link) { 88762059Sdfr if (!rle->res) { 88862059Sdfr int rid = rle->rid; 88962059Sdfr resource_list_alloc(rl, dev, child, 89062059Sdfr rle->type, 89162059Sdfr &rid, 0, ~0, 1, 0); 89262059Sdfr } 89362059Sdfr } 89450769Sdfr } 89550769Sdfr} 89650769Sdfr 89753094Sdfrstatic void 89853094Sdfrisa_driver_added(device_t dev, driver_t *driver) 89953094Sdfr{ 90053094Sdfr device_t *children; 90153094Sdfr int nchildren, i; 90253094Sdfr 90353094Sdfr /* 90453094Sdfr * Don't do anything if drivers are dynamically 90553094Sdfr * added during autoconfiguration (cf. ymf724). 90653094Sdfr * since that would end up calling identify 90753094Sdfr * twice. 90853094Sdfr */ 90953094Sdfr if (!isa_running) 91053094Sdfr return; 91153094Sdfr 91253094Sdfr DEVICE_IDENTIFY(driver, dev); 91353094Sdfr if (device_get_children(dev, &children, &nchildren)) 91453094Sdfr return; 91553094Sdfr 91653094Sdfr for (i = 0; i < nchildren; i++) { 91753094Sdfr device_t child = children[i]; 91853094Sdfr struct isa_device *idev = DEVTOISA(child); 91953094Sdfr struct resource_list *rl = &idev->id_resources; 92053094Sdfr struct resource_list_entry *rle; 92153094Sdfr 92253094Sdfr if (device_get_state(child) != DS_NOTPRESENT) 92353094Sdfr continue; 92462059Sdfr if (!device_is_enabled(child)) 92562059Sdfr continue; 92653094Sdfr 92762059Sdfr /* 92862059Sdfr * Free resources which we were holding on behalf of 92962059Sdfr * the device. 93062059Sdfr */ 93162059Sdfr SLIST_FOREACH(rle, &idev->id_resources, link) { 93262059Sdfr if (rle->res) 93362059Sdfr resource_list_release(rl, dev, child, 93462059Sdfr rle->type, 93562059Sdfr rle->rid, 93662059Sdfr rle->res); 93762059Sdfr } 93862059Sdfr 93953094Sdfr if (TAILQ_FIRST(&idev->id_configs)) 94053094Sdfr if (!isa_assign_resources(child)) 94153094Sdfr continue; 94253094Sdfr 94353094Sdfr device_probe_and_attach(child); 94453094Sdfr 94553094Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 94653094Sdfr /* 94753094Sdfr * Claim any unallocated resources to keep other 94853094Sdfr * devices from using them. 94953094Sdfr */ 95053094Sdfr SLIST_FOREACH(rle, rl, link) { 95153094Sdfr if (!rle->res) { 95253094Sdfr int rid = rle->rid; 95353094Sdfr resource_list_alloc(rl, dev, child, 95453094Sdfr rle->type, 95562059Sdfr &rid, 0, ~0, 1, 0); 95653094Sdfr } 95753094Sdfr } 95853094Sdfr } 95953094Sdfr } 96053094Sdfr 96153094Sdfr free(children, M_TEMP); 96253094Sdfr} 96353094Sdfr 96447398Sdfrstatic int 96547398Sdfrisa_set_resource(device_t dev, device_t child, int type, int rid, 96647398Sdfr u_long start, u_long count) 96747398Sdfr{ 96847398Sdfr struct isa_device* idev = DEVTOISA(child); 96947398Sdfr struct resource_list *rl = &idev->id_resources; 97047398Sdfr 97147398Sdfr if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 97247398Sdfr && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 97347398Sdfr return EINVAL; 97450769Sdfr if (rid < 0) 97547398Sdfr return EINVAL; 97650769Sdfr if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 97750769Sdfr return EINVAL; 97850769Sdfr if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 97950769Sdfr return EINVAL; 98050769Sdfr if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 98150769Sdfr return EINVAL; 98250769Sdfr if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 98350769Sdfr return EINVAL; 98447398Sdfr 98547398Sdfr resource_list_add(rl, type, rid, start, start + count - 1, count); 98647398Sdfr 98747398Sdfr return 0; 98847398Sdfr} 98947398Sdfr 99069295Smdoddstatic struct resource_list * 99169295Smdoddisa_get_resource_list (device_t dev, device_t child) 99247398Sdfr{ 99347398Sdfr struct isa_device* idev = DEVTOISA(child); 99447398Sdfr struct resource_list *rl = &idev->id_resources; 99547398Sdfr 99669295Smdodd if (!rl) 99769295Smdodd return (NULL); 99847398Sdfr 99969295Smdodd return (rl); 100047398Sdfr} 100147398Sdfr 100250769Sdfrstatic int 100350769Sdfrisa_add_config(device_t dev, device_t child, 100450769Sdfr int priority, struct isa_config *config) 100550769Sdfr{ 100650769Sdfr struct isa_device* idev = DEVTOISA(child); 100750769Sdfr struct isa_config_entry *newice, *ice; 100850769Sdfr 100950769Sdfr newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 101050769Sdfr if (!newice) 101150769Sdfr return ENOMEM; 101250769Sdfr 101350769Sdfr newice->ice_priority = priority; 101450769Sdfr newice->ice_config = *config; 101550769Sdfr 101650769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 101750769Sdfr if (ice->ice_priority > priority) 101850769Sdfr break; 101950769Sdfr } 102050769Sdfr if (ice) 102150769Sdfr TAILQ_INSERT_BEFORE(ice, newice, ice_link); 102250769Sdfr else 102350769Sdfr TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 102450769Sdfr 102583051Syokota if (isa_has_single_config(child)) 102683051Syokota idev->id_config_attr &= ~ISACFGATTR_MULTI; 102783051Syokota else 102883051Syokota idev->id_config_attr |= ISACFGATTR_MULTI; 102983051Syokota 103050769Sdfr return 0; 103150769Sdfr} 103250769Sdfr 103350769Sdfrstatic void 103450769Sdfrisa_set_config_callback(device_t dev, device_t child, 103550769Sdfr isa_config_cb *fn, void *arg) 103650769Sdfr{ 103750769Sdfr struct isa_device* idev = DEVTOISA(child); 103850769Sdfr 103950769Sdfr idev->id_config_cb = fn; 104050769Sdfr idev->id_config_arg = arg; 104150769Sdfr} 104250769Sdfr 104350769Sdfrstatic int 104450769Sdfrisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 104550769Sdfr{ 104650769Sdfr struct isa_device* idev = DEVTOISA(child); 104750769Sdfr 104850769Sdfr if (!idev->id_vendorid) 104950769Sdfr return ENOENT; 105050769Sdfr 105182553Smsmith while (ids && ids->ip_id) { 105250769Sdfr /* 105350769Sdfr * Really ought to support >1 compat id per device. 105450769Sdfr */ 105550769Sdfr if (idev->id_logicalid == ids->ip_id 105650769Sdfr || idev->id_compatid == ids->ip_id) { 105750910Sdfr if (ids->ip_desc) 105850910Sdfr device_set_desc(child, ids->ip_desc); 105950769Sdfr return 0; 106050769Sdfr } 106150769Sdfr ids++; 106250769Sdfr } 106350769Sdfr 106450769Sdfr return ENXIO; 106550769Sdfr} 106650769Sdfr 106747398Sdfrstatic device_method_t isa_methods[] = { 106847398Sdfr /* Device interface */ 106947398Sdfr DEVMETHOD(device_probe, isa_probe), 107047398Sdfr DEVMETHOD(device_attach, isa_attach), 107147398Sdfr DEVMETHOD(device_detach, bus_generic_detach), 107247398Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 107347398Sdfr DEVMETHOD(device_suspend, bus_generic_suspend), 107447398Sdfr DEVMETHOD(device_resume, bus_generic_resume), 107547398Sdfr 107647398Sdfr /* Bus interface */ 107747398Sdfr DEVMETHOD(bus_add_child, isa_add_child), 107847398Sdfr DEVMETHOD(bus_print_child, isa_print_child), 107962059Sdfr DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 108047398Sdfr DEVMETHOD(bus_read_ivar, isa_read_ivar), 108147398Sdfr DEVMETHOD(bus_write_ivar, isa_write_ivar), 108250769Sdfr DEVMETHOD(bus_child_detached, isa_child_detached), 108353094Sdfr DEVMETHOD(bus_driver_added, isa_driver_added), 108469295Smdodd DEVMETHOD(bus_setup_intr, isa_setup_intr), 108569295Smdodd DEVMETHOD(bus_teardown_intr, isa_teardown_intr), 108669295Smdodd 108769295Smdodd DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 108847398Sdfr DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 108947398Sdfr DEVMETHOD(bus_release_resource, isa_release_resource), 109069295Smdodd DEVMETHOD(bus_set_resource, isa_set_resource), 109169295Smdodd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 109269295Smdodd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 109347398Sdfr DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 109447398Sdfr DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 109547398Sdfr 109647398Sdfr /* ISA interface */ 109750769Sdfr DEVMETHOD(isa_add_config, isa_add_config), 109850769Sdfr DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 109950769Sdfr DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 110047398Sdfr 110147398Sdfr { 0, 0 } 110247398Sdfr}; 110347398Sdfr 110447398Sdfrstatic driver_t isa_driver = { 110547398Sdfr "isa", 110647398Sdfr isa_methods, 110747398Sdfr 1, /* no softc */ 110847398Sdfr}; 110947398Sdfr 111047398Sdfr/* 1111104015Sjhb * ISA can be attached to a PCI-ISA bridge or directly to the legacy device. 111247398Sdfr */ 111347398SdfrDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 111469942SmsmithDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 111547398Sdfr#ifdef __i386__ 1116104015SjhbDRIVER_MODULE(isa, legacy, isa_driver, isa_devclass, 0, 0); 111747398Sdfr#endif 1118