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$"); 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); 153295790Sjhibbits res[i] = bus_alloc_resource_any(child, 154295790Sjhibbits SYS_RES_MEMORY, &i, 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); 227295790Sjhibbits res[i] = bus_alloc_resource_any(child, 228295790Sjhibbits SYS_RES_IOPORT, &i, 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 470185059Sjhb/* 471185059Sjhb * Claim any unallocated resources to keep other devices from using 472185059Sjhb * them. 473185059Sjhb */ 474185059Sjhbstatic void 475185059Sjhbisa_claim_resources(device_t dev, device_t child) 476185059Sjhb{ 477185059Sjhb struct isa_device *idev = DEVTOISA(child); 478185059Sjhb struct resource_list *rl = &idev->id_resources; 479185059Sjhb struct resource_list_entry *rle; 480185059Sjhb int rid; 481185059Sjhb 482185059Sjhb STAILQ_FOREACH(rle, rl, link) { 483185059Sjhb if (!rle->res) { 484185059Sjhb rid = rle->rid; 485185059Sjhb resource_list_alloc(rl, dev, child, rle->type, &rid, 486296336Sjhibbits 0, ~0, 1, 0); 487185059Sjhb } 488185059Sjhb } 489185059Sjhb} 490185059Sjhb 491185059Sjhb/* 492185059Sjhb * Called after other devices have initialised to probe for isa devices. 493185059Sjhb */ 49450769Sdfrvoid 49550769Sdfrisa_probe_children(device_t dev) 49650769Sdfr{ 497185059Sjhb struct isa_device *idev; 498185059Sjhb device_t *children, child; 49981401Sjulian struct isa_config *cfg; 50050769Sdfr int nchildren, i; 50150769Sdfr 50253094Sdfr /* 503185059Sjhb * Create all the non-hinted children by calling drivers' 504185059Sjhb * identify methods. 50553094Sdfr */ 50653094Sdfr bus_generic_probe(dev); 50753094Sdfr 50850769Sdfr if (device_get_children(dev, &children, &nchildren)) 50950769Sdfr return; 51050769Sdfr 51150769Sdfr /* 51251905Sdfr * First disable all pnp devices so that they don't get 51351905Sdfr * matched by legacy probes. 51451905Sdfr */ 51553094Sdfr if (bootverbose) 51653094Sdfr printf("isa_probe_children: disabling PnP devices\n"); 51781401Sjulian 51881401Sjulian cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 51981401Sjulian if (cfg == NULL) { 52081401Sjulian free(children, M_TEMP); 52181401Sjulian return; 52281401Sjulian } 52381401Sjulian 52451905Sdfr for (i = 0; i < nchildren; i++) { 525185059Sjhb idev = DEVTOISA(children[i]); 52651905Sdfr 52781401Sjulian bzero(cfg, sizeof(*cfg)); 52851905Sdfr if (idev->id_config_cb) 52981401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 53051905Sdfr } 53151905Sdfr 53281401Sjulian free(cfg, M_TEMP); 53381401Sjulian 53451905Sdfr /* 535185059Sjhb * Next, probe all the PnP BIOS devices so they can subsume any 536185059Sjhb * hints. 53750769Sdfr */ 538185059Sjhb for (i = 0; i < nchildren; i++) { 539185059Sjhb child = children[i]; 540185059Sjhb idev = DEVTOISA(child); 541185059Sjhb 542185059Sjhb if (idev->id_order > ISA_ORDER_PNPBIOS) 543185059Sjhb continue; 544185059Sjhb if (!TAILQ_EMPTY(&idev->id_configs) && 545185059Sjhb !isa_assign_resources(child)) 546185059Sjhb continue; 547185059Sjhb 548185059Sjhb if (device_probe_and_attach(child) == 0) 549185059Sjhb isa_claim_resources(dev, child); 550185059Sjhb } 551185059Sjhb free(children, M_TEMP); 552185059Sjhb 553185059Sjhb /* 554185059Sjhb * Next, enumerate hinted devices and probe all non-pnp devices so 555185059Sjhb * that they claim their resources first. 556185059Sjhb */ 557185059Sjhb bus_enumerate_hinted_children(dev); 558185059Sjhb if (device_get_children(dev, &children, &nchildren)) 559185059Sjhb return; 56053094Sdfr if (bootverbose) 56153094Sdfr printf("isa_probe_children: probing non-PnP devices\n"); 56250769Sdfr for (i = 0; i < nchildren; i++) { 563185059Sjhb child = children[i]; 564185059Sjhb idev = DEVTOISA(child); 56550769Sdfr 566185059Sjhb if (device_is_attached(child) || 567185059Sjhb !TAILQ_EMPTY(&idev->id_configs)) 56850769Sdfr continue; 56950769Sdfr 57050769Sdfr device_probe_and_attach(child); 57150769Sdfr } 57250769Sdfr 57350769Sdfr /* 57451905Sdfr * Finally assign resource to pnp devices and probe them. 57550769Sdfr */ 57653094Sdfr if (bootverbose) 57753094Sdfr printf("isa_probe_children: probing PnP devices\n"); 57850769Sdfr for (i = 0; i < nchildren; i++) { 579185059Sjhb child = children[i]; 580185059Sjhb idev = DEVTOISA(child); 58150769Sdfr 582185059Sjhb if (device_is_attached(child) || TAILQ_EMPTY(&idev->id_configs)) 58350769Sdfr continue; 58450769Sdfr 58550769Sdfr if (isa_assign_resources(child)) { 58650769Sdfr device_probe_and_attach(child); 587185059Sjhb isa_claim_resources(dev, child); 58850769Sdfr } 58950769Sdfr } 59050769Sdfr 59150769Sdfr free(children, M_TEMP); 59253094Sdfr 59353094Sdfr isa_running = 1; 59450769Sdfr} 59550769Sdfr 59650769Sdfr/* 59747398Sdfr * Add a new child with default ivars. 59847398Sdfr */ 59947398Sdfrstatic device_t 600212413Savgisa_add_child(device_t dev, u_int order, const char *name, int unit) 60147398Sdfr{ 60254073Smdodd device_t child; 60347398Sdfr struct isa_device *idev; 60447398Sdfr 605104179Sphk child = device_add_child_ordered(dev, order, name, unit); 606104179Sphk if (child == NULL) 607104179Sphk return (child); 608104179Sphk 60969781Sdwmalone idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 61047398Sdfr if (!idev) 611139273Simp return (0); 61247398Sdfr 61347398Sdfr resource_list_init(&idev->id_resources); 61450769Sdfr TAILQ_INIT(&idev->id_configs); 615185059Sjhb idev->id_order = order; 61647398Sdfr 617104179Sphk device_set_ivars(child, idev); 61854073Smdodd 619104179Sphk return (child); 62047398Sdfr} 62147398Sdfr 62262059Sdfrstatic int 62362059Sdfrisa_print_all_resources(device_t dev) 62447398Sdfr{ 62547398Sdfr struct isa_device *idev = DEVTOISA(dev); 62647398Sdfr struct resource_list *rl = &idev->id_resources; 62749195Smdodd int retval = 0; 62847398Sdfr 629143785Simp if (STAILQ_FIRST(rl) || device_get_flags(dev)) 63049195Smdodd retval += printf(" at"); 63147398Sdfr 632297199Sjhibbits retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx"); 633297199Sjhibbits retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx"); 634297199Sjhibbits retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 635297199Sjhibbits retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%jd"); 63651052Sdfr if (device_get_flags(dev)) 63751052Sdfr retval += printf(" flags %#x", device_get_flags(dev)); 638159552Smarius#ifdef ISAPNP 639148611Simp if (idev->id_vendorid) 640148611Simp retval += printf(" pnpid %s", pnp_eisaformat(idev->id_vendorid)); 641159552Smarius#endif 64247398Sdfr 643139273Simp return (retval); 64462059Sdfr} 64562059Sdfr 64662059Sdfrstatic int 64762059Sdfrisa_print_child(device_t bus, device_t dev) 64862059Sdfr{ 64962059Sdfr int retval = 0; 65062059Sdfr 65162059Sdfr retval += bus_print_child_header(bus, dev); 65262059Sdfr retval += isa_print_all_resources(dev); 65349195Smdodd retval += bus_print_child_footer(bus, dev); 65449195Smdodd 65549195Smdodd return (retval); 65647398Sdfr} 65747398Sdfr 65862059Sdfrstatic void 65962059Sdfrisa_probe_nomatch(device_t dev, device_t child) 66062059Sdfr{ 66162987Sjhb if (bootverbose) { 66262987Sjhb bus_print_child_header(dev, child); 66362987Sjhb printf(" failed to probe"); 66462059Sdfr isa_print_all_resources(child); 66562987Sjhb bus_print_child_footer(dev, child); 66662987Sjhb } 66762059Sdfr 66862059Sdfr return; 66962059Sdfr} 67062059Sdfr 67147398Sdfrstatic int 67247398Sdfrisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 67347398Sdfr{ 67447398Sdfr struct isa_device* idev = DEVTOISA(dev); 67547398Sdfr struct resource_list *rl = &idev->id_resources; 67647398Sdfr struct resource_list_entry *rle; 67747398Sdfr 67847398Sdfr switch (index) { 67947398Sdfr case ISA_IVAR_PORT_0: 68047398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 68147398Sdfr if (rle) 68247398Sdfr *result = rle->start; 68347398Sdfr else 68447398Sdfr *result = -1; 68547398Sdfr break; 68647398Sdfr 68747398Sdfr case ISA_IVAR_PORT_1: 68847398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 68947398Sdfr if (rle) 69047398Sdfr *result = rle->start; 69147398Sdfr else 69247398Sdfr *result = -1; 69347398Sdfr break; 69447398Sdfr 69547398Sdfr case ISA_IVAR_PORTSIZE_0: 69647398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 69747398Sdfr if (rle) 69847398Sdfr *result = rle->count; 69947398Sdfr else 70047398Sdfr *result = 0; 70147398Sdfr break; 70247398Sdfr 70347398Sdfr case ISA_IVAR_PORTSIZE_1: 70447398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 70547398Sdfr if (rle) 70647398Sdfr *result = rle->count; 70747398Sdfr else 70847398Sdfr *result = 0; 70947398Sdfr break; 71047398Sdfr 71147398Sdfr case ISA_IVAR_MADDR_0: 71247398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 71347398Sdfr if (rle) 71447398Sdfr *result = rle->start; 71547398Sdfr else 71647398Sdfr *result = -1; 71747398Sdfr break; 71847398Sdfr 71947398Sdfr case ISA_IVAR_MADDR_1: 72047398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 72147398Sdfr if (rle) 72247398Sdfr *result = rle->start; 72347398Sdfr else 72447398Sdfr *result = -1; 72547398Sdfr break; 72647398Sdfr 727105139Sjhb case ISA_IVAR_MEMSIZE_0: 72847398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 72947398Sdfr if (rle) 73047398Sdfr *result = rle->count; 73147398Sdfr else 73247398Sdfr *result = 0; 73347398Sdfr break; 73447398Sdfr 735105139Sjhb case ISA_IVAR_MEMSIZE_1: 73647398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 73747398Sdfr if (rle) 73847398Sdfr *result = rle->count; 73947398Sdfr else 74047398Sdfr *result = 0; 74147398Sdfr break; 74247398Sdfr 74347398Sdfr case ISA_IVAR_IRQ_0: 74447398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 0); 74547398Sdfr if (rle) 74647398Sdfr *result = rle->start; 74747398Sdfr else 74847398Sdfr *result = -1; 74947398Sdfr break; 75047398Sdfr 75147398Sdfr case ISA_IVAR_IRQ_1: 75247398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 1); 75347398Sdfr if (rle) 75447398Sdfr *result = rle->start; 75547398Sdfr else 75647398Sdfr *result = -1; 75747398Sdfr break; 75847398Sdfr 75947398Sdfr case ISA_IVAR_DRQ_0: 76047398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 0); 76147398Sdfr if (rle) 76247398Sdfr *result = rle->start; 76347398Sdfr else 76447398Sdfr *result = -1; 76547398Sdfr break; 76647398Sdfr 76747398Sdfr case ISA_IVAR_DRQ_1: 76847398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 1); 76947398Sdfr if (rle) 77047398Sdfr *result = rle->start; 77147398Sdfr else 77247398Sdfr *result = -1; 77347398Sdfr break; 77447398Sdfr 77547613Sdfr case ISA_IVAR_VENDORID: 77647613Sdfr *result = idev->id_vendorid; 77747613Sdfr break; 77847613Sdfr 77947613Sdfr case ISA_IVAR_SERIAL: 78047613Sdfr *result = idev->id_serial; 78147613Sdfr break; 78247613Sdfr 78347613Sdfr case ISA_IVAR_LOGICALID: 78447613Sdfr *result = idev->id_logicalid; 78547613Sdfr break; 78647613Sdfr 78747613Sdfr case ISA_IVAR_COMPATID: 78847613Sdfr *result = idev->id_compatid; 78947613Sdfr break; 79047613Sdfr 79182863Syokota case ISA_IVAR_CONFIGATTR: 79282863Syokota *result = idev->id_config_attr; 79382863Syokota break; 79482863Syokota 795184564Simp case ISA_IVAR_PNP_CSN: 796184564Simp *result = idev->id_pnp_csn; 797184564Simp break; 798184564Simp 799184564Simp case ISA_IVAR_PNP_LDN: 800184564Simp *result = idev->id_pnp_ldn; 801184564Simp break; 802184564Simp 803184564Simp case ISA_IVAR_PNPBIOS_HANDLE: 804184564Simp *result = idev->id_pnpbios_handle; 805184564Simp break; 806184564Simp 80747613Sdfr default: 808139273Simp return (ENOENT); 80947398Sdfr } 81047613Sdfr 811139273Simp return (0); 81247398Sdfr} 81347398Sdfr 81447398Sdfrstatic int 815139273Simpisa_write_ivar(device_t bus, device_t dev, int index, uintptr_t value) 81647398Sdfr{ 81747398Sdfr struct isa_device* idev = DEVTOISA(dev); 81847398Sdfr 81947398Sdfr switch (index) { 82047398Sdfr case ISA_IVAR_PORT_0: 82147398Sdfr case ISA_IVAR_PORT_1: 82247398Sdfr case ISA_IVAR_PORTSIZE_0: 82347398Sdfr case ISA_IVAR_PORTSIZE_1: 82447398Sdfr case ISA_IVAR_MADDR_0: 82547398Sdfr case ISA_IVAR_MADDR_1: 826105139Sjhb case ISA_IVAR_MEMSIZE_0: 827105139Sjhb case ISA_IVAR_MEMSIZE_1: 82847398Sdfr case ISA_IVAR_IRQ_0: 82947398Sdfr case ISA_IVAR_IRQ_1: 83047398Sdfr case ISA_IVAR_DRQ_0: 83147398Sdfr case ISA_IVAR_DRQ_1: 832139273Simp return (EINVAL); 83347398Sdfr 83447613Sdfr case ISA_IVAR_VENDORID: 83547613Sdfr idev->id_vendorid = value; 83647613Sdfr break; 83747613Sdfr 83847613Sdfr case ISA_IVAR_SERIAL: 83947613Sdfr idev->id_serial = value; 84047613Sdfr break; 84147613Sdfr 84247613Sdfr case ISA_IVAR_LOGICALID: 84347613Sdfr idev->id_logicalid = value; 84447613Sdfr break; 84547613Sdfr 84647613Sdfr case ISA_IVAR_COMPATID: 84747613Sdfr idev->id_compatid = value; 84847613Sdfr break; 84947613Sdfr 85082863Syokota case ISA_IVAR_CONFIGATTR: 85182863Syokota idev->id_config_attr = value; 85282863Syokota break; 85382863Syokota 85447398Sdfr default: 85547398Sdfr return (ENOENT); 85647398Sdfr } 85747613Sdfr 85847398Sdfr return (0); 85947398Sdfr} 86047398Sdfr 86150769Sdfr/* 86250769Sdfr * Free any resources which the driver missed or which we were holding for 86350769Sdfr * it (see isa_probe_children). 86450769Sdfr */ 86550769Sdfrstatic void 86650769Sdfrisa_child_detached(device_t dev, device_t child) 86750769Sdfr{ 86850769Sdfr struct isa_device* idev = DEVTOISA(child); 86950769Sdfr 870185059Sjhb if (TAILQ_FIRST(&idev->id_configs)) 871185059Sjhb isa_claim_resources(dev, child); 87250769Sdfr} 87350769Sdfr 87453094Sdfrstatic void 87553094Sdfrisa_driver_added(device_t dev, driver_t *driver) 87653094Sdfr{ 87753094Sdfr device_t *children; 87853094Sdfr int nchildren, i; 87953094Sdfr 88053094Sdfr /* 88153094Sdfr * Don't do anything if drivers are dynamically 88253094Sdfr * added during autoconfiguration (cf. ymf724). 88353094Sdfr * since that would end up calling identify 88453094Sdfr * twice. 88553094Sdfr */ 88653094Sdfr if (!isa_running) 88753094Sdfr return; 88853094Sdfr 88953094Sdfr DEVICE_IDENTIFY(driver, dev); 89053094Sdfr if (device_get_children(dev, &children, &nchildren)) 89153094Sdfr return; 89253094Sdfr 89353094Sdfr for (i = 0; i < nchildren; i++) { 89453094Sdfr device_t child = children[i]; 89553094Sdfr struct isa_device *idev = DEVTOISA(child); 89653094Sdfr struct resource_list *rl = &idev->id_resources; 89753094Sdfr struct resource_list_entry *rle; 89853094Sdfr 89953094Sdfr if (device_get_state(child) != DS_NOTPRESENT) 90053094Sdfr continue; 90162059Sdfr if (!device_is_enabled(child)) 90262059Sdfr continue; 90353094Sdfr 90462059Sdfr /* 90562059Sdfr * Free resources which we were holding on behalf of 90662059Sdfr * the device. 90762059Sdfr */ 908143785Simp STAILQ_FOREACH(rle, &idev->id_resources, link) { 90962059Sdfr if (rle->res) 91062059Sdfr resource_list_release(rl, dev, child, 91162059Sdfr rle->type, 91262059Sdfr rle->rid, 91362059Sdfr rle->res); 91462059Sdfr } 91562059Sdfr 91653094Sdfr if (TAILQ_FIRST(&idev->id_configs)) 91753094Sdfr if (!isa_assign_resources(child)) 91853094Sdfr continue; 91953094Sdfr 92053094Sdfr device_probe_and_attach(child); 92153094Sdfr 922185059Sjhb if (TAILQ_FIRST(&idev->id_configs)) 923185059Sjhb isa_claim_resources(dev, child); 92453094Sdfr } 92553094Sdfr 92653094Sdfr free(children, M_TEMP); 92753094Sdfr} 92853094Sdfr 92947398Sdfrstatic int 93047398Sdfrisa_set_resource(device_t dev, device_t child, int type, int rid, 931294883Sjhibbits rman_res_t start, rman_res_t count) 93247398Sdfr{ 93347398Sdfr struct isa_device* idev = DEVTOISA(child); 93447398Sdfr struct resource_list *rl = &idev->id_resources; 93547398Sdfr 93647398Sdfr if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 93747398Sdfr && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 938139273Simp return (EINVAL); 93950769Sdfr if (rid < 0) 940139273Simp return (EINVAL); 94150769Sdfr if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 942139273Simp return (EINVAL); 94350769Sdfr if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 944139273Simp return (EINVAL); 94550769Sdfr if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 946139273Simp return (EINVAL); 94750769Sdfr if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 948139273Simp return (EINVAL); 94947398Sdfr 95047398Sdfr resource_list_add(rl, type, rid, start, start + count - 1, count); 95147398Sdfr 952139273Simp return (0); 95347398Sdfr} 95447398Sdfr 95569295Smdoddstatic struct resource_list * 95669295Smdoddisa_get_resource_list (device_t dev, device_t child) 95747398Sdfr{ 95847398Sdfr struct isa_device* idev = DEVTOISA(child); 95947398Sdfr struct resource_list *rl = &idev->id_resources; 96047398Sdfr 96169295Smdodd if (!rl) 96269295Smdodd return (NULL); 96347398Sdfr 96469295Smdodd return (rl); 96547398Sdfr} 96647398Sdfr 96750769Sdfrstatic int 968139273Simpisa_add_config(device_t dev, device_t child, int priority, 969139273Simp struct isa_config *config) 97050769Sdfr{ 97150769Sdfr struct isa_device* idev = DEVTOISA(child); 97250769Sdfr struct isa_config_entry *newice, *ice; 97350769Sdfr 97450769Sdfr newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 97550769Sdfr if (!newice) 976139273Simp return (ENOMEM); 97750769Sdfr 97850769Sdfr newice->ice_priority = priority; 97950769Sdfr newice->ice_config = *config; 98050769Sdfr 98150769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 98250769Sdfr if (ice->ice_priority > priority) 98350769Sdfr break; 98450769Sdfr } 98550769Sdfr if (ice) 98650769Sdfr TAILQ_INSERT_BEFORE(ice, newice, ice_link); 98750769Sdfr else 98850769Sdfr TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 98950769Sdfr 990139273Simp return (0); 99150769Sdfr} 99250769Sdfr 99350769Sdfrstatic void 994139273Simpisa_set_config_callback(device_t dev, device_t child, isa_config_cb *fn, 995139273Simp void *arg) 99650769Sdfr{ 99750769Sdfr struct isa_device* idev = DEVTOISA(child); 99850769Sdfr 99950769Sdfr idev->id_config_cb = fn; 100050769Sdfr idev->id_config_arg = arg; 100150769Sdfr} 100250769Sdfr 100350769Sdfrstatic int 100450769Sdfrisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 100550769Sdfr{ 100650769Sdfr struct isa_device* idev = DEVTOISA(child); 100750769Sdfr 100850769Sdfr if (!idev->id_vendorid) 1009139273Simp return (ENOENT); 101050769Sdfr 101182553Smsmith while (ids && ids->ip_id) { 101250769Sdfr /* 101350769Sdfr * Really ought to support >1 compat id per device. 101450769Sdfr */ 101550769Sdfr if (idev->id_logicalid == ids->ip_id 101650769Sdfr || idev->id_compatid == ids->ip_id) { 101750910Sdfr if (ids->ip_desc) 101850910Sdfr device_set_desc(child, ids->ip_desc); 1019139273Simp return (0); 102050769Sdfr } 102150769Sdfr ids++; 102250769Sdfr } 102350769Sdfr 1024139273Simp return (ENXIO); 102550769Sdfr} 102650769Sdfr 1027148611Simpstatic int 1028148611Simpisa_child_pnpinfo_str(device_t bus, device_t child, char *buf, 1029148611Simp size_t buflen) 1030148611Simp{ 1031159552Smarius#ifdef ISAPNP 1032148611Simp struct isa_device *idev = DEVTOISA(child); 1033148611Simp 1034148611Simp if (idev->id_vendorid) 1035148611Simp snprintf(buf, buflen, "pnpid=%s", 1036148611Simp pnp_eisaformat(idev->id_vendorid)); 1037159552Smarius#endif 1038148611Simp return (0); 1039148611Simp} 1040148611Simp 1041148611Simpstatic int 1042148611Simpisa_child_location_str(device_t bus, device_t child, char *buf, 1043148611Simp size_t buflen) 1044148611Simp{ 1045184564Simp#if 0 1046184564Simp /* id_pnphandle isn't there yet */ 1047184564Simp struct isa_device *idev = DEVTOISA(child); 1048184564Simp 1049184564Simp if (idev->id_vendorid) 1050184564Simp snprintf(buf, buflen, "pnphandle=%d", idev->id_pnphandle); 1051184564Simp#endif 1052148611Simp /* Nothing here yet */ 1053148611Simp *buf = '\0'; 1054148611Simp return (0); 1055148611Simp} 1056148611Simp 105747398Sdfrstatic device_method_t isa_methods[] = { 105847398Sdfr /* Device interface */ 105947398Sdfr DEVMETHOD(device_probe, isa_probe), 106047398Sdfr DEVMETHOD(device_attach, isa_attach), 106147398Sdfr DEVMETHOD(device_detach, bus_generic_detach), 106247398Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 106347398Sdfr DEVMETHOD(device_suspend, bus_generic_suspend), 106447398Sdfr DEVMETHOD(device_resume, bus_generic_resume), 106547398Sdfr 106647398Sdfr /* Bus interface */ 106747398Sdfr DEVMETHOD(bus_add_child, isa_add_child), 106847398Sdfr DEVMETHOD(bus_print_child, isa_print_child), 106962059Sdfr DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 107047398Sdfr DEVMETHOD(bus_read_ivar, isa_read_ivar), 107147398Sdfr DEVMETHOD(bus_write_ivar, isa_write_ivar), 107250769Sdfr DEVMETHOD(bus_child_detached, isa_child_detached), 107353094Sdfr DEVMETHOD(bus_driver_added, isa_driver_added), 1074221526Sjhb DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 1075221526Sjhb DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 107669295Smdodd 107769295Smdodd DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 107847398Sdfr DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 107947398Sdfr DEVMETHOD(bus_release_resource, isa_release_resource), 108069295Smdodd DEVMETHOD(bus_set_resource, isa_set_resource), 108169295Smdodd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 108269295Smdodd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 108347398Sdfr DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 108447398Sdfr DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1085148611Simp DEVMETHOD(bus_child_pnpinfo_str, isa_child_pnpinfo_str), 1086148611Simp DEVMETHOD(bus_child_location_str, isa_child_location_str), 1087185059Sjhb DEVMETHOD(bus_hinted_child, isa_hinted_child), 1088185059Sjhb DEVMETHOD(bus_hint_device_unit, isa_hint_device_unit), 108947398Sdfr 109047398Sdfr /* ISA interface */ 109150769Sdfr DEVMETHOD(isa_add_config, isa_add_config), 109250769Sdfr DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 109350769Sdfr DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 109447398Sdfr 109547398Sdfr { 0, 0 } 109647398Sdfr}; 109747398Sdfr 1098185059SjhbDEFINE_CLASS_0(isa, isa_driver, isa_methods, 0); 109947398Sdfr 1100139279Simpdevclass_t isa_devclass; 1101139279Simp 110247398Sdfr/* 1103139279Simp * ISA can be attached to a PCI-ISA bridge, or other locations on some 1104139279Simp * platforms. 110547398Sdfr */ 110647398SdfrDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 110769942SmsmithDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 1108113498SmdoddMODULE_VERSION(isa, 1); 1109117337Sjhb 1110117337Sjhb/* 1111117337Sjhb * Code common to ISA bridges. 1112117337Sjhb */ 1113117337Sjhb 1114117337Sjhbdevclass_t isab_devclass; 1115117337Sjhb 1116117337Sjhbint 1117117337Sjhbisab_attach(device_t dev) 1118117337Sjhb{ 1119117337Sjhb device_t child; 1120117337Sjhb 1121117337Sjhb child = device_add_child(dev, "isa", 0); 1122117337Sjhb if (child != NULL) 1123117337Sjhb return (bus_generic_attach(dev)); 1124117337Sjhb return (ENXIO); 1125117337Sjhb} 1126