isa_common.c revision 116181
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 116181 2003-06-11 00:34:37Z obrien $"); 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 8447398Sdfrstatic devclass_t isa_devclass; 8553094Sdfrstatic int isa_running; 8647398Sdfr 8747398Sdfr/* 8847398Sdfr * At 'probe' time, we add all the devices which we know about to the 8947398Sdfr * bus. The generic attach routine will probe and attach them if they 9047398Sdfr * are alive. 9147398Sdfr */ 9247398Sdfrstatic int 9347398Sdfrisa_probe(device_t dev) 9447398Sdfr{ 9547398Sdfr device_set_desc(dev, "ISA bus"); 9688376Stmm isa_init(dev); /* Allow machdep code to initialise */ 9753094Sdfr return 0; 9847398Sdfr} 9947398Sdfr 10047398Sdfrextern device_t isa_bus_device; 10147398Sdfr 10247398Sdfrstatic int 10347398Sdfrisa_attach(device_t dev) 10447398Sdfr{ 10547398Sdfr /* 10650769Sdfr * Arrange for isa_probe_children(dev) to be called later. XXX 10747398Sdfr */ 10847398Sdfr isa_bus_device = dev; 10947398Sdfr return 0; 11047398Sdfr} 11147398Sdfr 11247398Sdfr/* 11350769Sdfr * Find a working set of memory regions for a child using the ranges 11450769Sdfr * in *config and return the regions in *result. Returns non-zero if 11550769Sdfr * a set of ranges was found. 11650769Sdfr */ 11750769Sdfrstatic int 11850769Sdfrisa_find_memory(device_t child, 11950769Sdfr struct isa_config *config, 12050769Sdfr struct isa_config *result) 12150769Sdfr{ 12250769Sdfr int success, i; 12350769Sdfr struct resource *res[ISA_NMEM]; 12450769Sdfr 12550769Sdfr /* 12650769Sdfr * First clear out any existing resource definitions. 12750769Sdfr */ 12850769Sdfr for (i = 0; i < ISA_NMEM; i++) { 12952174Sdfr bus_delete_resource(child, SYS_RES_MEMORY, i); 13050769Sdfr res[i] = NULL; 13150769Sdfr } 13250769Sdfr 13350769Sdfr success = 1; 13450769Sdfr result->ic_nmem = config->ic_nmem; 13550769Sdfr for (i = 0; i < config->ic_nmem; i++) { 13650769Sdfr u_int32_t start, end, size, align; 13783051Syokota 13883051Syokota size = config->ic_mem[i].ir_size; 13983051Syokota 14083051Syokota /* the PnP device may have a null resource as filler */ 14183051Syokota if (size == 0) { 14283051Syokota result->ic_mem[i].ir_start = 0; 14383051Syokota result->ic_mem[i].ir_end = 0; 14483051Syokota result->ic_mem[i].ir_size = 0; 14583051Syokota result->ic_mem[i].ir_align = 0; 14683051Syokota continue; 14783051Syokota } 14883051Syokota 14950769Sdfr for (start = config->ic_mem[i].ir_start, 15050769Sdfr end = config->ic_mem[i].ir_end, 15150769Sdfr align = config->ic_mem[i].ir_align; 15250769Sdfr start + size - 1 <= end; 15350769Sdfr start += align) { 15452174Sdfr bus_set_resource(child, SYS_RES_MEMORY, i, 15550769Sdfr start, size); 15650769Sdfr res[i] = bus_alloc_resource(child, 15750769Sdfr SYS_RES_MEMORY, &i, 15857132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */); 15950769Sdfr if (res[i]) { 16050769Sdfr result->ic_mem[i].ir_start = start; 16150769Sdfr result->ic_mem[i].ir_end = start + size - 1; 16250769Sdfr result->ic_mem[i].ir_size = size; 16350769Sdfr result->ic_mem[i].ir_align = align; 16450769Sdfr break; 16550769Sdfr } 16650769Sdfr } 16750769Sdfr 16850769Sdfr /* 16950769Sdfr * If we didn't find a place for memory range i, then 17050769Sdfr * give up now. 17150769Sdfr */ 17250769Sdfr if (!res[i]) { 17350769Sdfr success = 0; 17450769Sdfr break; 17550769Sdfr } 17650769Sdfr } 17750769Sdfr 17850769Sdfr for (i = 0; i < ISA_NMEM; i++) { 17950769Sdfr if (res[i]) 18050769Sdfr bus_release_resource(child, SYS_RES_MEMORY, 18150769Sdfr i, res[i]); 18250769Sdfr } 18350769Sdfr 18450769Sdfr return success; 18550769Sdfr} 18650769Sdfr 18750769Sdfr/* 18850769Sdfr * Find a working set of port regions for a child using the ranges 18950769Sdfr * in *config and return the regions in *result. Returns non-zero if 19050769Sdfr * a set of ranges was found. 19150769Sdfr */ 19250769Sdfrstatic int 19350769Sdfrisa_find_port(device_t child, 19450769Sdfr struct isa_config *config, 19550769Sdfr struct isa_config *result) 19650769Sdfr{ 19750769Sdfr int success, i; 19850769Sdfr struct resource *res[ISA_NPORT]; 19950769Sdfr 20050769Sdfr /* 20150769Sdfr * First clear out any existing resource definitions. 20250769Sdfr */ 20350769Sdfr for (i = 0; i < ISA_NPORT; i++) { 20452174Sdfr bus_delete_resource(child, SYS_RES_IOPORT, i); 20550769Sdfr res[i] = NULL; 20650769Sdfr } 20750769Sdfr 20850769Sdfr success = 1; 20950769Sdfr result->ic_nport = config->ic_nport; 21050769Sdfr for (i = 0; i < config->ic_nport; i++) { 21150769Sdfr u_int32_t start, end, size, align; 21283051Syokota 21383051Syokota size = config->ic_port[i].ir_size; 21483051Syokota 21583051Syokota /* the PnP device may have a null resource as filler */ 21683051Syokota if (size == 0) { 21783051Syokota result->ic_port[i].ir_start = 0; 21883051Syokota result->ic_port[i].ir_end = 0; 21983051Syokota result->ic_port[i].ir_size = 0; 22083051Syokota result->ic_port[i].ir_align = 0; 22183051Syokota continue; 22283051Syokota } 22383051Syokota 22450769Sdfr for (start = config->ic_port[i].ir_start, 22550769Sdfr end = config->ic_port[i].ir_end, 22650769Sdfr align = config->ic_port[i].ir_align; 22750769Sdfr start + size - 1 <= end; 22850769Sdfr start += align) { 22952174Sdfr bus_set_resource(child, SYS_RES_IOPORT, i, 23050769Sdfr start, size); 23150769Sdfr res[i] = bus_alloc_resource(child, 23250769Sdfr SYS_RES_IOPORT, &i, 23357132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */); 23450769Sdfr if (res[i]) { 23550769Sdfr result->ic_port[i].ir_start = start; 23650769Sdfr result->ic_port[i].ir_end = start + size - 1; 23750769Sdfr result->ic_port[i].ir_size = size; 23850769Sdfr result->ic_port[i].ir_align = align; 23950769Sdfr break; 24050769Sdfr } 24150769Sdfr } 24250769Sdfr 24350769Sdfr /* 24450769Sdfr * If we didn't find a place for port range i, then 24550769Sdfr * give up now. 24650769Sdfr */ 24750769Sdfr if (!res[i]) { 24850769Sdfr success = 0; 24950769Sdfr break; 25050769Sdfr } 25150769Sdfr } 25250769Sdfr 25350769Sdfr for (i = 0; i < ISA_NPORT; i++) { 25450769Sdfr if (res[i]) 25550769Sdfr bus_release_resource(child, SYS_RES_IOPORT, 25650769Sdfr i, res[i]); 25750769Sdfr } 25850769Sdfr 25950769Sdfr return success; 26050769Sdfr} 26150769Sdfr 26250769Sdfr/* 26350769Sdfr * Return the index of the first bit in the mask (or -1 if mask is empty. 26450769Sdfr */ 26550769Sdfrstatic int 26650769Sdfrfind_first_bit(u_int32_t mask) 26750769Sdfr{ 26850769Sdfr return ffs(mask) - 1; 26950769Sdfr} 27050769Sdfr 27150769Sdfr/* 27250769Sdfr * Return the index of the next bit in the mask, or -1 if there are no more. 27350769Sdfr */ 27450769Sdfrstatic int 27550769Sdfrfind_next_bit(u_int32_t mask, int bit) 27650769Sdfr{ 27750769Sdfr bit++; 27850769Sdfr while (bit < 32 && !(mask & (1 << bit))) 27950769Sdfr bit++; 28050769Sdfr if (bit != 32) 28150769Sdfr return bit; 28250769Sdfr return -1; 28350769Sdfr} 28450769Sdfr 28550769Sdfr/* 28650769Sdfr * Find a working set of irqs for a child using the masks in *config 28750769Sdfr * and return the regions in *result. Returns non-zero if a set of 28850769Sdfr * irqs was found. 28950769Sdfr */ 29050769Sdfrstatic int 29150769Sdfrisa_find_irq(device_t child, 29250769Sdfr struct isa_config *config, 29350769Sdfr struct isa_config *result) 29450769Sdfr{ 29550769Sdfr int success, i; 29650769Sdfr struct resource *res[ISA_NIRQ]; 29750769Sdfr 29850769Sdfr /* 29950769Sdfr * First clear out any existing resource definitions. 30050769Sdfr */ 30150769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 30252174Sdfr bus_delete_resource(child, SYS_RES_IRQ, i); 30350769Sdfr res[i] = NULL; 30450769Sdfr } 30550769Sdfr 30650769Sdfr success = 1; 30750769Sdfr result->ic_nirq = config->ic_nirq; 30850769Sdfr for (i = 0; i < config->ic_nirq; i++) { 30950769Sdfr u_int32_t mask = config->ic_irqmask[i]; 31050769Sdfr int irq; 31183051Syokota 31283051Syokota /* the PnP device may have a null resource as filler */ 31383051Syokota if (mask == 0) { 31483051Syokota result->ic_irqmask[i] = 0; 31583051Syokota continue; 31683051Syokota } 31783051Syokota 31850769Sdfr for (irq = find_first_bit(mask); 31950769Sdfr irq != -1; 32050769Sdfr irq = find_next_bit(mask, irq)) { 32152174Sdfr bus_set_resource(child, SYS_RES_IRQ, i, 32250769Sdfr irq, 1); 32350769Sdfr res[i] = bus_alloc_resource(child, 32450769Sdfr SYS_RES_IRQ, &i, 32557132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */ ); 32650769Sdfr if (res[i]) { 32750769Sdfr result->ic_irqmask[i] = (1 << irq); 32850769Sdfr break; 32950769Sdfr } 33050769Sdfr } 33150769Sdfr 33250769Sdfr /* 33350769Sdfr * If we didn't find a place for irq range i, then 33450769Sdfr * give up now. 33550769Sdfr */ 33650769Sdfr if (!res[i]) { 33750769Sdfr success = 0; 33850769Sdfr break; 33950769Sdfr } 34050769Sdfr } 34150769Sdfr 34250769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 34350769Sdfr if (res[i]) 34450769Sdfr bus_release_resource(child, SYS_RES_IRQ, 34550769Sdfr i, res[i]); 34650769Sdfr } 34750769Sdfr 34850769Sdfr return success; 34950769Sdfr} 35050769Sdfr 35150769Sdfr/* 35250769Sdfr * Find a working set of drqs for a child using the masks in *config 35350769Sdfr * and return the regions in *result. Returns non-zero if a set of 35450769Sdfr * drqs was found. 35550769Sdfr */ 35650769Sdfrstatic int 35750769Sdfrisa_find_drq(device_t child, 35850769Sdfr struct isa_config *config, 35950769Sdfr struct isa_config *result) 36050769Sdfr{ 36150769Sdfr int success, i; 36250769Sdfr struct resource *res[ISA_NDRQ]; 36350769Sdfr 36450769Sdfr /* 36550769Sdfr * First clear out any existing resource definitions. 36650769Sdfr */ 36750769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 36852174Sdfr bus_delete_resource(child, SYS_RES_DRQ, i); 36950769Sdfr res[i] = NULL; 37050769Sdfr } 37150769Sdfr 37250769Sdfr success = 1; 37350769Sdfr result->ic_ndrq = config->ic_ndrq; 37450769Sdfr for (i = 0; i < config->ic_ndrq; i++) { 37550769Sdfr u_int32_t mask = config->ic_drqmask[i]; 37650769Sdfr int drq; 37783051Syokota 37883051Syokota /* the PnP device may have a null resource as filler */ 37983051Syokota if (mask == 0) { 38083051Syokota result->ic_drqmask[i] = 0; 38183051Syokota continue; 38283051Syokota } 38383051Syokota 38450769Sdfr for (drq = find_first_bit(mask); 38550769Sdfr drq != -1; 38650769Sdfr drq = find_next_bit(mask, drq)) { 38752174Sdfr bus_set_resource(child, SYS_RES_DRQ, i, 38850769Sdfr drq, 1); 38950769Sdfr res[i] = bus_alloc_resource(child, 39050769Sdfr SYS_RES_DRQ, &i, 39157132Smsmith 0, ~0, 1, 0 /* !RF_ACTIVE */); 39250769Sdfr if (res[i]) { 39350769Sdfr result->ic_drqmask[i] = (1 << drq); 39450769Sdfr break; 39550769Sdfr } 39650769Sdfr } 39750769Sdfr 39850769Sdfr /* 39950769Sdfr * If we didn't find a place for drq range i, then 40050769Sdfr * give up now. 40150769Sdfr */ 40250769Sdfr if (!res[i]) { 40350769Sdfr success = 0; 40450769Sdfr break; 40550769Sdfr } 40650769Sdfr } 40750769Sdfr 40850769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 40950769Sdfr if (res[i]) 41050769Sdfr bus_release_resource(child, SYS_RES_DRQ, 41150769Sdfr i, res[i]); 41250769Sdfr } 41350769Sdfr 41450769Sdfr return success; 41550769Sdfr} 41650769Sdfr 41750769Sdfr/* 41850769Sdfr * Attempt to find a working set of resources for a device. Return 41950769Sdfr * non-zero if a working configuration is found. 42050769Sdfr */ 42150769Sdfrstatic int 42250769Sdfrisa_assign_resources(device_t child) 42350769Sdfr{ 42450769Sdfr struct isa_device *idev = DEVTOISA(child); 42550769Sdfr struct isa_config_entry *ice; 42681401Sjulian struct isa_config *cfg; 42791206Salfred const char *reason; 42891206Salfred 42991206Salfred reason = "Empty ISA id_configs"; 43081401Sjulian cfg = malloc(sizeof(struct isa_config), M_TEMP, M_NOWAIT|M_ZERO); 43181401Sjulian if (cfg == NULL) 43281401Sjulian return(0); 43350769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 43491202Salfred reason = "memory"; 43581401Sjulian if (!isa_find_memory(child, &ice->ice_config, cfg)) 43650769Sdfr continue; 43791202Salfred reason = "port"; 43881401Sjulian if (!isa_find_port(child, &ice->ice_config, cfg)) 43950769Sdfr continue; 44091202Salfred reason = "irq"; 44181401Sjulian if (!isa_find_irq(child, &ice->ice_config, cfg)) 44250769Sdfr continue; 44391202Salfred reason = "drq"; 44481401Sjulian if (!isa_find_drq(child, &ice->ice_config, cfg)) 44550769Sdfr continue; 44650769Sdfr 44750769Sdfr /* 44850769Sdfr * A working configuration was found enable the device 44950769Sdfr * with this configuration. 45050769Sdfr */ 45191202Salfred reason = "no callback"; 45250769Sdfr if (idev->id_config_cb) { 45350769Sdfr idev->id_config_cb(idev->id_config_arg, 45481401Sjulian cfg, 1); 45581401Sjulian free(cfg, M_TEMP); 45650769Sdfr return 1; 45750769Sdfr } 45850769Sdfr } 45950769Sdfr 46050769Sdfr /* 46150769Sdfr * Disable the device. 46250769Sdfr */ 46362987Sjhb bus_print_child_header(device_get_parent(child), child); 46491202Salfred printf(" can't assign resources (%s)\n", reason); 46562987Sjhb if (bootverbose) 46662987Sjhb isa_print_child(device_get_parent(child), child); 46781401Sjulian bzero(cfg, sizeof (*cfg)); 46850769Sdfr if (idev->id_config_cb) 46981401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 47050769Sdfr device_disable(child); 47150769Sdfr 47281401Sjulian free(cfg, M_TEMP); 47350769Sdfr return 0; 47450769Sdfr} 47550769Sdfr 47650769Sdfr/* 47783051Syokota * Return non-zero if the device has a single configuration, that is, 47883051Syokota * a fixed set of resoruces. 47983051Syokota */ 48083051Syokotastatic int 48183051Syokotaisa_has_single_config(device_t dev) 48283051Syokota{ 48383051Syokota struct isa_device *idev = DEVTOISA(dev); 48483051Syokota struct isa_config_entry *ice; 48583051Syokota u_int32_t mask; 48683051Syokota int i; 48783051Syokota 48883051Syokota ice = TAILQ_FIRST(&idev->id_configs); 48983051Syokota if (TAILQ_NEXT(ice, ice_link)) 49083051Syokota return 0; 49183051Syokota 49283051Syokota for (i = 0; i < ice->ice_config.ic_nmem; ++i) { 49383051Syokota if (ice->ice_config.ic_mem[i].ir_size == 0) 49483051Syokota continue; 49583051Syokota if (ice->ice_config.ic_mem[i].ir_end != 49683051Syokota ice->ice_config.ic_mem[i].ir_start + 49783051Syokota ice->ice_config.ic_mem[i].ir_size - 1) 49883051Syokota return 0; 49983051Syokota } 50083051Syokota for (i = 0; i < ice->ice_config.ic_nport; ++i) { 50183051Syokota if (ice->ice_config.ic_port[i].ir_size == 0) 50283051Syokota continue; 50383051Syokota if (ice->ice_config.ic_port[i].ir_end != 50483051Syokota ice->ice_config.ic_port[i].ir_start + 50583051Syokota ice->ice_config.ic_port[i].ir_size - 1) 50683051Syokota return 0; 50783051Syokota } 50883051Syokota for (i = 0; i < ice->ice_config.ic_nirq; ++i) { 50983051Syokota mask = ice->ice_config.ic_irqmask[i]; 51083051Syokota if (mask == 0) 51183051Syokota continue; 51283051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 51383051Syokota return 0; 51483051Syokota } 51583051Syokota for (i = 0; i < ice->ice_config.ic_ndrq; ++i) { 51683051Syokota mask = ice->ice_config.ic_drqmask[i]; 51783051Syokota if (mask == 0) 51883051Syokota continue; 51983051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 52083051Syokota return 0; 52183051Syokota } 52283051Syokota return 1; 52383051Syokota} 52483051Syokota 52583051Syokota/* 52650769Sdfr * Called after other devices have initialised to probe for isa devices. 52750769Sdfr */ 52850769Sdfrvoid 52950769Sdfrisa_probe_children(device_t dev) 53050769Sdfr{ 53150769Sdfr device_t *children; 53281401Sjulian struct isa_config *cfg; 53350769Sdfr int nchildren, i; 53450769Sdfr 53553094Sdfr /* 53653094Sdfr * Create all the children by calling driver's identify methods. 53753094Sdfr */ 53853094Sdfr bus_generic_probe(dev); 53953094Sdfr 54050769Sdfr if (device_get_children(dev, &children, &nchildren)) 54150769Sdfr return; 54250769Sdfr 54350769Sdfr /* 54451905Sdfr * First disable all pnp devices so that they don't get 54551905Sdfr * matched by legacy probes. 54651905Sdfr */ 54753094Sdfr if (bootverbose) 54853094Sdfr printf("isa_probe_children: disabling PnP devices\n"); 54981401Sjulian 55081401Sjulian cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 55181401Sjulian if (cfg == NULL) { 55281401Sjulian free(children, M_TEMP); 55381401Sjulian return; 55481401Sjulian } 55581401Sjulian 55651905Sdfr for (i = 0; i < nchildren; i++) { 55751905Sdfr device_t child = children[i]; 55851905Sdfr struct isa_device *idev = DEVTOISA(child); 55951905Sdfr 56081401Sjulian bzero(cfg, sizeof(*cfg)); 56151905Sdfr if (idev->id_config_cb) 56281401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 56351905Sdfr } 56451905Sdfr 56581401Sjulian free(cfg, M_TEMP); 56681401Sjulian 56751905Sdfr /* 56851905Sdfr * Next probe all non-pnp devices so that they claim their 56950769Sdfr * resources first. 57050769Sdfr */ 57153094Sdfr if (bootverbose) 57253094Sdfr printf("isa_probe_children: probing non-PnP devices\n"); 57350769Sdfr for (i = 0; i < nchildren; i++) { 57450769Sdfr device_t child = children[i]; 57550769Sdfr struct isa_device *idev = DEVTOISA(child); 57650769Sdfr 57750769Sdfr if (TAILQ_FIRST(&idev->id_configs)) 57850769Sdfr continue; 57950769Sdfr 58050769Sdfr device_probe_and_attach(child); 58150769Sdfr } 58250769Sdfr 58350769Sdfr /* 58451905Sdfr * Finally assign resource to pnp devices and probe them. 58550769Sdfr */ 58653094Sdfr if (bootverbose) 58753094Sdfr printf("isa_probe_children: probing PnP devices\n"); 58850769Sdfr for (i = 0; i < nchildren; i++) { 58950769Sdfr device_t child = children[i]; 59050769Sdfr struct isa_device* idev = DEVTOISA(child); 59150769Sdfr 59250769Sdfr if (!TAILQ_FIRST(&idev->id_configs)) 59350769Sdfr continue; 59450769Sdfr 59550769Sdfr if (isa_assign_resources(child)) { 59652174Sdfr struct resource_list *rl = &idev->id_resources; 59750769Sdfr struct resource_list_entry *rle; 59850769Sdfr 59950769Sdfr device_probe_and_attach(child); 60050769Sdfr 60150769Sdfr /* 60250769Sdfr * Claim any unallocated resources to keep other 60350769Sdfr * devices from using them. 60450769Sdfr */ 60552174Sdfr SLIST_FOREACH(rle, rl, link) { 60650769Sdfr if (!rle->res) { 60750769Sdfr int rid = rle->rid; 60852174Sdfr resource_list_alloc(rl, dev, child, 60950769Sdfr rle->type, 61050769Sdfr &rid, 61162059Sdfr 0, ~0, 1, 0); 61250769Sdfr } 61350769Sdfr } 61450769Sdfr } 61550769Sdfr } 61650769Sdfr 61750769Sdfr free(children, M_TEMP); 61853094Sdfr 61953094Sdfr isa_running = 1; 62050769Sdfr} 62150769Sdfr 62250769Sdfr/* 62347398Sdfr * Add a new child with default ivars. 62447398Sdfr */ 62547398Sdfrstatic device_t 62647578Sdfrisa_add_child(device_t dev, int order, const char *name, int unit) 62747398Sdfr{ 62854073Smdodd device_t child; 62947398Sdfr struct isa_device *idev; 63047398Sdfr 631104179Sphk child = device_add_child_ordered(dev, order, name, unit); 632104179Sphk if (child == NULL) 633104179Sphk return (child); 634104179Sphk 63569781Sdwmalone idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 63647398Sdfr if (!idev) 63747398Sdfr return 0; 63847398Sdfr 63947398Sdfr resource_list_init(&idev->id_resources); 64050769Sdfr TAILQ_INIT(&idev->id_configs); 64147398Sdfr 642104179Sphk device_set_ivars(child, idev); 64354073Smdodd 644104179Sphk return (child); 64547398Sdfr} 64647398Sdfr 64762059Sdfrstatic int 64862059Sdfrisa_print_all_resources(device_t dev) 64947398Sdfr{ 65047398Sdfr struct isa_device *idev = DEVTOISA(dev); 65147398Sdfr struct resource_list *rl = &idev->id_resources; 65249195Smdodd int retval = 0; 65347398Sdfr 65451052Sdfr if (SLIST_FIRST(rl) || device_get_flags(dev)) 65549195Smdodd retval += printf(" at"); 65647398Sdfr 65788376Stmm retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 65888376Stmm retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 65988376Stmm retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 66088376Stmm retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld"); 66151052Sdfr if (device_get_flags(dev)) 66251052Sdfr retval += printf(" flags %#x", device_get_flags(dev)); 66347398Sdfr 66462059Sdfr return retval; 66562059Sdfr} 66662059Sdfr 66762059Sdfrstatic int 66862059Sdfrisa_print_child(device_t bus, device_t dev) 66962059Sdfr{ 67062059Sdfr int retval = 0; 67162059Sdfr 67262059Sdfr retval += bus_print_child_header(bus, dev); 67362059Sdfr retval += isa_print_all_resources(dev); 67449195Smdodd retval += bus_print_child_footer(bus, dev); 67549195Smdodd 67649195Smdodd return (retval); 67747398Sdfr} 67847398Sdfr 67962059Sdfrstatic void 68062059Sdfrisa_probe_nomatch(device_t dev, device_t child) 68162059Sdfr{ 68262987Sjhb if (bootverbose) { 68362987Sjhb bus_print_child_header(dev, child); 68462987Sjhb printf(" failed to probe"); 68562059Sdfr isa_print_all_resources(child); 68662987Sjhb bus_print_child_footer(dev, child); 68762987Sjhb } 68862059Sdfr 68962059Sdfr return; 69062059Sdfr} 69162059Sdfr 69247398Sdfrstatic int 69347398Sdfrisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 69447398Sdfr{ 69547398Sdfr struct isa_device* idev = DEVTOISA(dev); 69647398Sdfr struct resource_list *rl = &idev->id_resources; 69747398Sdfr struct resource_list_entry *rle; 69847398Sdfr 69947398Sdfr switch (index) { 70047398Sdfr case ISA_IVAR_PORT_0: 70147398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 70247398Sdfr if (rle) 70347398Sdfr *result = rle->start; 70447398Sdfr else 70547398Sdfr *result = -1; 70647398Sdfr break; 70747398Sdfr 70847398Sdfr case ISA_IVAR_PORT_1: 70947398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 71047398Sdfr if (rle) 71147398Sdfr *result = rle->start; 71247398Sdfr else 71347398Sdfr *result = -1; 71447398Sdfr break; 71547398Sdfr 71647398Sdfr case ISA_IVAR_PORTSIZE_0: 71747398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 71847398Sdfr if (rle) 71947398Sdfr *result = rle->count; 72047398Sdfr else 72147398Sdfr *result = 0; 72247398Sdfr break; 72347398Sdfr 72447398Sdfr case ISA_IVAR_PORTSIZE_1: 72547398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 72647398Sdfr if (rle) 72747398Sdfr *result = rle->count; 72847398Sdfr else 72947398Sdfr *result = 0; 73047398Sdfr break; 73147398Sdfr 73247398Sdfr case ISA_IVAR_MADDR_0: 73347398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 73447398Sdfr if (rle) 73547398Sdfr *result = rle->start; 73647398Sdfr else 73747398Sdfr *result = -1; 73847398Sdfr break; 73947398Sdfr 74047398Sdfr case ISA_IVAR_MADDR_1: 74147398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 74247398Sdfr if (rle) 74347398Sdfr *result = rle->start; 74447398Sdfr else 74547398Sdfr *result = -1; 74647398Sdfr break; 74747398Sdfr 748105139Sjhb case ISA_IVAR_MEMSIZE_0: 74947398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 75047398Sdfr if (rle) 75147398Sdfr *result = rle->count; 75247398Sdfr else 75347398Sdfr *result = 0; 75447398Sdfr break; 75547398Sdfr 756105139Sjhb case ISA_IVAR_MEMSIZE_1: 75747398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 75847398Sdfr if (rle) 75947398Sdfr *result = rle->count; 76047398Sdfr else 76147398Sdfr *result = 0; 76247398Sdfr break; 76347398Sdfr 76447398Sdfr case ISA_IVAR_IRQ_0: 76547398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 0); 76647398Sdfr if (rle) 76747398Sdfr *result = rle->start; 76847398Sdfr else 76947398Sdfr *result = -1; 77047398Sdfr break; 77147398Sdfr 77247398Sdfr case ISA_IVAR_IRQ_1: 77347398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 1); 77447398Sdfr if (rle) 77547398Sdfr *result = rle->start; 77647398Sdfr else 77747398Sdfr *result = -1; 77847398Sdfr break; 77947398Sdfr 78047398Sdfr case ISA_IVAR_DRQ_0: 78147398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 0); 78247398Sdfr if (rle) 78347398Sdfr *result = rle->start; 78447398Sdfr else 78547398Sdfr *result = -1; 78647398Sdfr break; 78747398Sdfr 78847398Sdfr case ISA_IVAR_DRQ_1: 78947398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 1); 79047398Sdfr if (rle) 79147398Sdfr *result = rle->start; 79247398Sdfr else 79347398Sdfr *result = -1; 79447398Sdfr break; 79547398Sdfr 79647613Sdfr case ISA_IVAR_VENDORID: 79747613Sdfr *result = idev->id_vendorid; 79847613Sdfr break; 79947613Sdfr 80047613Sdfr case ISA_IVAR_SERIAL: 80147613Sdfr *result = idev->id_serial; 80247613Sdfr break; 80347613Sdfr 80447613Sdfr case ISA_IVAR_LOGICALID: 80547613Sdfr *result = idev->id_logicalid; 80647613Sdfr break; 80747613Sdfr 80847613Sdfr case ISA_IVAR_COMPATID: 80947613Sdfr *result = idev->id_compatid; 81047613Sdfr break; 81147613Sdfr 81282863Syokota case ISA_IVAR_CONFIGATTR: 81382863Syokota *result = idev->id_config_attr; 81482863Syokota break; 81582863Syokota 81647613Sdfr default: 81747613Sdfr return ENOENT; 81847398Sdfr } 81947613Sdfr 82047613Sdfr return 0; 82147398Sdfr} 82247398Sdfr 82347398Sdfrstatic int 82447398Sdfrisa_write_ivar(device_t bus, device_t dev, 82547398Sdfr int index, uintptr_t value) 82647398Sdfr{ 82747398Sdfr struct isa_device* idev = DEVTOISA(dev); 82847398Sdfr 82947398Sdfr switch (index) { 83047398Sdfr case ISA_IVAR_PORT_0: 83147398Sdfr case ISA_IVAR_PORT_1: 83247398Sdfr case ISA_IVAR_PORTSIZE_0: 83347398Sdfr case ISA_IVAR_PORTSIZE_1: 83447398Sdfr case ISA_IVAR_MADDR_0: 83547398Sdfr case ISA_IVAR_MADDR_1: 836105139Sjhb case ISA_IVAR_MEMSIZE_0: 837105139Sjhb case ISA_IVAR_MEMSIZE_1: 83847398Sdfr case ISA_IVAR_IRQ_0: 83947398Sdfr case ISA_IVAR_IRQ_1: 84047398Sdfr case ISA_IVAR_DRQ_0: 84147398Sdfr case ISA_IVAR_DRQ_1: 84247398Sdfr return EINVAL; 84347398Sdfr 84447613Sdfr case ISA_IVAR_VENDORID: 84547613Sdfr idev->id_vendorid = value; 84647613Sdfr break; 84747613Sdfr 84847613Sdfr case ISA_IVAR_SERIAL: 84947613Sdfr idev->id_serial = value; 85047613Sdfr break; 85147613Sdfr 85247613Sdfr case ISA_IVAR_LOGICALID: 85347613Sdfr idev->id_logicalid = value; 85447613Sdfr break; 85547613Sdfr 85647613Sdfr case ISA_IVAR_COMPATID: 85747613Sdfr idev->id_compatid = value; 85847613Sdfr break; 85947613Sdfr 86082863Syokota case ISA_IVAR_CONFIGATTR: 86182863Syokota idev->id_config_attr = value; 86282863Syokota break; 86382863Syokota 86447398Sdfr default: 86547398Sdfr return (ENOENT); 86647398Sdfr } 86747613Sdfr 86847398Sdfr return (0); 86947398Sdfr} 87047398Sdfr 87150769Sdfr/* 87250769Sdfr * Free any resources which the driver missed or which we were holding for 87350769Sdfr * it (see isa_probe_children). 87450769Sdfr */ 87550769Sdfrstatic void 87650769Sdfrisa_child_detached(device_t dev, device_t child) 87750769Sdfr{ 87850769Sdfr struct isa_device* idev = DEVTOISA(child); 87952174Sdfr struct resource_list *rl = &idev->id_resources; 88050769Sdfr struct resource_list_entry *rle; 88150769Sdfr 88262059Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 88362059Sdfr /* 88462059Sdfr * Claim any unallocated resources to keep other 88562059Sdfr * devices from using them. 88662059Sdfr */ 88762059Sdfr SLIST_FOREACH(rle, rl, link) { 88862059Sdfr if (!rle->res) { 88962059Sdfr int rid = rle->rid; 89062059Sdfr resource_list_alloc(rl, dev, child, 89162059Sdfr rle->type, 89262059Sdfr &rid, 0, ~0, 1, 0); 89362059Sdfr } 89462059Sdfr } 89550769Sdfr } 89650769Sdfr} 89750769Sdfr 89853094Sdfrstatic void 89953094Sdfrisa_driver_added(device_t dev, driver_t *driver) 90053094Sdfr{ 90153094Sdfr device_t *children; 90253094Sdfr int nchildren, i; 90353094Sdfr 90453094Sdfr /* 90553094Sdfr * Don't do anything if drivers are dynamically 90653094Sdfr * added during autoconfiguration (cf. ymf724). 90753094Sdfr * since that would end up calling identify 90853094Sdfr * twice. 90953094Sdfr */ 91053094Sdfr if (!isa_running) 91153094Sdfr return; 91253094Sdfr 91353094Sdfr DEVICE_IDENTIFY(driver, dev); 91453094Sdfr if (device_get_children(dev, &children, &nchildren)) 91553094Sdfr return; 91653094Sdfr 91753094Sdfr for (i = 0; i < nchildren; i++) { 91853094Sdfr device_t child = children[i]; 91953094Sdfr struct isa_device *idev = DEVTOISA(child); 92053094Sdfr struct resource_list *rl = &idev->id_resources; 92153094Sdfr struct resource_list_entry *rle; 92253094Sdfr 92353094Sdfr if (device_get_state(child) != DS_NOTPRESENT) 92453094Sdfr continue; 92562059Sdfr if (!device_is_enabled(child)) 92662059Sdfr continue; 92753094Sdfr 92862059Sdfr /* 92962059Sdfr * Free resources which we were holding on behalf of 93062059Sdfr * the device. 93162059Sdfr */ 93262059Sdfr SLIST_FOREACH(rle, &idev->id_resources, link) { 93362059Sdfr if (rle->res) 93462059Sdfr resource_list_release(rl, dev, child, 93562059Sdfr rle->type, 93662059Sdfr rle->rid, 93762059Sdfr rle->res); 93862059Sdfr } 93962059Sdfr 94053094Sdfr if (TAILQ_FIRST(&idev->id_configs)) 94153094Sdfr if (!isa_assign_resources(child)) 94253094Sdfr continue; 94353094Sdfr 94453094Sdfr device_probe_and_attach(child); 94553094Sdfr 94653094Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 94753094Sdfr /* 94853094Sdfr * Claim any unallocated resources to keep other 94953094Sdfr * devices from using them. 95053094Sdfr */ 95153094Sdfr SLIST_FOREACH(rle, rl, link) { 95253094Sdfr if (!rle->res) { 95353094Sdfr int rid = rle->rid; 95453094Sdfr resource_list_alloc(rl, dev, child, 95553094Sdfr rle->type, 95662059Sdfr &rid, 0, ~0, 1, 0); 95753094Sdfr } 95853094Sdfr } 95953094Sdfr } 96053094Sdfr } 96153094Sdfr 96253094Sdfr free(children, M_TEMP); 96353094Sdfr} 96453094Sdfr 96547398Sdfrstatic int 96647398Sdfrisa_set_resource(device_t dev, device_t child, int type, int rid, 96747398Sdfr u_long start, u_long count) 96847398Sdfr{ 96947398Sdfr struct isa_device* idev = DEVTOISA(child); 97047398Sdfr struct resource_list *rl = &idev->id_resources; 97147398Sdfr 97247398Sdfr if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 97347398Sdfr && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 97447398Sdfr return EINVAL; 97550769Sdfr if (rid < 0) 97647398Sdfr return EINVAL; 97750769Sdfr if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 97850769Sdfr return EINVAL; 97950769Sdfr if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 98050769Sdfr return EINVAL; 98150769Sdfr if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 98250769Sdfr return EINVAL; 98350769Sdfr if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 98450769Sdfr return EINVAL; 98547398Sdfr 98647398Sdfr resource_list_add(rl, type, rid, start, start + count - 1, count); 98747398Sdfr 98847398Sdfr return 0; 98947398Sdfr} 99047398Sdfr 99169295Smdoddstatic struct resource_list * 99269295Smdoddisa_get_resource_list (device_t dev, device_t child) 99347398Sdfr{ 99447398Sdfr struct isa_device* idev = DEVTOISA(child); 99547398Sdfr struct resource_list *rl = &idev->id_resources; 99647398Sdfr 99769295Smdodd if (!rl) 99869295Smdodd return (NULL); 99947398Sdfr 100069295Smdodd return (rl); 100147398Sdfr} 100247398Sdfr 100350769Sdfrstatic int 100450769Sdfrisa_add_config(device_t dev, device_t child, 100550769Sdfr int priority, struct isa_config *config) 100650769Sdfr{ 100750769Sdfr struct isa_device* idev = DEVTOISA(child); 100850769Sdfr struct isa_config_entry *newice, *ice; 100950769Sdfr 101050769Sdfr newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 101150769Sdfr if (!newice) 101250769Sdfr return ENOMEM; 101350769Sdfr 101450769Sdfr newice->ice_priority = priority; 101550769Sdfr newice->ice_config = *config; 101650769Sdfr 101750769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 101850769Sdfr if (ice->ice_priority > priority) 101950769Sdfr break; 102050769Sdfr } 102150769Sdfr if (ice) 102250769Sdfr TAILQ_INSERT_BEFORE(ice, newice, ice_link); 102350769Sdfr else 102450769Sdfr TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 102550769Sdfr 102683051Syokota if (isa_has_single_config(child)) 102783051Syokota idev->id_config_attr &= ~ISACFGATTR_MULTI; 102883051Syokota else 102983051Syokota idev->id_config_attr |= ISACFGATTR_MULTI; 103083051Syokota 103150769Sdfr return 0; 103250769Sdfr} 103350769Sdfr 103450769Sdfrstatic void 103550769Sdfrisa_set_config_callback(device_t dev, device_t child, 103650769Sdfr isa_config_cb *fn, void *arg) 103750769Sdfr{ 103850769Sdfr struct isa_device* idev = DEVTOISA(child); 103950769Sdfr 104050769Sdfr idev->id_config_cb = fn; 104150769Sdfr idev->id_config_arg = arg; 104250769Sdfr} 104350769Sdfr 104450769Sdfrstatic int 104550769Sdfrisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 104650769Sdfr{ 104750769Sdfr struct isa_device* idev = DEVTOISA(child); 104850769Sdfr 104950769Sdfr if (!idev->id_vendorid) 105050769Sdfr return ENOENT; 105150769Sdfr 105282553Smsmith while (ids && ids->ip_id) { 105350769Sdfr /* 105450769Sdfr * Really ought to support >1 compat id per device. 105550769Sdfr */ 105650769Sdfr if (idev->id_logicalid == ids->ip_id 105750769Sdfr || idev->id_compatid == ids->ip_id) { 105850910Sdfr if (ids->ip_desc) 105950910Sdfr device_set_desc(child, ids->ip_desc); 106050769Sdfr return 0; 106150769Sdfr } 106250769Sdfr ids++; 106350769Sdfr } 106450769Sdfr 106550769Sdfr return ENXIO; 106650769Sdfr} 106750769Sdfr 106847398Sdfrstatic device_method_t isa_methods[] = { 106947398Sdfr /* Device interface */ 107047398Sdfr DEVMETHOD(device_probe, isa_probe), 107147398Sdfr DEVMETHOD(device_attach, isa_attach), 107247398Sdfr DEVMETHOD(device_detach, bus_generic_detach), 107347398Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 107447398Sdfr DEVMETHOD(device_suspend, bus_generic_suspend), 107547398Sdfr DEVMETHOD(device_resume, bus_generic_resume), 107647398Sdfr 107747398Sdfr /* Bus interface */ 107847398Sdfr DEVMETHOD(bus_add_child, isa_add_child), 107947398Sdfr DEVMETHOD(bus_print_child, isa_print_child), 108062059Sdfr DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 108147398Sdfr DEVMETHOD(bus_read_ivar, isa_read_ivar), 108247398Sdfr DEVMETHOD(bus_write_ivar, isa_write_ivar), 108350769Sdfr DEVMETHOD(bus_child_detached, isa_child_detached), 108453094Sdfr DEVMETHOD(bus_driver_added, isa_driver_added), 108569295Smdodd DEVMETHOD(bus_setup_intr, isa_setup_intr), 108669295Smdodd DEVMETHOD(bus_teardown_intr, isa_teardown_intr), 108769295Smdodd 108869295Smdodd DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 108947398Sdfr DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 109047398Sdfr DEVMETHOD(bus_release_resource, isa_release_resource), 109169295Smdodd DEVMETHOD(bus_set_resource, isa_set_resource), 109269295Smdodd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 109369295Smdodd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 109447398Sdfr DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 109547398Sdfr DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 109647398Sdfr 109747398Sdfr /* ISA interface */ 109850769Sdfr DEVMETHOD(isa_add_config, isa_add_config), 109950769Sdfr DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 110050769Sdfr DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 110147398Sdfr 110247398Sdfr { 0, 0 } 110347398Sdfr}; 110447398Sdfr 110547398Sdfrstatic driver_t isa_driver = { 110647398Sdfr "isa", 110747398Sdfr isa_methods, 110847398Sdfr 1, /* no softc */ 110947398Sdfr}; 111047398Sdfr 111147398Sdfr/* 1112104015Sjhb * ISA can be attached to a PCI-ISA bridge or directly to the legacy device. 111347398Sdfr */ 111447398SdfrDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 111569942SmsmithDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 1116114335Speter#if defined(__i386__) || defined(__amd64__) 1117104015SjhbDRIVER_MODULE(isa, legacy, isa_driver, isa_devclass, 0, 0); 111847398Sdfr#endif 1119113498SmdoddMODULE_VERSION(isa, 1); 1120