isa_common.c revision 168816
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 168816 2007-04-17 15:14:23Z jhb $"); 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 47050769Sdfr/* 47183051Syokota * Return non-zero if the device has a single configuration, that is, 47283051Syokota * a fixed set of resoruces. 47383051Syokota */ 47483051Syokotastatic int 47583051Syokotaisa_has_single_config(device_t dev) 47683051Syokota{ 47783051Syokota struct isa_device *idev = DEVTOISA(dev); 47883051Syokota struct isa_config_entry *ice; 479139273Simp uint32_t mask; 48083051Syokota int i; 48183051Syokota 48283051Syokota ice = TAILQ_FIRST(&idev->id_configs); 48383051Syokota if (TAILQ_NEXT(ice, ice_link)) 484139273Simp return (0); 48583051Syokota 48683051Syokota for (i = 0; i < ice->ice_config.ic_nmem; ++i) { 48783051Syokota if (ice->ice_config.ic_mem[i].ir_size == 0) 48883051Syokota continue; 48983051Syokota if (ice->ice_config.ic_mem[i].ir_end != 49083051Syokota ice->ice_config.ic_mem[i].ir_start + 49183051Syokota ice->ice_config.ic_mem[i].ir_size - 1) 492139273Simp return (0); 49383051Syokota } 49483051Syokota for (i = 0; i < ice->ice_config.ic_nport; ++i) { 49583051Syokota if (ice->ice_config.ic_port[i].ir_size == 0) 49683051Syokota continue; 49783051Syokota if (ice->ice_config.ic_port[i].ir_end != 49883051Syokota ice->ice_config.ic_port[i].ir_start + 49983051Syokota ice->ice_config.ic_port[i].ir_size - 1) 500139273Simp return (0); 50183051Syokota } 50283051Syokota for (i = 0; i < ice->ice_config.ic_nirq; ++i) { 50383051Syokota mask = ice->ice_config.ic_irqmask[i]; 50483051Syokota if (mask == 0) 50583051Syokota continue; 50683051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 507139273Simp return (0); 50883051Syokota } 50983051Syokota for (i = 0; i < ice->ice_config.ic_ndrq; ++i) { 51083051Syokota mask = ice->ice_config.ic_drqmask[i]; 51183051Syokota if (mask == 0) 51283051Syokota continue; 51383051Syokota if (find_next_bit(mask, find_first_bit(mask)) != -1) 514139273Simp return (0); 51583051Syokota } 516139273Simp return (1); 51783051Syokota} 51883051Syokota 51983051Syokota/* 52050769Sdfr * Called after other devices have initialised to probe for isa devices. 52150769Sdfr */ 52250769Sdfrvoid 52350769Sdfrisa_probe_children(device_t dev) 52450769Sdfr{ 52550769Sdfr device_t *children; 52681401Sjulian struct isa_config *cfg; 52750769Sdfr int nchildren, i; 52850769Sdfr 52953094Sdfr /* 53053094Sdfr * Create all the children by calling driver's identify methods. 53153094Sdfr */ 53253094Sdfr bus_generic_probe(dev); 53353094Sdfr 53450769Sdfr if (device_get_children(dev, &children, &nchildren)) 53550769Sdfr return; 53650769Sdfr 53750769Sdfr /* 53851905Sdfr * First disable all pnp devices so that they don't get 53951905Sdfr * matched by legacy probes. 54051905Sdfr */ 54153094Sdfr if (bootverbose) 54253094Sdfr printf("isa_probe_children: disabling PnP devices\n"); 54381401Sjulian 54481401Sjulian cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 54581401Sjulian if (cfg == NULL) { 54681401Sjulian free(children, M_TEMP); 54781401Sjulian return; 54881401Sjulian } 54981401Sjulian 55051905Sdfr for (i = 0; i < nchildren; i++) { 55151905Sdfr device_t child = children[i]; 55251905Sdfr struct isa_device *idev = DEVTOISA(child); 55351905Sdfr 55481401Sjulian bzero(cfg, sizeof(*cfg)); 55551905Sdfr if (idev->id_config_cb) 55681401Sjulian idev->id_config_cb(idev->id_config_arg, cfg, 0); 55751905Sdfr } 55851905Sdfr 55981401Sjulian free(cfg, M_TEMP); 56081401Sjulian 56151905Sdfr /* 56251905Sdfr * Next probe all non-pnp devices so that they claim their 56350769Sdfr * resources first. 56450769Sdfr */ 56553094Sdfr if (bootverbose) 56653094Sdfr printf("isa_probe_children: probing non-PnP devices\n"); 56750769Sdfr for (i = 0; i < nchildren; i++) { 56850769Sdfr device_t child = children[i]; 56950769Sdfr struct isa_device *idev = DEVTOISA(child); 57050769Sdfr 57150769Sdfr if (TAILQ_FIRST(&idev->id_configs)) 57250769Sdfr continue; 57350769Sdfr 57450769Sdfr device_probe_and_attach(child); 57550769Sdfr } 57650769Sdfr 57750769Sdfr /* 57851905Sdfr * Finally assign resource to pnp devices and probe them. 57950769Sdfr */ 58053094Sdfr if (bootverbose) 58153094Sdfr printf("isa_probe_children: probing PnP devices\n"); 58250769Sdfr for (i = 0; i < nchildren; i++) { 58350769Sdfr device_t child = children[i]; 58450769Sdfr struct isa_device* idev = DEVTOISA(child); 58550769Sdfr 58650769Sdfr if (!TAILQ_FIRST(&idev->id_configs)) 58750769Sdfr continue; 58850769Sdfr 58950769Sdfr if (isa_assign_resources(child)) { 59052174Sdfr struct resource_list *rl = &idev->id_resources; 59150769Sdfr struct resource_list_entry *rle; 59250769Sdfr 59350769Sdfr device_probe_and_attach(child); 59450769Sdfr 59550769Sdfr /* 59650769Sdfr * Claim any unallocated resources to keep other 59750769Sdfr * devices from using them. 59850769Sdfr */ 599143785Simp STAILQ_FOREACH(rle, rl, link) { 60050769Sdfr if (!rle->res) { 60150769Sdfr int rid = rle->rid; 60252174Sdfr resource_list_alloc(rl, dev, child, 60350769Sdfr rle->type, 60450769Sdfr &rid, 60562059Sdfr 0, ~0, 1, 0); 60650769Sdfr } 60750769Sdfr } 60850769Sdfr } 60950769Sdfr } 61050769Sdfr 61150769Sdfr free(children, M_TEMP); 61253094Sdfr 61353094Sdfr isa_running = 1; 61450769Sdfr} 61550769Sdfr 61650769Sdfr/* 61747398Sdfr * Add a new child with default ivars. 61847398Sdfr */ 61947398Sdfrstatic device_t 62047578Sdfrisa_add_child(device_t dev, int order, const char *name, int unit) 62147398Sdfr{ 62254073Smdodd device_t child; 62347398Sdfr struct isa_device *idev; 62447398Sdfr 625104179Sphk child = device_add_child_ordered(dev, order, name, unit); 626104179Sphk if (child == NULL) 627104179Sphk return (child); 628104179Sphk 62969781Sdwmalone idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 63047398Sdfr if (!idev) 631139273Simp return (0); 63247398Sdfr 63347398Sdfr resource_list_init(&idev->id_resources); 63450769Sdfr TAILQ_INIT(&idev->id_configs); 63547398Sdfr 636104179Sphk device_set_ivars(child, idev); 63754073Smdodd 638104179Sphk return (child); 63947398Sdfr} 64047398Sdfr 64162059Sdfrstatic int 64262059Sdfrisa_print_all_resources(device_t dev) 64347398Sdfr{ 64447398Sdfr struct isa_device *idev = DEVTOISA(dev); 64547398Sdfr struct resource_list *rl = &idev->id_resources; 64649195Smdodd int retval = 0; 64747398Sdfr 648143785Simp if (STAILQ_FIRST(rl) || device_get_flags(dev)) 64949195Smdodd retval += printf(" at"); 65047398Sdfr 65188376Stmm retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 65288376Stmm retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 65388376Stmm retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 65488376Stmm retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld"); 65551052Sdfr if (device_get_flags(dev)) 65651052Sdfr retval += printf(" flags %#x", device_get_flags(dev)); 657159552Smarius#ifdef ISAPNP 658148611Simp if (idev->id_vendorid) 659148611Simp retval += printf(" pnpid %s", pnp_eisaformat(idev->id_vendorid)); 660159552Smarius#endif 66147398Sdfr 662139273Simp return (retval); 66362059Sdfr} 66462059Sdfr 66562059Sdfrstatic int 66662059Sdfrisa_print_child(device_t bus, device_t dev) 66762059Sdfr{ 66862059Sdfr int retval = 0; 66962059Sdfr 67062059Sdfr retval += bus_print_child_header(bus, dev); 67162059Sdfr retval += isa_print_all_resources(dev); 67249195Smdodd retval += bus_print_child_footer(bus, dev); 67349195Smdodd 67449195Smdodd return (retval); 67547398Sdfr} 67647398Sdfr 67762059Sdfrstatic void 67862059Sdfrisa_probe_nomatch(device_t dev, device_t child) 67962059Sdfr{ 68062987Sjhb if (bootverbose) { 68162987Sjhb bus_print_child_header(dev, child); 68262987Sjhb printf(" failed to probe"); 68362059Sdfr isa_print_all_resources(child); 68462987Sjhb bus_print_child_footer(dev, child); 68562987Sjhb } 68662059Sdfr 68762059Sdfr return; 68862059Sdfr} 68962059Sdfr 69047398Sdfrstatic int 69147398Sdfrisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 69247398Sdfr{ 69347398Sdfr struct isa_device* idev = DEVTOISA(dev); 69447398Sdfr struct resource_list *rl = &idev->id_resources; 69547398Sdfr struct resource_list_entry *rle; 69647398Sdfr 69747398Sdfr switch (index) { 69847398Sdfr case ISA_IVAR_PORT_0: 69947398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 70047398Sdfr if (rle) 70147398Sdfr *result = rle->start; 70247398Sdfr else 70347398Sdfr *result = -1; 70447398Sdfr break; 70547398Sdfr 70647398Sdfr case ISA_IVAR_PORT_1: 70747398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 70847398Sdfr if (rle) 70947398Sdfr *result = rle->start; 71047398Sdfr else 71147398Sdfr *result = -1; 71247398Sdfr break; 71347398Sdfr 71447398Sdfr case ISA_IVAR_PORTSIZE_0: 71547398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 71647398Sdfr if (rle) 71747398Sdfr *result = rle->count; 71847398Sdfr else 71947398Sdfr *result = 0; 72047398Sdfr break; 72147398Sdfr 72247398Sdfr case ISA_IVAR_PORTSIZE_1: 72347398Sdfr rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 72447398Sdfr if (rle) 72547398Sdfr *result = rle->count; 72647398Sdfr else 72747398Sdfr *result = 0; 72847398Sdfr break; 72947398Sdfr 73047398Sdfr case ISA_IVAR_MADDR_0: 73147398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 73247398Sdfr if (rle) 73347398Sdfr *result = rle->start; 73447398Sdfr else 73547398Sdfr *result = -1; 73647398Sdfr break; 73747398Sdfr 73847398Sdfr case ISA_IVAR_MADDR_1: 73947398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 74047398Sdfr if (rle) 74147398Sdfr *result = rle->start; 74247398Sdfr else 74347398Sdfr *result = -1; 74447398Sdfr break; 74547398Sdfr 746105139Sjhb case ISA_IVAR_MEMSIZE_0: 74747398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 74847398Sdfr if (rle) 74947398Sdfr *result = rle->count; 75047398Sdfr else 75147398Sdfr *result = 0; 75247398Sdfr break; 75347398Sdfr 754105139Sjhb case ISA_IVAR_MEMSIZE_1: 75547398Sdfr rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 75647398Sdfr if (rle) 75747398Sdfr *result = rle->count; 75847398Sdfr else 75947398Sdfr *result = 0; 76047398Sdfr break; 76147398Sdfr 76247398Sdfr case ISA_IVAR_IRQ_0: 76347398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 0); 76447398Sdfr if (rle) 76547398Sdfr *result = rle->start; 76647398Sdfr else 76747398Sdfr *result = -1; 76847398Sdfr break; 76947398Sdfr 77047398Sdfr case ISA_IVAR_IRQ_1: 77147398Sdfr rle = resource_list_find(rl, SYS_RES_IRQ, 1); 77247398Sdfr if (rle) 77347398Sdfr *result = rle->start; 77447398Sdfr else 77547398Sdfr *result = -1; 77647398Sdfr break; 77747398Sdfr 77847398Sdfr case ISA_IVAR_DRQ_0: 77947398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 0); 78047398Sdfr if (rle) 78147398Sdfr *result = rle->start; 78247398Sdfr else 78347398Sdfr *result = -1; 78447398Sdfr break; 78547398Sdfr 78647398Sdfr case ISA_IVAR_DRQ_1: 78747398Sdfr rle = resource_list_find(rl, SYS_RES_DRQ, 1); 78847398Sdfr if (rle) 78947398Sdfr *result = rle->start; 79047398Sdfr else 79147398Sdfr *result = -1; 79247398Sdfr break; 79347398Sdfr 79447613Sdfr case ISA_IVAR_VENDORID: 79547613Sdfr *result = idev->id_vendorid; 79647613Sdfr break; 79747613Sdfr 79847613Sdfr case ISA_IVAR_SERIAL: 79947613Sdfr *result = idev->id_serial; 80047613Sdfr break; 80147613Sdfr 80247613Sdfr case ISA_IVAR_LOGICALID: 80347613Sdfr *result = idev->id_logicalid; 80447613Sdfr break; 80547613Sdfr 80647613Sdfr case ISA_IVAR_COMPATID: 80747613Sdfr *result = idev->id_compatid; 80847613Sdfr break; 80947613Sdfr 81082863Syokota case ISA_IVAR_CONFIGATTR: 81182863Syokota *result = idev->id_config_attr; 81282863Syokota break; 81382863Syokota 81447613Sdfr default: 815139273Simp return (ENOENT); 81647398Sdfr } 81747613Sdfr 818139273Simp return (0); 81947398Sdfr} 82047398Sdfr 82147398Sdfrstatic int 822139273Simpisa_write_ivar(device_t bus, device_t dev, int index, uintptr_t value) 82347398Sdfr{ 82447398Sdfr struct isa_device* idev = DEVTOISA(dev); 82547398Sdfr 82647398Sdfr switch (index) { 82747398Sdfr case ISA_IVAR_PORT_0: 82847398Sdfr case ISA_IVAR_PORT_1: 82947398Sdfr case ISA_IVAR_PORTSIZE_0: 83047398Sdfr case ISA_IVAR_PORTSIZE_1: 83147398Sdfr case ISA_IVAR_MADDR_0: 83247398Sdfr case ISA_IVAR_MADDR_1: 833105139Sjhb case ISA_IVAR_MEMSIZE_0: 834105139Sjhb case ISA_IVAR_MEMSIZE_1: 83547398Sdfr case ISA_IVAR_IRQ_0: 83647398Sdfr case ISA_IVAR_IRQ_1: 83747398Sdfr case ISA_IVAR_DRQ_0: 83847398Sdfr case ISA_IVAR_DRQ_1: 839139273Simp return (EINVAL); 84047398Sdfr 84147613Sdfr case ISA_IVAR_VENDORID: 84247613Sdfr idev->id_vendorid = value; 84347613Sdfr break; 84447613Sdfr 84547613Sdfr case ISA_IVAR_SERIAL: 84647613Sdfr idev->id_serial = value; 84747613Sdfr break; 84847613Sdfr 84947613Sdfr case ISA_IVAR_LOGICALID: 85047613Sdfr idev->id_logicalid = value; 85147613Sdfr break; 85247613Sdfr 85347613Sdfr case ISA_IVAR_COMPATID: 85447613Sdfr idev->id_compatid = value; 85547613Sdfr break; 85647613Sdfr 85782863Syokota case ISA_IVAR_CONFIGATTR: 85882863Syokota idev->id_config_attr = value; 85982863Syokota break; 86082863Syokota 86147398Sdfr default: 86247398Sdfr return (ENOENT); 86347398Sdfr } 86447613Sdfr 86547398Sdfr return (0); 86647398Sdfr} 86747398Sdfr 86850769Sdfr/* 86950769Sdfr * Free any resources which the driver missed or which we were holding for 87050769Sdfr * it (see isa_probe_children). 87150769Sdfr */ 87250769Sdfrstatic void 87350769Sdfrisa_child_detached(device_t dev, device_t child) 87450769Sdfr{ 87550769Sdfr struct isa_device* idev = DEVTOISA(child); 87652174Sdfr struct resource_list *rl = &idev->id_resources; 87750769Sdfr struct resource_list_entry *rle; 87850769Sdfr 87962059Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 88062059Sdfr /* 88162059Sdfr * Claim any unallocated resources to keep other 88262059Sdfr * devices from using them. 88362059Sdfr */ 884143785Simp STAILQ_FOREACH(rle, rl, link) { 88562059Sdfr if (!rle->res) { 88662059Sdfr int rid = rle->rid; 88762059Sdfr resource_list_alloc(rl, dev, child, 88862059Sdfr rle->type, 88962059Sdfr &rid, 0, ~0, 1, 0); 89062059Sdfr } 89162059Sdfr } 89250769Sdfr } 89350769Sdfr} 89450769Sdfr 89553094Sdfrstatic void 89653094Sdfrisa_driver_added(device_t dev, driver_t *driver) 89753094Sdfr{ 89853094Sdfr device_t *children; 89953094Sdfr int nchildren, i; 90053094Sdfr 90153094Sdfr /* 90253094Sdfr * Don't do anything if drivers are dynamically 90353094Sdfr * added during autoconfiguration (cf. ymf724). 90453094Sdfr * since that would end up calling identify 90553094Sdfr * twice. 90653094Sdfr */ 90753094Sdfr if (!isa_running) 90853094Sdfr return; 90953094Sdfr 91053094Sdfr DEVICE_IDENTIFY(driver, dev); 91153094Sdfr if (device_get_children(dev, &children, &nchildren)) 91253094Sdfr return; 91353094Sdfr 91453094Sdfr for (i = 0; i < nchildren; i++) { 91553094Sdfr device_t child = children[i]; 91653094Sdfr struct isa_device *idev = DEVTOISA(child); 91753094Sdfr struct resource_list *rl = &idev->id_resources; 91853094Sdfr struct resource_list_entry *rle; 91953094Sdfr 92053094Sdfr if (device_get_state(child) != DS_NOTPRESENT) 92153094Sdfr continue; 92262059Sdfr if (!device_is_enabled(child)) 92362059Sdfr continue; 92453094Sdfr 92562059Sdfr /* 92662059Sdfr * Free resources which we were holding on behalf of 92762059Sdfr * the device. 92862059Sdfr */ 929143785Simp STAILQ_FOREACH(rle, &idev->id_resources, link) { 93062059Sdfr if (rle->res) 93162059Sdfr resource_list_release(rl, dev, child, 93262059Sdfr rle->type, 93362059Sdfr rle->rid, 93462059Sdfr rle->res); 93562059Sdfr } 93662059Sdfr 93753094Sdfr if (TAILQ_FIRST(&idev->id_configs)) 93853094Sdfr if (!isa_assign_resources(child)) 93953094Sdfr continue; 94053094Sdfr 94153094Sdfr device_probe_and_attach(child); 94253094Sdfr 94353094Sdfr if (TAILQ_FIRST(&idev->id_configs)) { 94453094Sdfr /* 94553094Sdfr * Claim any unallocated resources to keep other 94653094Sdfr * devices from using them. 94753094Sdfr */ 948143785Simp STAILQ_FOREACH(rle, rl, link) { 94953094Sdfr if (!rle->res) { 95053094Sdfr int rid = rle->rid; 95153094Sdfr resource_list_alloc(rl, dev, child, 95253094Sdfr rle->type, 95362059Sdfr &rid, 0, ~0, 1, 0); 95453094Sdfr } 95553094Sdfr } 95653094Sdfr } 95753094Sdfr } 95853094Sdfr 95953094Sdfr free(children, M_TEMP); 96053094Sdfr} 96153094Sdfr 96247398Sdfrstatic int 96347398Sdfrisa_set_resource(device_t dev, device_t child, int type, int rid, 964139273Simp u_long start, u_long count) 96547398Sdfr{ 96647398Sdfr struct isa_device* idev = DEVTOISA(child); 96747398Sdfr struct resource_list *rl = &idev->id_resources; 96847398Sdfr 96947398Sdfr if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 97047398Sdfr && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 971139273Simp return (EINVAL); 97250769Sdfr if (rid < 0) 973139273Simp return (EINVAL); 97450769Sdfr if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 975139273Simp return (EINVAL); 97650769Sdfr if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 977139273Simp return (EINVAL); 97850769Sdfr if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 979139273Simp return (EINVAL); 98050769Sdfr if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 981139273Simp return (EINVAL); 98247398Sdfr 98347398Sdfr resource_list_add(rl, type, rid, start, start + count - 1, count); 98447398Sdfr 985139273Simp return (0); 98647398Sdfr} 98747398Sdfr 98869295Smdoddstatic struct resource_list * 98969295Smdoddisa_get_resource_list (device_t dev, device_t child) 99047398Sdfr{ 99147398Sdfr struct isa_device* idev = DEVTOISA(child); 99247398Sdfr struct resource_list *rl = &idev->id_resources; 99347398Sdfr 99469295Smdodd if (!rl) 99569295Smdodd return (NULL); 99647398Sdfr 99769295Smdodd return (rl); 99847398Sdfr} 99947398Sdfr 100050769Sdfrstatic int 1001139273Simpisa_add_config(device_t dev, device_t child, int priority, 1002139273Simp struct isa_config *config) 100350769Sdfr{ 100450769Sdfr struct isa_device* idev = DEVTOISA(child); 100550769Sdfr struct isa_config_entry *newice, *ice; 100650769Sdfr 100750769Sdfr newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 100850769Sdfr if (!newice) 1009139273Simp return (ENOMEM); 101050769Sdfr 101150769Sdfr newice->ice_priority = priority; 101250769Sdfr newice->ice_config = *config; 101350769Sdfr 101450769Sdfr TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 101550769Sdfr if (ice->ice_priority > priority) 101650769Sdfr break; 101750769Sdfr } 101850769Sdfr if (ice) 101950769Sdfr TAILQ_INSERT_BEFORE(ice, newice, ice_link); 102050769Sdfr else 102150769Sdfr TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 102250769Sdfr 102383051Syokota if (isa_has_single_config(child)) 102483051Syokota idev->id_config_attr &= ~ISACFGATTR_MULTI; 102583051Syokota else 102683051Syokota idev->id_config_attr |= ISACFGATTR_MULTI; 102783051Syokota 1028139273Simp return (0); 102950769Sdfr} 103050769Sdfr 103150769Sdfrstatic void 1032139273Simpisa_set_config_callback(device_t dev, device_t child, isa_config_cb *fn, 1033139273Simp void *arg) 103450769Sdfr{ 103550769Sdfr struct isa_device* idev = DEVTOISA(child); 103650769Sdfr 103750769Sdfr idev->id_config_cb = fn; 103850769Sdfr idev->id_config_arg = arg; 103950769Sdfr} 104050769Sdfr 104150769Sdfrstatic int 104250769Sdfrisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 104350769Sdfr{ 104450769Sdfr struct isa_device* idev = DEVTOISA(child); 104550769Sdfr 104650769Sdfr if (!idev->id_vendorid) 1047139273Simp return (ENOENT); 104850769Sdfr 104982553Smsmith while (ids && ids->ip_id) { 105050769Sdfr /* 105150769Sdfr * Really ought to support >1 compat id per device. 105250769Sdfr */ 105350769Sdfr if (idev->id_logicalid == ids->ip_id 105450769Sdfr || idev->id_compatid == ids->ip_id) { 105550910Sdfr if (ids->ip_desc) 105650910Sdfr device_set_desc(child, ids->ip_desc); 1057139273Simp return (0); 105850769Sdfr } 105950769Sdfr ids++; 106050769Sdfr } 106150769Sdfr 1062139273Simp return (ENXIO); 106350769Sdfr} 106450769Sdfr 1065148611Simpstatic int 1066148611Simpisa_child_pnpinfo_str(device_t bus, device_t child, char *buf, 1067148611Simp size_t buflen) 1068148611Simp{ 1069159552Smarius#ifdef ISAPNP 1070148611Simp struct isa_device *idev = DEVTOISA(child); 1071148611Simp 1072148611Simp if (idev->id_vendorid) 1073148611Simp snprintf(buf, buflen, "pnpid=%s", 1074148611Simp pnp_eisaformat(idev->id_vendorid)); 1075159552Smarius#endif 1076148611Simp return (0); 1077148611Simp} 1078148611Simp 1079148611Simpstatic int 1080148611Simpisa_child_location_str(device_t bus, device_t child, char *buf, 1081148611Simp size_t buflen) 1082148611Simp{ 1083148611Simp /* Nothing here yet */ 1084148611Simp *buf = '\0'; 1085148611Simp return (0); 1086148611Simp} 1087148611Simp 108847398Sdfrstatic device_method_t isa_methods[] = { 108947398Sdfr /* Device interface */ 109047398Sdfr DEVMETHOD(device_probe, isa_probe), 109147398Sdfr DEVMETHOD(device_attach, isa_attach), 109247398Sdfr DEVMETHOD(device_detach, bus_generic_detach), 109347398Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 109447398Sdfr DEVMETHOD(device_suspend, bus_generic_suspend), 109547398Sdfr DEVMETHOD(device_resume, bus_generic_resume), 109647398Sdfr 109747398Sdfr /* Bus interface */ 109847398Sdfr DEVMETHOD(bus_add_child, isa_add_child), 109947398Sdfr DEVMETHOD(bus_print_child, isa_print_child), 110062059Sdfr DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 110147398Sdfr DEVMETHOD(bus_read_ivar, isa_read_ivar), 110247398Sdfr DEVMETHOD(bus_write_ivar, isa_write_ivar), 110350769Sdfr DEVMETHOD(bus_child_detached, isa_child_detached), 110453094Sdfr DEVMETHOD(bus_driver_added, isa_driver_added), 110569295Smdodd DEVMETHOD(bus_setup_intr, isa_setup_intr), 110669295Smdodd DEVMETHOD(bus_teardown_intr, isa_teardown_intr), 110769295Smdodd 110869295Smdodd DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 110947398Sdfr DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 111047398Sdfr DEVMETHOD(bus_release_resource, isa_release_resource), 111169295Smdodd DEVMETHOD(bus_set_resource, isa_set_resource), 111269295Smdodd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 111369295Smdodd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 111447398Sdfr DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 111547398Sdfr DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1116148611Simp DEVMETHOD(bus_child_pnpinfo_str, isa_child_pnpinfo_str), 1117148611Simp DEVMETHOD(bus_child_location_str, isa_child_location_str), 111847398Sdfr 111947398Sdfr /* ISA interface */ 112050769Sdfr DEVMETHOD(isa_add_config, isa_add_config), 112150769Sdfr DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 112250769Sdfr DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 112347398Sdfr 112447398Sdfr { 0, 0 } 112547398Sdfr}; 112647398Sdfr 1127139279Simpdriver_t isa_driver = { 112847398Sdfr "isa", 112947398Sdfr isa_methods, 113047398Sdfr 1, /* no softc */ 113147398Sdfr}; 113247398Sdfr 1133139279Simpdevclass_t isa_devclass; 1134139279Simp 113547398Sdfr/* 1136139279Simp * ISA can be attached to a PCI-ISA bridge, or other locations on some 1137139279Simp * platforms. 113847398Sdfr */ 113947398SdfrDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 114069942SmsmithDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 1141113498SmdoddMODULE_VERSION(isa, 1); 1142117337Sjhb 1143117337Sjhb/* 1144117337Sjhb * Code common to ISA bridges. 1145117337Sjhb */ 1146117337Sjhb 1147117337Sjhbdevclass_t isab_devclass; 1148117337Sjhb 1149117337Sjhbint 1150117337Sjhbisab_attach(device_t dev) 1151117337Sjhb{ 1152117337Sjhb device_t child; 1153117337Sjhb 1154117337Sjhb child = device_add_child(dev, "isa", 0); 1155117337Sjhb if (child != NULL) 1156117337Sjhb return (bus_generic_attach(dev)); 1157117337Sjhb return (ENXIO); 1158117337Sjhb} 1159