isa_common.c revision 184564
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 184564 2008-11-02 18:48:54Z imp $"); 62116181Sobrien 63159552Smarius#include "opt_isa.h" 64159552Smarius 6547398Sdfr#include <sys/param.h> 6647398Sdfr#include <sys/systm.h> 6747398Sdfr#include <sys/kernel.h> 6847398Sdfr#include <sys/bus.h> 6947398Sdfr#include <sys/malloc.h> 7047398Sdfr#include <sys/module.h> 7147398Sdfr#include <machine/bus.h> 7247398Sdfr#include <sys/rman.h> 7347398Sdfr 7447398Sdfr#include <machine/resource.h> 7547398Sdfr 7647398Sdfr#include <isa/isavar.h> 7747398Sdfr#include <isa/isa_common.h> 7847398Sdfr 7962987Sjhbstatic int isa_print_child(device_t bus, device_t dev); 8062987Sjhb 8169774Sphkstatic MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); 8247398Sdfr 8353094Sdfrstatic int isa_running; 8447398Sdfr 8547398Sdfr/* 8647398Sdfr * At 'probe' time, we add all the devices which we know about to the 8747398Sdfr * bus. The generic attach routine will probe and attach them if they 8847398Sdfr * are alive. 8947398Sdfr */ 9047398Sdfrstatic int 9147398Sdfrisa_probe(device_t dev) 9247398Sdfr{ 9347398Sdfr device_set_desc(dev, "ISA bus"); 9488376Stmm isa_init(dev); /* Allow machdep code to initialise */ 95139273Simp return (0); 9647398Sdfr} 9747398Sdfr 9847398Sdfrextern device_t isa_bus_device; 9947398Sdfr 10047398Sdfrstatic int 10147398Sdfrisa_attach(device_t dev) 10247398Sdfr{ 10347398Sdfr /* 10450769Sdfr * Arrange for isa_probe_children(dev) to be called later. XXX 10547398Sdfr */ 10647398Sdfr isa_bus_device = dev; 107139273Simp return (0); 10847398Sdfr} 10947398Sdfr 11047398Sdfr/* 11150769Sdfr * Find a working set of memory regions for a child using the ranges 11250769Sdfr * in *config and return the regions in *result. Returns non-zero if 11350769Sdfr * a set of ranges was found. 11450769Sdfr */ 11550769Sdfrstatic int 116139273Simpisa_find_memory(device_t child, struct isa_config *config, 117139273Simp struct isa_config *result) 11850769Sdfr{ 11950769Sdfr int success, i; 12050769Sdfr struct resource *res[ISA_NMEM]; 12150769Sdfr 12250769Sdfr /* 12350769Sdfr * First clear out any existing resource definitions. 12450769Sdfr */ 12550769Sdfr for (i = 0; i < ISA_NMEM; i++) { 12652174Sdfr bus_delete_resource(child, SYS_RES_MEMORY, i); 12750769Sdfr res[i] = NULL; 12850769Sdfr } 12950769Sdfr 13050769Sdfr success = 1; 13150769Sdfr result->ic_nmem = config->ic_nmem; 13250769Sdfr for (i = 0; i < config->ic_nmem; i++) { 133139273Simp uint32_t start, end, size, align; 13483051Syokota 13583051Syokota size = config->ic_mem[i].ir_size; 13683051Syokota 13783051Syokota /* the PnP device may have a null resource as filler */ 13883051Syokota if (size == 0) { 13983051Syokota result->ic_mem[i].ir_start = 0; 14083051Syokota result->ic_mem[i].ir_end = 0; 14183051Syokota result->ic_mem[i].ir_size = 0; 14283051Syokota result->ic_mem[i].ir_align = 0; 14383051Syokota continue; 14483051Syokota } 14583051Syokota 14650769Sdfr for (start = config->ic_mem[i].ir_start, 14750769Sdfr end = config->ic_mem[i].ir_end, 14850769Sdfr align = config->ic_mem[i].ir_align; 149140647Simp start + size - 1 <= end && start + size > start; 150168816Sjhb start += MAX(align, 1)) { 15152174Sdfr bus_set_resource(child, SYS_RES_MEMORY, i, 15250769Sdfr start, size); 153139360Simp res[i] = bus_alloc_resource(child, 154139360Simp SYS_RES_MEMORY, &i, 0, ~0, 1, 155139360Simp rman_make_alignment_flags(align) /* !RF_ACTIVE */); 15650769Sdfr if (res[i]) { 15750769Sdfr result->ic_mem[i].ir_start = start; 15850769Sdfr result->ic_mem[i].ir_end = start + size - 1; 15950769Sdfr result->ic_mem[i].ir_size = size; 16050769Sdfr result->ic_mem[i].ir_align = align; 16150769Sdfr break; 16250769Sdfr } 16350769Sdfr } 16450769Sdfr 16550769Sdfr /* 16650769Sdfr * If we didn't find a place for memory range i, then 16750769Sdfr * give up now. 16850769Sdfr */ 16950769Sdfr if (!res[i]) { 17050769Sdfr success = 0; 17150769Sdfr break; 17250769Sdfr } 17350769Sdfr } 17450769Sdfr 17550769Sdfr for (i = 0; i < ISA_NMEM; i++) { 17650769Sdfr if (res[i]) 17750769Sdfr bus_release_resource(child, SYS_RES_MEMORY, 17850769Sdfr i, res[i]); 17950769Sdfr } 18050769Sdfr 181139273Simp return (success); 18250769Sdfr} 18350769Sdfr 18450769Sdfr/* 18550769Sdfr * Find a working set of port regions for a child using the ranges 18650769Sdfr * in *config and return the regions in *result. Returns non-zero if 18750769Sdfr * a set of ranges was found. 18850769Sdfr */ 18950769Sdfrstatic int 190139273Simpisa_find_port(device_t child, struct isa_config *config, 191139273Simp struct isa_config *result) 19250769Sdfr{ 19350769Sdfr int success, i; 19450769Sdfr struct resource *res[ISA_NPORT]; 19550769Sdfr 19650769Sdfr /* 19750769Sdfr * First clear out any existing resource definitions. 19850769Sdfr */ 19950769Sdfr for (i = 0; i < ISA_NPORT; i++) { 20052174Sdfr bus_delete_resource(child, SYS_RES_IOPORT, i); 20150769Sdfr res[i] = NULL; 20250769Sdfr } 20350769Sdfr 20450769Sdfr success = 1; 20550769Sdfr result->ic_nport = config->ic_nport; 20650769Sdfr for (i = 0; i < config->ic_nport; i++) { 207139273Simp uint32_t start, end, size, align; 20883051Syokota 20983051Syokota size = config->ic_port[i].ir_size; 21083051Syokota 21183051Syokota /* the PnP device may have a null resource as filler */ 21283051Syokota if (size == 0) { 21383051Syokota result->ic_port[i].ir_start = 0; 21483051Syokota result->ic_port[i].ir_end = 0; 21583051Syokota result->ic_port[i].ir_size = 0; 21683051Syokota result->ic_port[i].ir_align = 0; 21783051Syokota continue; 21883051Syokota } 21983051Syokota 22050769Sdfr for (start = config->ic_port[i].ir_start, 22150769Sdfr end = config->ic_port[i].ir_end, 22250769Sdfr align = config->ic_port[i].ir_align; 22350769Sdfr start + size - 1 <= end; 22450769Sdfr start += align) { 22552174Sdfr bus_set_resource(child, SYS_RES_IOPORT, i, 22650769Sdfr start, size); 227139360Simp res[i] = bus_alloc_resource(child, 228139360Simp SYS_RES_IOPORT, &i, 0, ~0, 1, 229139360Simp rman_make_alignment_flags(align) /* !RF_ACTIVE */); 23050769Sdfr if (res[i]) { 23150769Sdfr result->ic_port[i].ir_start = start; 23250769Sdfr result->ic_port[i].ir_end = start + size - 1; 23350769Sdfr result->ic_port[i].ir_size = size; 23450769Sdfr result->ic_port[i].ir_align = align; 23550769Sdfr break; 23650769Sdfr } 23750769Sdfr } 23850769Sdfr 23950769Sdfr /* 24050769Sdfr * If we didn't find a place for port range i, then 24150769Sdfr * give up now. 24250769Sdfr */ 24350769Sdfr if (!res[i]) { 24450769Sdfr success = 0; 24550769Sdfr break; 24650769Sdfr } 24750769Sdfr } 24850769Sdfr 24950769Sdfr for (i = 0; i < ISA_NPORT; i++) { 25050769Sdfr if (res[i]) 25150769Sdfr bus_release_resource(child, SYS_RES_IOPORT, 25250769Sdfr i, res[i]); 25350769Sdfr } 25450769Sdfr 25550769Sdfr return success; 25650769Sdfr} 25750769Sdfr 25850769Sdfr/* 25950769Sdfr * Return the index of the first bit in the mask (or -1 if mask is empty. 26050769Sdfr */ 26150769Sdfrstatic int 262139273Simpfind_first_bit(uint32_t mask) 26350769Sdfr{ 264139273Simp return (ffs(mask) - 1); 26550769Sdfr} 26650769Sdfr 26750769Sdfr/* 26850769Sdfr * Return the index of the next bit in the mask, or -1 if there are no more. 26950769Sdfr */ 27050769Sdfrstatic int 271139273Simpfind_next_bit(uint32_t mask, int bit) 27250769Sdfr{ 27350769Sdfr bit++; 27450769Sdfr while (bit < 32 && !(mask & (1 << bit))) 27550769Sdfr bit++; 27650769Sdfr if (bit != 32) 277139273Simp return (bit); 278139273Simp return (-1); 27950769Sdfr} 28050769Sdfr 28150769Sdfr/* 28250769Sdfr * Find a working set of irqs for a child using the masks in *config 28350769Sdfr * and return the regions in *result. Returns non-zero if a set of 28450769Sdfr * irqs was found. 28550769Sdfr */ 28650769Sdfrstatic int 287139273Simpisa_find_irq(device_t child, struct isa_config *config, 288139273Simp struct isa_config *result) 28950769Sdfr{ 29050769Sdfr int success, i; 29150769Sdfr struct resource *res[ISA_NIRQ]; 29250769Sdfr 29350769Sdfr /* 29450769Sdfr * First clear out any existing resource definitions. 29550769Sdfr */ 29650769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 29752174Sdfr bus_delete_resource(child, SYS_RES_IRQ, i); 29850769Sdfr res[i] = NULL; 29950769Sdfr } 30050769Sdfr 30150769Sdfr success = 1; 30250769Sdfr result->ic_nirq = config->ic_nirq; 30350769Sdfr for (i = 0; i < config->ic_nirq; i++) { 304139273Simp uint32_t mask = config->ic_irqmask[i]; 30550769Sdfr int irq; 30683051Syokota 30783051Syokota /* the PnP device may have a null resource as filler */ 30883051Syokota if (mask == 0) { 30983051Syokota result->ic_irqmask[i] = 0; 31083051Syokota continue; 31183051Syokota } 31283051Syokota 31350769Sdfr for (irq = find_first_bit(mask); 31450769Sdfr irq != -1; 31550769Sdfr irq = find_next_bit(mask, irq)) { 31652174Sdfr bus_set_resource(child, SYS_RES_IRQ, i, 31750769Sdfr irq, 1); 318127135Snjl res[i] = bus_alloc_resource_any(child, 319127135Snjl SYS_RES_IRQ, &i, 320127135Snjl 0 /* !RF_ACTIVE */ ); 32150769Sdfr if (res[i]) { 32250769Sdfr result->ic_irqmask[i] = (1 << irq); 32350769Sdfr break; 32450769Sdfr } 32550769Sdfr } 32650769Sdfr 32750769Sdfr /* 32850769Sdfr * If we didn't find a place for irq range i, then 32950769Sdfr * give up now. 33050769Sdfr */ 33150769Sdfr if (!res[i]) { 33250769Sdfr success = 0; 33350769Sdfr break; 33450769Sdfr } 33550769Sdfr } 33650769Sdfr 33750769Sdfr for (i = 0; i < ISA_NIRQ; i++) { 33850769Sdfr if (res[i]) 33950769Sdfr bus_release_resource(child, SYS_RES_IRQ, 34050769Sdfr i, res[i]); 34150769Sdfr } 34250769Sdfr 343139273Simp return (success); 34450769Sdfr} 34550769Sdfr 34650769Sdfr/* 34750769Sdfr * Find a working set of drqs for a child using the masks in *config 34850769Sdfr * and return the regions in *result. Returns non-zero if a set of 34950769Sdfr * drqs was found. 35050769Sdfr */ 35150769Sdfrstatic int 352139273Simpisa_find_drq(device_t child, struct isa_config *config, 353139273Simp struct isa_config *result) 35450769Sdfr{ 35550769Sdfr int success, i; 35650769Sdfr struct resource *res[ISA_NDRQ]; 35750769Sdfr 35850769Sdfr /* 35950769Sdfr * First clear out any existing resource definitions. 36050769Sdfr */ 36150769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 36252174Sdfr bus_delete_resource(child, SYS_RES_DRQ, i); 36350769Sdfr res[i] = NULL; 36450769Sdfr } 36550769Sdfr 36650769Sdfr success = 1; 36750769Sdfr result->ic_ndrq = config->ic_ndrq; 36850769Sdfr for (i = 0; i < config->ic_ndrq; i++) { 369139273Simp uint32_t mask = config->ic_drqmask[i]; 37050769Sdfr int drq; 37183051Syokota 37283051Syokota /* the PnP device may have a null resource as filler */ 37383051Syokota if (mask == 0) { 37483051Syokota result->ic_drqmask[i] = 0; 37583051Syokota continue; 37683051Syokota } 37783051Syokota 37850769Sdfr for (drq = find_first_bit(mask); 37950769Sdfr drq != -1; 38050769Sdfr drq = find_next_bit(mask, drq)) { 38152174Sdfr bus_set_resource(child, SYS_RES_DRQ, i, 38250769Sdfr drq, 1); 383127135Snjl res[i] = bus_alloc_resource_any(child, 384127135Snjl SYS_RES_DRQ, &i, 385127135Snjl 0 /* !RF_ACTIVE */); 38650769Sdfr if (res[i]) { 38750769Sdfr result->ic_drqmask[i] = (1 << drq); 38850769Sdfr break; 38950769Sdfr } 39050769Sdfr } 39150769Sdfr 39250769Sdfr /* 39350769Sdfr * If we didn't find a place for drq range i, then 39450769Sdfr * give up now. 39550769Sdfr */ 39650769Sdfr if (!res[i]) { 39750769Sdfr success = 0; 39850769Sdfr break; 39950769Sdfr } 40050769Sdfr } 40150769Sdfr 40250769Sdfr for (i = 0; i < ISA_NDRQ; i++) { 40350769Sdfr if (res[i]) 40450769Sdfr bus_release_resource(child, SYS_RES_DRQ, 40550769Sdfr i, res[i]); 40650769Sdfr } 40750769Sdfr 408139273Simp return (success); 40950769Sdfr} 41050769Sdfr 41150769Sdfr/* 41250769Sdfr * Attempt to find a working set of resources for a device. Return 41350769Sdfr * non-zero if a working configuration is found. 41450769Sdfr */ 41550769Sdfrstatic int 41650769Sdfrisa_assign_resources(device_t child) 41750769Sdfr{ 41850769Sdfr struct isa_device *idev = DEVTOISA(child); 41950769Sdfr struct isa_config_entry *ice; 42081401Sjulian struct isa_config *cfg; 42191206Salfred const char *reason; 42291206Salfred 42391206Salfred reason = "Empty ISA id_configs"; 42481401Sjulian cfg = malloc(sizeof(struct isa_config), M_TEMP, M_NOWAIT|M_ZERO); 42581401Sjulian if (cfg == NULL) 42681401Sjulian return(0); 42750769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 42891202Salfred reason = "memory"; 42981401Sjulian if (!isa_find_memory(child, &ice->ice_config, cfg)) 43050769Sdfr continue; 43191202Salfred reason = "port"; 43281401Sjulian if (!isa_find_port(child, &ice->ice_config, cfg)) 43350769Sdfr continue; 43491202Salfred reason = "irq"; 43581401Sjulian if (!isa_find_irq(child, &ice->ice_config, cfg)) 43650769Sdfr continue; 43791202Salfred reason = "drq"; 43881401Sjulian if (!isa_find_drq(child, &ice->ice_config, cfg)) 43950769Sdfr continue; 44050769Sdfr 44150769Sdfr /* 44250769Sdfr * A working configuration was found enable the device 44350769Sdfr * with this configuration. 44450769Sdfr */ 44591202Salfred reason = "no callback"; 44650769Sdfr if (idev->id_config_cb) { 44750769Sdfr idev->id_config_cb(idev->id_config_arg, 44881401Sjulian cfg, 1); 44981401Sjulian free(cfg, M_TEMP); 450139273Simp return (1); 45150769Sdfr } 45250769Sdfr } 45350769Sdfr 45450769Sdfr /* 45550769Sdfr * Disable the device. 45650769Sdfr */ 45762987Sjhb bus_print_child_header(device_get_parent(child), child); 45891202Salfred printf(" can't assign resources (%s)\n", reason); 45962987Sjhb if (bootverbose) 460139273Simp isa_print_child(device_get_parent(child), child); 46181401Sjulian bzero(cfg, sizeof (*cfg)); 46250769Sdfr if (idev->id_config_cb) 46381401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 46450769Sdfr device_disable(child); 46550769Sdfr 46681401Sjulian free(cfg, M_TEMP); 467139273Simp return (0); 46850769Sdfr} 46950769Sdfr 47050769Sdfrvoid 47150769Sdfrisa_probe_children(device_t dev) 47250769Sdfr{ 47350769Sdfr device_t *children; 47481401Sjulian struct isa_config *cfg; 47550769Sdfr int nchildren, i; 47650769Sdfr 47753094Sdfr /* 47853094Sdfr * Create all the children by calling driver's identify methods. 47953094Sdfr */ 48053094Sdfr bus_generic_probe(dev); 48153094Sdfr 48250769Sdfr if (device_get_children(dev, &children, &nchildren)) 48350769Sdfr return; 48450769Sdfr 48550769Sdfr /* 48651905Sdfr * First disable all pnp devices so that they don't get 48751905Sdfr * matched by legacy probes. 48851905Sdfr */ 48953094Sdfr if (bootverbose) 49053094Sdfr printf("isa_probe_children: disabling PnP devices\n"); 49181401Sjulian 49281401Sjulian cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 49381401Sjulian if (cfg == NULL) { 49481401Sjulian free(children, M_TEMP); 49581401Sjulian return; 49681401Sjulian } 49781401Sjulian 49851905Sdfr for (i = 0; i < nchildren; i++) { 49951905Sdfr device_t child = children[i]; 50051905Sdfr struct isa_device *idev = DEVTOISA(child); 50151905Sdfr 50281401Sjulian bzero(cfg, sizeof(*cfg)); 50351905Sdfr if (idev->id_config_cb) 50481401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 50551905Sdfr } 50651905Sdfr 50781401Sjulian free(cfg, M_TEMP); 50881401Sjulian 50951905Sdfr /* 51051905Sdfr * Next probe all non-pnp devices so that they claim their 51150769Sdfr * resources first. 51250769Sdfr */ 51353094Sdfr if (bootverbose) 51453094Sdfr printf("isa_probe_children: probing non-PnP devices\n"); 51550769Sdfr for (i = 0; i < nchildren; i++) { 51650769Sdfr device_t child = children[i]; 51750769Sdfr struct isa_device *idev = DEVTOISA(child); 51850769Sdfr 51950769Sdfr if (TAILQ_FIRST(&idev->id_configs)) 52050769Sdfr continue; 52150769Sdfr 52250769Sdfr device_probe_and_attach(child); 52350769Sdfr } 52450769Sdfr 52550769Sdfr /* 52651905Sdfr * Finally assign resource to pnp devices and probe them. 52750769Sdfr */ 52853094Sdfr if (bootverbose) 52953094Sdfr printf("isa_probe_children: probing PnP devices\n"); 53050769Sdfr for (i = 0; i < nchildren; i++) { 53150769Sdfr device_t child = children[i]; 53250769Sdfr struct isa_device* idev = DEVTOISA(child); 53350769Sdfr 53450769Sdfr if (!TAILQ_FIRST(&idev->id_configs)) 53550769Sdfr continue; 53650769Sdfr 53750769Sdfr if (isa_assign_resources(child)) { 53852174Sdfr struct resource_list *rl = &idev->id_resources; 53950769Sdfr struct resource_list_entry *rle; 54050769Sdfr 54150769Sdfr device_probe_and_attach(child); 54250769Sdfr 54350769Sdfr /* 54450769Sdfr * Claim any unallocated resources to keep other 54550769Sdfr * devices from using them. 54650769Sdfr */ 547143785Simp STAILQ_FOREACH(rle, rl, link) { 54850769Sdfr if (!rle->res) { 54950769Sdfr int rid = rle->rid; 55052174Sdfr resource_list_alloc(rl, dev, child, 55150769Sdfr rle->type, 55250769Sdfr &rid, 55362059Sdfr 0, ~0, 1, 0); 55450769Sdfr } 55550769Sdfr } 55650769Sdfr } 55750769Sdfr } 55850769Sdfr 55950769Sdfr free(children, M_TEMP); 56053094Sdfr 56153094Sdfr isa_running = 1; 56250769Sdfr} 56350769Sdfr 56450769Sdfr/* 56547398Sdfr * Add a new child with default ivars. 56647398Sdfr */ 56747398Sdfrstatic device_t 56847578Sdfrisa_add_child(device_t dev, int order, const char *name, int unit) 56947398Sdfr{ 57054073Smdodd device_t child; 57147398Sdfr struct isa_device *idev; 57247398Sdfr 573104179Sphk child = device_add_child_ordered(dev, order, name, unit); 574104179Sphk if (child == NULL) 575104179Sphk return (child); 576104179Sphk 57769781Sdwmalone idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 57847398Sdfr if (!idev) 579139273Simp return (0); 58047398Sdfr 58147398Sdfr resource_list_init(&idev->id_resources); 58250769Sdfr TAILQ_INIT(&idev->id_configs); 58347398Sdfr 584104179Sphk device_set_ivars(child, idev); 58554073Smdodd 586104179Sphk return (child); 58747398Sdfr} 58847398Sdfr 58962059Sdfrstatic int 59062059Sdfrisa_print_all_resources(device_t dev) 59147398Sdfr{ 59247398Sdfr struct isa_device *idev = DEVTOISA(dev); 59347398Sdfr struct resource_list *rl = &idev->id_resources; 59449195Smdodd int retval = 0; 59547398Sdfr 596143785Simp if (STAILQ_FIRST(rl) || device_get_flags(dev)) 59749195Smdodd retval += printf(" at"); 59847398Sdfr 59988376Stmm retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 60088376Stmm retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 60188376Stmm retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 60288376Stmm retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld"); 60351052Sdfr if (device_get_flags(dev)) 60451052Sdfr retval += printf(" flags %#x", device_get_flags(dev)); 605159552Smarius#ifdef ISAPNP 606148611Simp if (idev->id_vendorid) 607148611Simp retval += printf(" pnpid %s", pnp_eisaformat(idev->id_vendorid)); 608159552Smarius#endif 60947398Sdfr 610139273Simp return (retval); 61162059Sdfr} 61262059Sdfr 61362059Sdfrstatic int 61462059Sdfrisa_print_child(device_t bus, device_t dev) 61562059Sdfr{ 61662059Sdfr int retval = 0; 61762059Sdfr 61862059Sdfr retval += bus_print_child_header(bus, dev); 61962059Sdfr retval += isa_print_all_resources(dev); 62049195Smdodd retval += bus_print_child_footer(bus, dev); 62149195Smdodd 62249195Smdodd return (retval); 62347398Sdfr} 62447398Sdfr 62562059Sdfrstatic void 62662059Sdfrisa_probe_nomatch(device_t dev, device_t child) 62762059Sdfr{ 62862987Sjhb if (bootverbose) { 62962987Sjhb bus_print_child_header(dev, child); 63062987Sjhb printf(" failed to probe"); 63162059Sdfr isa_print_all_resources(child); 63262987Sjhb bus_print_child_footer(dev, child); 63362987Sjhb } 63462059Sdfr 63562059Sdfr return; 63662059Sdfr} 63762059Sdfr 63847398Sdfrstatic int 63947398Sdfrisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 64047398Sdfr{ 64147398Sdfr struct isa_device* idev = DEVTOISA(dev); 64247398Sdfr struct resource_list *rl = &idev->id_resources; 64347398Sdfr struct resource_list_entry *rle; 64447398Sdfr 64547398Sdfr switch (index) { 64647398Sdfr case ISA_IVAR_PORT_0: 64747398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 64847398Sdfr if (rle) 64947398Sdfr *result = rle->start; 65047398Sdfr else 65147398Sdfr *result = -1; 65247398Sdfr break; 65347398Sdfr 65447398Sdfr case ISA_IVAR_PORT_1: 65547398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 65647398Sdfr if (rle) 65747398Sdfr *result = rle->start; 65847398Sdfr else 65947398Sdfr *result = -1; 66047398Sdfr break; 66147398Sdfr 66247398Sdfr case ISA_IVAR_PORTSIZE_0: 66347398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 66447398Sdfr if (rle) 66547398Sdfr *result = rle->count; 66647398Sdfr else 66747398Sdfr *result = 0; 66847398Sdfr break; 66947398Sdfr 67047398Sdfr case ISA_IVAR_PORTSIZE_1: 67147398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 67247398Sdfr if (rle) 67347398Sdfr *result = rle->count; 67447398Sdfr else 67547398Sdfr *result = 0; 67647398Sdfr break; 67747398Sdfr 67847398Sdfr case ISA_IVAR_MADDR_0: 67947398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 68047398Sdfr if (rle) 68147398Sdfr *result = rle->start; 68247398Sdfr else 68347398Sdfr *result = -1; 68447398Sdfr break; 68547398Sdfr 68647398Sdfr case ISA_IVAR_MADDR_1: 68747398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 68847398Sdfr if (rle) 68947398Sdfr *result = rle->start; 69047398Sdfr else 69147398Sdfr *result = -1; 69247398Sdfr break; 69347398Sdfr 694105139Sjhb case ISA_IVAR_MEMSIZE_0: 69547398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 69647398Sdfr if (rle) 69747398Sdfr *result = rle->count; 69847398Sdfr else 69947398Sdfr *result = 0; 70047398Sdfr break; 70147398Sdfr 702105139Sjhb case ISA_IVAR_MEMSIZE_1: 70347398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 70447398Sdfr if (rle) 70547398Sdfr *result = rle->count; 70647398Sdfr else 70747398Sdfr *result = 0; 70847398Sdfr break; 70947398Sdfr 71047398Sdfr case ISA_IVAR_IRQ_0: 71147398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 0); 71247398Sdfr if (rle) 71347398Sdfr *result = rle->start; 71447398Sdfr else 71547398Sdfr *result = -1; 71647398Sdfr break; 71747398Sdfr 71847398Sdfr case ISA_IVAR_IRQ_1: 71947398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 1); 72047398Sdfr if (rle) 72147398Sdfr *result = rle->start; 72247398Sdfr else 72347398Sdfr *result = -1; 72447398Sdfr break; 72547398Sdfr 72647398Sdfr case ISA_IVAR_DRQ_0: 72747398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 0); 72847398Sdfr if (rle) 72947398Sdfr *result = rle->start; 73047398Sdfr else 73147398Sdfr *result = -1; 73247398Sdfr break; 73347398Sdfr 73447398Sdfr case ISA_IVAR_DRQ_1: 73547398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 1); 73647398Sdfr if (rle) 73747398Sdfr *result = rle->start; 73847398Sdfr else 73947398Sdfr *result = -1; 74047398Sdfr break; 74147398Sdfr 74247613Sdfr case ISA_IVAR_VENDORID: 74347613Sdfr *result = idev->id_vendorid; 74447613Sdfr break; 74547613Sdfr 74647613Sdfr case ISA_IVAR_SERIAL: 74747613Sdfr *result = idev->id_serial; 74847613Sdfr break; 74947613Sdfr 75047613Sdfr case ISA_IVAR_LOGICALID: 75147613Sdfr *result = idev->id_logicalid; 75247613Sdfr break; 75347613Sdfr 75447613Sdfr case ISA_IVAR_COMPATID: 75547613Sdfr *result = idev->id_compatid; 75647613Sdfr break; 75747613Sdfr 75882863Syokota case ISA_IVAR_CONFIGATTR: 75982863Syokota *result = idev->id_config_attr; 76082863Syokota break; 76182863Syokota 762184564Simp case ISA_IVAR_PNP_CSN: 763184564Simp *result = idev->id_pnp_csn; 764184564Simp break; 765184564Simp 766184564Simp case ISA_IVAR_PNP_LDN: 767184564Simp *result = idev->id_pnp_ldn; 768184564Simp break; 769184564Simp 770184564Simp case ISA_IVAR_PNPBIOS_HANDLE: 771184564Simp *result = idev->id_pnpbios_handle; 772184564Simp break; 773184564Simp 77447613Sdfr default: 775139273Simp return (ENOENT); 77647398Sdfr } 77747613Sdfr 778139273Simp return (0); 77947398Sdfr} 78047398Sdfr 78147398Sdfrstatic int 782139273Simpisa_write_ivar(device_t bus, device_t dev, int index, uintptr_t value) 78347398Sdfr{ 78447398Sdfr struct isa_device* idev = DEVTOISA(dev); 78547398Sdfr 78647398Sdfr switch (index) { 78747398Sdfr case ISA_IVAR_PORT_0: 78847398Sdfr case ISA_IVAR_PORT_1: 78947398Sdfr case ISA_IVAR_PORTSIZE_0: 79047398Sdfr case ISA_IVAR_PORTSIZE_1: 79147398Sdfr case ISA_IVAR_MADDR_0: 79247398Sdfr case ISA_IVAR_MADDR_1: 793105139Sjhb case ISA_IVAR_MEMSIZE_0: 794105139Sjhb case ISA_IVAR_MEMSIZE_1: 79547398Sdfr case ISA_IVAR_IRQ_0: 79647398Sdfr case ISA_IVAR_IRQ_1: 79747398Sdfr case ISA_IVAR_DRQ_0: 79847398Sdfr case ISA_IVAR_DRQ_1: 799139273Simp return (EINVAL); 80047398Sdfr 80147613Sdfr case ISA_IVAR_VENDORID: 80247613Sdfr idev->id_vendorid = value; 80347613Sdfr break; 80447613Sdfr 80547613Sdfr case ISA_IVAR_SERIAL: 80647613Sdfr idev->id_serial = value; 80747613Sdfr break; 80847613Sdfr 80947613Sdfr case ISA_IVAR_LOGICALID: 81047613Sdfr idev->id_logicalid = value; 81147613Sdfr break; 81247613Sdfr 81347613Sdfr case ISA_IVAR_COMPATID: 81447613Sdfr idev->id_compatid = value; 81547613Sdfr break; 81647613Sdfr 81782863Syokota case ISA_IVAR_CONFIGATTR: 81882863Syokota idev->id_config_attr = value; 81982863Syokota break; 82082863Syokota 82147398Sdfr default: 82247398Sdfr return (ENOENT); 82347398Sdfr } 82447613Sdfr 82547398Sdfr return (0); 82647398Sdfr} 82747398Sdfr 82850769Sdfr/* 82950769Sdfr * Free any resources which the driver missed or which we were holding for 83050769Sdfr * it (see isa_probe_children). 83150769Sdfr */ 83250769Sdfrstatic void 83350769Sdfrisa_child_detached(device_t dev, device_t child) 83450769Sdfr{ 83550769Sdfr struct isa_device* idev = DEVTOISA(child); 83652174Sdfr struct resource_list *rl = &idev->id_resources; 83750769Sdfr struct resource_list_entry *rle; 83850769Sdfr 83962059Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 84062059Sdfr /* 84162059Sdfr * Claim any unallocated resources to keep other 84262059Sdfr * devices from using them. 84362059Sdfr */ 844143785Simp STAILQ_FOREACH(rle, rl, link) { 84562059Sdfr if (!rle->res) { 84662059Sdfr int rid = rle->rid; 84762059Sdfr resource_list_alloc(rl, dev, child, 84862059Sdfr rle->type, 84962059Sdfr &rid, 0, ~0, 1, 0); 85062059Sdfr } 85162059Sdfr } 85250769Sdfr } 85350769Sdfr} 85450769Sdfr 85553094Sdfrstatic void 85653094Sdfrisa_driver_added(device_t dev, driver_t *driver) 85753094Sdfr{ 85853094Sdfr device_t *children; 85953094Sdfr int nchildren, i; 86053094Sdfr 86153094Sdfr /* 86253094Sdfr * Don't do anything if drivers are dynamically 86353094Sdfr * added during autoconfiguration (cf. ymf724). 86453094Sdfr * since that would end up calling identify 86553094Sdfr * twice. 86653094Sdfr */ 86753094Sdfr if (!isa_running) 86853094Sdfr return; 86953094Sdfr 87053094Sdfr DEVICE_IDENTIFY(driver, dev); 87153094Sdfr if (device_get_children(dev, &children, &nchildren)) 87253094Sdfr return; 87353094Sdfr 87453094Sdfr for (i = 0; i < nchildren; i++) { 87553094Sdfr device_t child = children[i]; 87653094Sdfr struct isa_device *idev = DEVTOISA(child); 87753094Sdfr struct resource_list *rl = &idev->id_resources; 87853094Sdfr struct resource_list_entry *rle; 87953094Sdfr 88053094Sdfr if (device_get_state(child) != DS_NOTPRESENT) 88153094Sdfr continue; 88262059Sdfr if (!device_is_enabled(child)) 88362059Sdfr continue; 88453094Sdfr 88562059Sdfr /* 88662059Sdfr * Free resources which we were holding on behalf of 88762059Sdfr * the device. 88862059Sdfr */ 889143785Simp STAILQ_FOREACH(rle, &idev->id_resources, link) { 89062059Sdfr if (rle->res) 89162059Sdfr resource_list_release(rl, dev, child, 89262059Sdfr rle->type, 89362059Sdfr rle->rid, 89462059Sdfr rle->res); 89562059Sdfr } 89662059Sdfr 89753094Sdfr if (TAILQ_FIRST(&idev->id_configs)) 89853094Sdfr if (!isa_assign_resources(child)) 89953094Sdfr continue; 90053094Sdfr 90153094Sdfr device_probe_and_attach(child); 90253094Sdfr 90353094Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 90453094Sdfr /* 90553094Sdfr * Claim any unallocated resources to keep other 90653094Sdfr * devices from using them. 90753094Sdfr */ 908143785Simp STAILQ_FOREACH(rle, rl, link) { 90953094Sdfr if (!rle->res) { 91053094Sdfr int rid = rle->rid; 91153094Sdfr resource_list_alloc(rl, dev, child, 91253094Sdfr rle->type, 91362059Sdfr &rid, 0, ~0, 1, 0); 91453094Sdfr } 91553094Sdfr } 91653094Sdfr } 91753094Sdfr } 91853094Sdfr 91953094Sdfr free(children, M_TEMP); 92053094Sdfr} 92153094Sdfr 92247398Sdfrstatic int 92347398Sdfrisa_set_resource(device_t dev, device_t child, int type, int rid, 924139273Simp u_long start, u_long count) 92547398Sdfr{ 92647398Sdfr struct isa_device* idev = DEVTOISA(child); 92747398Sdfr struct resource_list *rl = &idev->id_resources; 92847398Sdfr 92947398Sdfr if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 93047398Sdfr && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 931139273Simp return (EINVAL); 93250769Sdfr if (rid < 0) 933139273Simp return (EINVAL); 93450769Sdfr if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 935139273Simp return (EINVAL); 93650769Sdfr if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 937139273Simp return (EINVAL); 93850769Sdfr if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 939139273Simp return (EINVAL); 94050769Sdfr if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 941139273Simp return (EINVAL); 94247398Sdfr 94347398Sdfr resource_list_add(rl, type, rid, start, start + count - 1, count); 94447398Sdfr 945139273Simp return (0); 94647398Sdfr} 94747398Sdfr 94869295Smdoddstatic struct resource_list * 94969295Smdoddisa_get_resource_list (device_t dev, device_t child) 95047398Sdfr{ 95147398Sdfr struct isa_device* idev = DEVTOISA(child); 95247398Sdfr struct resource_list *rl = &idev->id_resources; 95347398Sdfr 95469295Smdodd if (!rl) 95569295Smdodd return (NULL); 95647398Sdfr 95769295Smdodd return (rl); 95847398Sdfr} 95947398Sdfr 96050769Sdfrstatic int 961139273Simpisa_add_config(device_t dev, device_t child, int priority, 962139273Simp struct isa_config *config) 96350769Sdfr{ 96450769Sdfr struct isa_device* idev = DEVTOISA(child); 96550769Sdfr struct isa_config_entry *newice, *ice; 96650769Sdfr 96750769Sdfr newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 96850769Sdfr if (!newice) 969139273Simp return (ENOMEM); 97050769Sdfr 97150769Sdfr newice->ice_priority = priority; 97250769Sdfr newice->ice_config = *config; 97350769Sdfr 97450769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 97550769Sdfr if (ice->ice_priority > priority) 97650769Sdfr break; 97750769Sdfr } 97850769Sdfr if (ice) 97950769Sdfr TAILQ_INSERT_BEFORE(ice, newice, ice_link); 98050769Sdfr else 98150769Sdfr TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 98250769Sdfr 983139273Simp return (0); 98450769Sdfr} 98550769Sdfr 98650769Sdfrstatic void 987139273Simpisa_set_config_callback(device_t dev, device_t child, isa_config_cb *fn, 988139273Simp void *arg) 98950769Sdfr{ 99050769Sdfr struct isa_device* idev = DEVTOISA(child); 99150769Sdfr 99250769Sdfr idev->id_config_cb = fn; 99350769Sdfr idev->id_config_arg = arg; 99450769Sdfr} 99550769Sdfr 99650769Sdfrstatic int 99750769Sdfrisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 99850769Sdfr{ 99950769Sdfr struct isa_device* idev = DEVTOISA(child); 100050769Sdfr 100150769Sdfr if (!idev->id_vendorid) 1002139273Simp return (ENOENT); 100350769Sdfr 100482553Smsmith while (ids && ids->ip_id) { 100550769Sdfr /* 100650769Sdfr * Really ought to support >1 compat id per device. 100750769Sdfr */ 100850769Sdfr if (idev->id_logicalid == ids->ip_id 100950769Sdfr || idev->id_compatid == ids->ip_id) { 101050910Sdfr if (ids->ip_desc) 101150910Sdfr device_set_desc(child, ids->ip_desc); 1012139273Simp return (0); 101350769Sdfr } 101450769Sdfr ids++; 101550769Sdfr } 101650769Sdfr 1017139273Simp return (ENXIO); 101850769Sdfr} 101950769Sdfr 1020148611Simpstatic int 1021148611Simpisa_child_pnpinfo_str(device_t bus, device_t child, char *buf, 1022148611Simp size_t buflen) 1023148611Simp{ 1024159552Smarius#ifdef ISAPNP 1025148611Simp struct isa_device *idev = DEVTOISA(child); 1026148611Simp 1027148611Simp if (idev->id_vendorid) 1028148611Simp snprintf(buf, buflen, "pnpid=%s", 1029148611Simp pnp_eisaformat(idev->id_vendorid)); 1030159552Smarius#endif 1031148611Simp return (0); 1032148611Simp} 1033148611Simp 1034148611Simpstatic int 1035148611Simpisa_child_location_str(device_t bus, device_t child, char *buf, 1036148611Simp size_t buflen) 1037148611Simp{ 1038184564Simp#if 0 1039184564Simp /* id_pnphandle isn't there yet */ 1040184564Simp struct isa_device *idev = DEVTOISA(child); 1041184564Simp 1042184564Simp if (idev->id_vendorid) 1043184564Simp snprintf(buf, buflen, "pnphandle=%d", idev->id_pnphandle); 1044184564Simp#endif 1045148611Simp /* Nothing here yet */ 1046148611Simp *buf = '\0'; 1047148611Simp return (0); 1048148611Simp} 1049148611Simp 105047398Sdfrstatic device_method_t isa_methods[] = { 105147398Sdfr /* Device interface */ 105247398Sdfr DEVMETHOD(device_probe, isa_probe), 105347398Sdfr DEVMETHOD(device_attach, isa_attach), 105447398Sdfr DEVMETHOD(device_detach, bus_generic_detach), 105547398Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 105647398Sdfr DEVMETHOD(device_suspend, bus_generic_suspend), 105747398Sdfr DEVMETHOD(device_resume, bus_generic_resume), 105847398Sdfr 105947398Sdfr /* Bus interface */ 106047398Sdfr DEVMETHOD(bus_add_child, isa_add_child), 106147398Sdfr DEVMETHOD(bus_print_child, isa_print_child), 106262059Sdfr DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 106347398Sdfr DEVMETHOD(bus_read_ivar, isa_read_ivar), 106447398Sdfr DEVMETHOD(bus_write_ivar, isa_write_ivar), 106550769Sdfr DEVMETHOD(bus_child_detached, isa_child_detached), 106653094Sdfr DEVMETHOD(bus_driver_added, isa_driver_added), 106769295Smdodd DEVMETHOD(bus_setup_intr, isa_setup_intr), 106869295Smdodd DEVMETHOD(bus_teardown_intr, isa_teardown_intr), 106969295Smdodd 107069295Smdodd DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 107147398Sdfr DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 107247398Sdfr DEVMETHOD(bus_release_resource, isa_release_resource), 107369295Smdodd DEVMETHOD(bus_set_resource, isa_set_resource), 107469295Smdodd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 107569295Smdodd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 107647398Sdfr DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 107747398Sdfr DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1078148611Simp DEVMETHOD(bus_child_pnpinfo_str, isa_child_pnpinfo_str), 1079148611Simp DEVMETHOD(bus_child_location_str, isa_child_location_str), 108047398Sdfr 108147398Sdfr /* ISA interface */ 108250769Sdfr DEVMETHOD(isa_add_config, isa_add_config), 108350769Sdfr DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 108450769Sdfr DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 108547398Sdfr 108647398Sdfr { 0, 0 } 108747398Sdfr}; 108847398Sdfr 1089139279Simpdriver_t isa_driver = { 109047398Sdfr "isa", 109147398Sdfr isa_methods, 109247398Sdfr 1, /* no softc */ 109347398Sdfr}; 109447398Sdfr 1095139279Simpdevclass_t isa_devclass; 1096139279Simp 109747398Sdfr/* 1098139279Simp * ISA can be attached to a PCI-ISA bridge, or other locations on some 1099139279Simp * platforms. 110047398Sdfr */ 110147398SdfrDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 110269942SmsmithDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 1103113498SmdoddMODULE_VERSION(isa, 1); 1104117337Sjhb 1105117337Sjhb/* 1106117337Sjhb * Code common to ISA bridges. 1107117337Sjhb */ 1108117337Sjhb 1109117337Sjhbdevclass_t isab_devclass; 1110117337Sjhb 1111117337Sjhbint 1112117337Sjhbisab_attach(device_t dev) 1113117337Sjhb{ 1114117337Sjhb device_t child; 1115117337Sjhb 1116117337Sjhb child = device_add_child(dev, "isa", 0); 1117117337Sjhb if (child != NULL) 1118117337Sjhb return (bus_generic_attach(dev)); 1119117337Sjhb return (ENXIO); 1120117337Sjhb} 1121