isa_common.c revision 182103
1264790Sbapt/*- 2264790Sbapt * Copyright (c) 1999 Doug Rabson 3272955Srodrigc * All rights reserved. 4264790Sbapt * 5264790Sbapt * Redistribution and use in source and binary forms, with or without 6264790Sbapt * modification, are permitted provided that the following conditions 7264790Sbapt * are met: 8264790Sbapt * 1. Redistributions of source code must retain the above copyright 9264790Sbapt * notice, this list of conditions and the following disclaimer. 10264790Sbapt * 2. Redistributions in binary form must reproduce the above copyright 11264790Sbapt * notice, this list of conditions and the following disclaimer in the 12264790Sbapt * documentation and/or other materials provided with the distribution. 13264790Sbapt * 14264790Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15264790Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16264790Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17264790Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18264790Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19264790Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20264790Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21264790Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22264790Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23264790Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24264790Sbapt * SUCH DAMAGE. 25264790Sbapt */ 26264790Sbapt/* 27264790Sbapt * Modifications for Intel architecture by Garrett A. Wollman. 28264790Sbapt * Copyright 1998 Massachusetts Institute of Technology 29264790Sbapt * 30264790Sbapt * Permission to use, copy, modify, and distribute this software and 31264790Sbapt * its documentation for any purpose and without fee is hereby 32264790Sbapt * granted, provided that both the above copyright notice and this 33264790Sbapt * permission notice appear in all copies, that both the above 34264790Sbapt * copyright notice and this permission notice appear in all 35264790Sbapt * supporting documentation, and that the name of M.I.T. not be used 36264790Sbapt * in advertising or publicity pertaining to distribution of the 37264790Sbapt * software without specific, written prior permission. M.I.T. makes 38264790Sbapt * no representations about the suitability of this software for any 39264790Sbapt * purpose. It is provided "as is" without express or implied 40264790Sbapt * warranty. 41264790Sbapt * 42264790Sbapt * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 43264790Sbapt * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 44264790Sbapt * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 45264790Sbapt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 46264790Sbapt * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47264790Sbapt * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48264790Sbapt * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 49264790Sbapt * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 50264790Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 51264790Sbapt * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 52264790Sbapt * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53264790Sbapt * SUCH DAMAGE. 54264790Sbapt */ 55264790Sbapt 56264790Sbapt/* 57264790Sbapt * Parts of the ISA bus implementation common to all architectures. 58264790Sbapt */ 59264790Sbapt 60264790Sbapt#include <sys/cdefs.h> 61264790Sbapt__FBSDID("$FreeBSD: head/sys/isa/isa_common.c 182103 2008-08-24 07:40:14Z imp $"); 62264790Sbapt 63264790Sbapt#include "opt_isa.h" 64264790Sbapt 65264790Sbapt#include <sys/param.h> 66264790Sbapt#include <sys/systm.h> 67264790Sbapt#include <sys/kernel.h> 68264790Sbapt#include <sys/bus.h> 69264790Sbapt#include <sys/malloc.h> 70264790Sbapt#include <sys/module.h> 71264790Sbapt#include <machine/bus.h> 72264790Sbapt#include <sys/rman.h> 73264790Sbapt 74264790Sbapt#include <machine/resource.h> 75264790Sbapt 76264790Sbapt#include <isa/isavar.h> 77264790Sbapt#include <isa/isa_common.h> 78264790Sbapt 79264790Sbaptstatic int isa_print_child(device_t bus, device_t dev); 80264790Sbapt 81264790Sbaptstatic MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); 82264790Sbapt 83264790Sbaptstatic int isa_running; 84264790Sbapt 85264790Sbapt/* 86264790Sbapt * At 'probe' time, we add all the devices which we know about to the 87264790Sbapt * bus. The generic attach routine will probe and attach them if they 88264790Sbapt * are alive. 89264790Sbapt */ 90264790Sbaptstatic int 91264790Sbaptisa_probe(device_t dev) 92264790Sbapt{ 93264790Sbapt device_set_desc(dev, "ISA bus"); 94264790Sbapt isa_init(dev); /* Allow machdep code to initialise */ 95264790Sbapt return (0); 96264790Sbapt} 97264790Sbapt 98264790Sbaptextern device_t isa_bus_device; 99264790Sbapt 100264790Sbaptstatic int 101264790Sbaptisa_attach(device_t dev) 102264790Sbapt{ 103264790Sbapt /* 104264790Sbapt * Arrange for isa_probe_children(dev) to be called later. XXX 105264790Sbapt */ 106264790Sbapt isa_bus_device = dev; 107264790Sbapt return (0); 108264790Sbapt} 109264790Sbapt 110264790Sbapt/* 111264790Sbapt * Find a working set of memory regions for a child using the ranges 112264790Sbapt * in *config and return the regions in *result. Returns non-zero if 113264790Sbapt * a set of ranges was found. 114264790Sbapt */ 115264790Sbaptstatic int 116264790Sbaptisa_find_memory(device_t child, struct isa_config *config, 117264790Sbapt struct isa_config *result) 118264790Sbapt{ 119264790Sbapt int success, i; 120264790Sbapt struct resource *res[ISA_NMEM]; 121264790Sbapt 122264790Sbapt /* 123264790Sbapt * First clear out any existing resource definitions. 124264790Sbapt */ 125264790Sbapt for (i = 0; i < ISA_NMEM; i++) { 126264790Sbapt bus_delete_resource(child, SYS_RES_MEMORY, i); 127264790Sbapt res[i] = NULL; 128264790Sbapt } 129264790Sbapt 130264790Sbapt success = 1; 131264790Sbapt result->ic_nmem = config->ic_nmem; 132264790Sbapt for (i = 0; i < config->ic_nmem; i++) { 133264790Sbapt uint32_t start, end, size, align; 134264790Sbapt 135264790Sbapt size = config->ic_mem[i].ir_size; 136264790Sbapt 137264790Sbapt /* the PnP device may have a null resource as filler */ 138264790Sbapt if (size == 0) { 139264790Sbapt result->ic_mem[i].ir_start = 0; 140264790Sbapt result->ic_mem[i].ir_end = 0; 141264790Sbapt result->ic_mem[i].ir_size = 0; 142264790Sbapt result->ic_mem[i].ir_align = 0; 143264790Sbapt continue; 144264790Sbapt } 145264790Sbapt 146264790Sbapt for (start = config->ic_mem[i].ir_start, 147264790Sbapt end = config->ic_mem[i].ir_end, 148264790Sbapt align = config->ic_mem[i].ir_align; 149264790Sbapt start + size - 1 <= end && start + size > start; 150272955Srodrigc start += MAX(align, 1)) { 151264790Sbapt bus_set_resource(child, SYS_RES_MEMORY, i, 152264790Sbapt start, size); 153264790Sbapt res[i] = bus_alloc_resource(child, 154264790Sbapt SYS_RES_MEMORY, &i, 0, ~0, 1, 155264790Sbapt rman_make_alignment_flags(align) /* !RF_ACTIVE */); 156264790Sbapt if (res[i]) { 157264790Sbapt result->ic_mem[i].ir_start = start; 158264790Sbapt result->ic_mem[i].ir_end = start + size - 1; 159264790Sbapt result->ic_mem[i].ir_size = size; 160264790Sbapt result->ic_mem[i].ir_align = align; 161264790Sbapt break; 162272955Srodrigc } 163264790Sbapt } 164264790Sbapt 165264790Sbapt /* 166264790Sbapt * If we didn't find a place for memory range i, then 167264790Sbapt * give up now. 168272955Srodrigc */ 169264790Sbapt if (!res[i]) { 170264790Sbapt success = 0; 171264790Sbapt break; 172264790Sbapt } 173264790Sbapt } 174264790Sbapt 175264790Sbapt for (i = 0; i < ISA_NMEM; i++) { 176264790Sbapt if (res[i]) 177264790Sbapt bus_release_resource(child, SYS_RES_MEMORY, 178264790Sbapt i, res[i]); 179264790Sbapt } 180264790Sbapt 181264790Sbapt return (success); 182264790Sbapt} 183264790Sbapt 184264790Sbapt/* 185264790Sbapt * Find a working set of port regions for a child using the ranges 186264790Sbapt * in *config and return the regions in *result. Returns non-zero if 187264790Sbapt * a set of ranges was found. 188264790Sbapt */ 189264790Sbaptstatic int 190264790Sbaptisa_find_port(device_t child, struct isa_config *config, 191264790Sbapt struct isa_config *result) 192264790Sbapt{ 193264790Sbapt int success, i; 194264790Sbapt struct resource *res[ISA_NPORT]; 195264790Sbapt 196264790Sbapt /* 197264790Sbapt * First clear out any existing resource definitions. 198264790Sbapt */ 199264790Sbapt for (i = 0; i < ISA_NPORT; i++) { 200264790Sbapt bus_delete_resource(child, SYS_RES_IOPORT, i); 201264790Sbapt res[i] = NULL; 202264790Sbapt } 203264790Sbapt 204264790Sbapt success = 1; 205264790Sbapt result->ic_nport = config->ic_nport; 206264790Sbapt for (i = 0; i < config->ic_nport; i++) { 207264790Sbapt uint32_t start, end, size, align; 208264790Sbapt 209264790Sbapt size = config->ic_port[i].ir_size; 210264790Sbapt 211264790Sbapt /* the PnP device may have a null resource as filler */ 212264790Sbapt if (size == 0) { 213264790Sbapt result->ic_port[i].ir_start = 0; 214264790Sbapt result->ic_port[i].ir_end = 0; 215264790Sbapt result->ic_port[i].ir_size = 0; 216264790Sbapt result->ic_port[i].ir_align = 0; 217264790Sbapt continue; 218264790Sbapt } 219264790Sbapt 220264790Sbapt for (start = config->ic_port[i].ir_start, 221264790Sbapt end = config->ic_port[i].ir_end, 222264790Sbapt align = config->ic_port[i].ir_align; 223264790Sbapt start + size - 1 <= end; 224264790Sbapt start += align) { 225264790Sbapt bus_set_resource(child, SYS_RES_IOPORT, i, 226264790Sbapt start, size); 227264790Sbapt res[i] = bus_alloc_resource(child, 228264790Sbapt SYS_RES_IOPORT, &i, 0, ~0, 1, 229264790Sbapt rman_make_alignment_flags(align) /* !RF_ACTIVE */); 230264790Sbapt if (res[i]) { 231264790Sbapt result->ic_port[i].ir_start = start; 232264790Sbapt result->ic_port[i].ir_end = start + size - 1; 233264790Sbapt result->ic_port[i].ir_size = size; 234264790Sbapt result->ic_port[i].ir_align = align; 235264790Sbapt break; 236264790Sbapt } 237264790Sbapt } 238264790Sbapt 239264790Sbapt /* 240264790Sbapt * If we didn't find a place for port range i, then 241264790Sbapt * give up now. 242264790Sbapt */ 243264790Sbapt if (!res[i]) { 244264790Sbapt success = 0; 245264790Sbapt break; 246264790Sbapt } 247264790Sbapt } 248264790Sbapt 249264790Sbapt for (i = 0; i < ISA_NPORT; i++) { 250264790Sbapt if (res[i]) 251264790Sbapt bus_release_resource(child, SYS_RES_IOPORT, 252264790Sbapt i, res[i]); 253264790Sbapt } 254264790Sbapt 255264790Sbapt return success; 256264790Sbapt} 257264790Sbapt 258264790Sbapt/* 259264790Sbapt * Return the index of the first bit in the mask (or -1 if mask is empty. 260264790Sbapt */ 261264790Sbaptstatic int 262264790Sbaptfind_first_bit(uint32_t mask) 263264790Sbapt{ 264264790Sbapt return (ffs(mask) - 1); 265264790Sbapt} 266264790Sbapt 267264790Sbapt/* 268264790Sbapt * Return the index of the next bit in the mask, or -1 if there are no more. 269264790Sbapt */ 270264790Sbaptstatic int 271264790Sbaptfind_next_bit(uint32_t mask, int bit) 272264790Sbapt{ 273264790Sbapt bit++; 274264790Sbapt while (bit < 32 && !(mask & (1 << bit))) 275264790Sbapt bit++; 276272955Srodrigc if (bit != 32) 277272955Srodrigc return (bit); 278272955Srodrigc return (-1); 279272955Srodrigc} 280272955Srodrigc 281272955Srodrigc/* 282272955Srodrigc * Find a working set of irqs for a child using the masks in *config 283272955Srodrigc * and return the regions in *result. Returns non-zero if a set of 284272955Srodrigc * irqs was found. 285272955Srodrigc */ 286272955Srodrigcstatic int 287272955Srodrigcisa_find_irq(device_t child, struct isa_config *config, 288272955Srodrigc struct isa_config *result) 289272955Srodrigc{ 290272955Srodrigc int success, i; 291272955Srodrigc struct resource *res[ISA_NIRQ]; 292272955Srodrigc 293272955Srodrigc /* 294272955Srodrigc * First clear out any existing resource definitions. 295272955Srodrigc */ 296272955Srodrigc for (i = 0; i < ISA_NIRQ; i++) { 297272955Srodrigc bus_delete_resource(child, SYS_RES_IRQ, i); 298272955Srodrigc res[i] = NULL; 299272955Srodrigc } 300272955Srodrigc 301272955Srodrigc success = 1; 302264790Sbapt result->ic_nirq = config->ic_nirq; 303264790Sbapt for (i = 0; i < config->ic_nirq; i++) { 304264790Sbapt uint32_t mask = config->ic_irqmask[i]; 305264790Sbapt int irq; 306264790Sbapt 307264790Sbapt /* the PnP device may have a null resource as filler */ 308264790Sbapt if (mask == 0) { 309264790Sbapt result->ic_irqmask[i] = 0; 310264790Sbapt continue; 311264790Sbapt } 312264790Sbapt 313264790Sbapt for (irq = find_first_bit(mask); 314264790Sbapt irq != -1; 315264790Sbapt irq = find_next_bit(mask, irq)) { 316264790Sbapt bus_set_resource(child, SYS_RES_IRQ, i, 317264790Sbapt irq, 1); 318264790Sbapt res[i] = bus_alloc_resource_any(child, 319264790Sbapt SYS_RES_IRQ, &i, 320264790Sbapt 0 /* !RF_ACTIVE */ ); 321264790Sbapt if (res[i]) { 322264790Sbapt result->ic_irqmask[i] = (1 << irq); 323264790Sbapt break; 324264790Sbapt } 325264790Sbapt } 326264790Sbapt 327264790Sbapt /* 328264790Sbapt * If we didn't find a place for irq range i, then 329264790Sbapt * give up now. 330264790Sbapt */ 331264790Sbapt if (!res[i]) { 332264790Sbapt success = 0; 333264790Sbapt break; 334264790Sbapt } 335264790Sbapt } 336264790Sbapt 337264790Sbapt for (i = 0; i < ISA_NIRQ; i++) { 338264790Sbapt if (res[i]) 339264790Sbapt bus_release_resource(child, SYS_RES_IRQ, 340264790Sbapt i, res[i]); 341264790Sbapt } 342264790Sbapt 343264790Sbapt return (success); 344264790Sbapt} 345264790Sbapt 346264790Sbapt/* 347264790Sbapt * Find a working set of drqs for a child using the masks in *config 348264790Sbapt * and return the regions in *result. Returns non-zero if a set of 349264790Sbapt * drqs was found. 350264790Sbapt */ 351264790Sbaptstatic int 352264790Sbaptisa_find_drq(device_t child, struct isa_config *config, 353264790Sbapt struct isa_config *result) 354264790Sbapt{ 355264790Sbapt int success, i; 356264790Sbapt struct resource *res[ISA_NDRQ]; 357264790Sbapt 358264790Sbapt /* 359264790Sbapt * First clear out any existing resource definitions. 360264790Sbapt */ 361264790Sbapt for (i = 0; i < ISA_NDRQ; i++) { 362264790Sbapt bus_delete_resource(child, SYS_RES_DRQ, i); 363264790Sbapt res[i] = NULL; 364264790Sbapt } 365264790Sbapt 366264790Sbapt success = 1; 367264790Sbapt result->ic_ndrq = config->ic_ndrq; 368264790Sbapt for (i = 0; i < config->ic_ndrq; i++) { 369264790Sbapt uint32_t mask = config->ic_drqmask[i]; 370264790Sbapt int drq; 371264790Sbapt 372264790Sbapt /* the PnP device may have a null resource as filler */ 373264790Sbapt if (mask == 0) { 374264790Sbapt result->ic_drqmask[i] = 0; 375264790Sbapt continue; 376264790Sbapt } 377264790Sbapt 378264790Sbapt for (drq = find_first_bit(mask); 379264790Sbapt drq != -1; 380264790Sbapt drq = find_next_bit(mask, drq)) { 381264790Sbapt bus_set_resource(child, SYS_RES_DRQ, i, 382264790Sbapt drq, 1); 383264790Sbapt res[i] = bus_alloc_resource_any(child, 384264790Sbapt SYS_RES_DRQ, &i, 385264790Sbapt 0 /* !RF_ACTIVE */); 386264790Sbapt if (res[i]) { 387264790Sbapt result->ic_drqmask[i] = (1 << drq); 388264790Sbapt break; 389264790Sbapt } 390264790Sbapt } 391264790Sbapt 392264790Sbapt /* 393264790Sbapt * If we didn't find a place for drq range i, then 394264790Sbapt * give up now. 395264790Sbapt */ 396264790Sbapt if (!res[i]) { 397264790Sbapt success = 0; 398264790Sbapt break; 399264790Sbapt } 400264790Sbapt } 401264790Sbapt 402264790Sbapt for (i = 0; i < ISA_NDRQ; i++) { 403264790Sbapt if (res[i]) 404264790Sbapt bus_release_resource(child, SYS_RES_DRQ, 405264790Sbapt i, res[i]); 406264790Sbapt } 407264790Sbapt 408264790Sbapt return (success); 409264790Sbapt} 410264790Sbapt 411264790Sbapt/* 412264790Sbapt * Attempt to find a working set of resources for a device. Return 413264790Sbapt * non-zero if a working configuration is found. 414264790Sbapt */ 415264790Sbaptstatic int 416264790Sbaptisa_assign_resources(device_t child) 417264790Sbapt{ 418264790Sbapt struct isa_device *idev = DEVTOISA(child); 419264790Sbapt struct isa_config_entry *ice; 420264790Sbapt struct isa_config *cfg; 421264790Sbapt const char *reason; 422264790Sbapt 423264790Sbapt reason = "Empty ISA id_configs"; 424264790Sbapt cfg = malloc(sizeof(struct isa_config), M_TEMP, M_NOWAIT|M_ZERO); 425264790Sbapt if (cfg == NULL) 426264790Sbapt return(0); 427264790Sbapt TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 428264790Sbapt reason = "memory"; 429264790Sbapt if (!isa_find_memory(child, &ice->ice_config, cfg)) 430264790Sbapt continue; 431264790Sbapt reason = "port"; 432264790Sbapt if (!isa_find_port(child, &ice->ice_config, cfg)) 433264790Sbapt continue; 434264790Sbapt reason = "irq"; 435264790Sbapt if (!isa_find_irq(child, &ice->ice_config, cfg)) 436264790Sbapt continue; 437264790Sbapt reason = "drq"; 438264790Sbapt if (!isa_find_drq(child, &ice->ice_config, cfg)) 439264790Sbapt continue; 440264790Sbapt 441264790Sbapt /* 442264790Sbapt * A working configuration was found enable the device 443264790Sbapt * with this configuration. 444264790Sbapt */ 445264790Sbapt reason = "no callback"; 446264790Sbapt if (idev->id_config_cb) { 447264790Sbapt idev->id_config_cb(idev->id_config_arg, 448264790Sbapt cfg, 1); 449264790Sbapt free(cfg, M_TEMP); 450264790Sbapt return (1); 451264790Sbapt } 452264790Sbapt } 453264790Sbapt 454264790Sbapt /* 455264790Sbapt * Disable the device. 456264790Sbapt */ 457264790Sbapt bus_print_child_header(device_get_parent(child), child); 458264790Sbapt printf(" can't assign resources (%s)\n", reason); 459264790Sbapt if (bootverbose) 460264790Sbapt isa_print_child(device_get_parent(child), child); 461264790Sbapt bzero(cfg, sizeof (*cfg)); 462264790Sbapt if (idev->id_config_cb) 463264790Sbapt idev->id_config_cb(idev->id_config_arg, cfg, 0); 464264790Sbapt device_disable(child); 465264790Sbapt 466264790Sbapt free(cfg, M_TEMP); 467264790Sbapt return (0); 468264790Sbapt} 469264790Sbapt 470264790Sbapt/* 471264790Sbapt * Called after other devices have initialised to probe for isa devices. 472264790Sbapt */ 473272955Srodrigcvoid 474264790Sbaptisa_probe_children(device_t dev) 475264790Sbapt{ 476264790Sbapt device_t *children; 477264790Sbapt struct isa_config *cfg; 478264790Sbapt int nchildren, i; 479264790Sbapt 480264790Sbapt /* 481264790Sbapt * Create all the children by calling driver's identify methods. 482272955Srodrigc */ 483264790Sbapt bus_generic_probe(dev); 484264790Sbapt 485272955Srodrigc if (device_get_children(dev, &children, &nchildren)) 486272955Srodrigc return; 487264790Sbapt 488264790Sbapt /* 489264790Sbapt * First disable all pnp devices so that they don't get 490264790Sbapt * matched by legacy probes. 491264790Sbapt */ 492264790Sbapt if (bootverbose) 493264790Sbapt printf("isa_probe_children: disabling PnP devices\n"); 494264790Sbapt 495264790Sbapt cfg = malloc(sizeof(*cfg), M_TEMP, M_NOWAIT|M_ZERO); 496264790Sbapt if (cfg == NULL) { 497264790Sbapt free(children, M_TEMP); 498264790Sbapt return; 499264790Sbapt } 500264790Sbapt 501264790Sbapt for (i = 0; i < nchildren; i++) { 502264790Sbapt device_t child = children[i]; 503264790Sbapt struct isa_device *idev = DEVTOISA(child); 504264790Sbapt 505264790Sbapt bzero(cfg, sizeof(*cfg)); 506264790Sbapt if (idev->id_config_cb) 507264790Sbapt idev->id_config_cb(idev->id_config_arg, cfg, 0); 508264790Sbapt } 509264790Sbapt 510264790Sbapt free(cfg, M_TEMP); 511264790Sbapt 512264790Sbapt /* 513264790Sbapt * Next probe all non-pnp devices so that they claim their 514264790Sbapt * resources first. 515264790Sbapt */ 516264790Sbapt if (bootverbose) 517264790Sbapt printf("isa_probe_children: probing non-PnP devices\n"); 518264790Sbapt for (i = 0; i < nchildren; i++) { 519264790Sbapt device_t child = children[i]; 520264790Sbapt struct isa_device *idev = DEVTOISA(child); 521264790Sbapt 522264790Sbapt if (TAILQ_FIRST(&idev->id_configs)) 523264790Sbapt continue; 524264790Sbapt 525264790Sbapt device_probe_and_attach(child); 526264790Sbapt } 527264790Sbapt 528264790Sbapt /* 529264790Sbapt * Finally assign resource to pnp devices and probe them. 530264790Sbapt */ 531264790Sbapt if (bootverbose) 532264790Sbapt printf("isa_probe_children: probing PnP devices\n"); 533264790Sbapt for (i = 0; i < nchildren; i++) { 534264790Sbapt device_t child = children[i]; 535264790Sbapt struct isa_device* idev = DEVTOISA(child); 536264790Sbapt 537264790Sbapt if (!TAILQ_FIRST(&idev->id_configs)) 538264790Sbapt continue; 539264790Sbapt 540264790Sbapt if (isa_assign_resources(child)) { 541264790Sbapt struct resource_list *rl = &idev->id_resources; 542264790Sbapt struct resource_list_entry *rle; 543264790Sbapt 544264790Sbapt device_probe_and_attach(child); 545264790Sbapt 546264790Sbapt /* 547264790Sbapt * Claim any unallocated resources to keep other 548264790Sbapt * devices from using them. 549264790Sbapt */ 550264790Sbapt STAILQ_FOREACH(rle, rl, link) { 551264790Sbapt if (!rle->res) { 552264790Sbapt int rid = rle->rid; 553264790Sbapt resource_list_alloc(rl, dev, child, 554264790Sbapt rle->type, 555264790Sbapt &rid, 556264790Sbapt 0, ~0, 1, 0); 557264790Sbapt } 558264790Sbapt } 559264790Sbapt } 560264790Sbapt } 561264790Sbapt 562264790Sbapt free(children, M_TEMP); 563264790Sbapt 564264790Sbapt isa_running = 1; 565264790Sbapt} 566264790Sbapt 567264790Sbapt/* 568264790Sbapt * Add a new child with default ivars. 569264790Sbapt */ 570264790Sbaptstatic device_t 571264790Sbaptisa_add_child(device_t dev, int order, const char *name, int unit) 572264790Sbapt{ 573264790Sbapt device_t child; 574264790Sbapt struct isa_device *idev; 575264790Sbapt 576264790Sbapt child = device_add_child_ordered(dev, order, name, unit); 577264790Sbapt if (child == NULL) 578264790Sbapt return (child); 579264790Sbapt 580264790Sbapt idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT | M_ZERO); 581264790Sbapt if (!idev) 582264790Sbapt return (0); 583264790Sbapt 584264790Sbapt resource_list_init(&idev->id_resources); 585264790Sbapt TAILQ_INIT(&idev->id_configs); 586264790Sbapt 587264790Sbapt device_set_ivars(child, idev); 588264790Sbapt 589264790Sbapt return (child); 590264790Sbapt} 591264790Sbapt 592264790Sbaptstatic int 593264790Sbaptisa_print_all_resources(device_t dev) 594264790Sbapt{ 595264790Sbapt struct isa_device *idev = DEVTOISA(dev); 596264790Sbapt struct resource_list *rl = &idev->id_resources; 597264790Sbapt int retval = 0; 598264790Sbapt 599264790Sbapt if (STAILQ_FIRST(rl) || device_get_flags(dev)) 600264790Sbapt retval += printf(" at"); 601264790Sbapt 602264790Sbapt retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 603264790Sbapt retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 604264790Sbapt retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 605264790Sbapt retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld"); 606264790Sbapt if (device_get_flags(dev)) 607264790Sbapt retval += printf(" flags %#x", device_get_flags(dev)); 608264790Sbapt#ifdef ISAPNP 609264790Sbapt if (idev->id_vendorid) 610264790Sbapt retval += printf(" pnpid %s", pnp_eisaformat(idev->id_vendorid)); 611264790Sbapt#endif 612264790Sbapt 613264790Sbapt return (retval); 614264790Sbapt} 615264790Sbapt 616264790Sbaptstatic int 617264790Sbaptisa_print_child(device_t bus, device_t dev) 618264790Sbapt{ 619264790Sbapt int retval = 0; 620264790Sbapt 621264790Sbapt retval += bus_print_child_header(bus, dev); 622264790Sbapt retval += isa_print_all_resources(dev); 623264790Sbapt retval += bus_print_child_footer(bus, dev); 624264790Sbapt 625264790Sbapt return (retval); 626264790Sbapt} 627264790Sbapt 628264790Sbaptstatic void 629264790Sbaptisa_probe_nomatch(device_t dev, device_t child) 630264790Sbapt{ 631264790Sbapt if (bootverbose) { 632264790Sbapt bus_print_child_header(dev, child); 633264790Sbapt printf(" failed to probe"); 634264790Sbapt isa_print_all_resources(child); 635264790Sbapt bus_print_child_footer(dev, child); 636264790Sbapt } 637264790Sbapt 638264790Sbapt return; 639264790Sbapt} 640264790Sbapt 641264790Sbaptstatic int 642264790Sbaptisa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) 643264790Sbapt{ 644264790Sbapt struct isa_device* idev = DEVTOISA(dev); 645264790Sbapt struct resource_list *rl = &idev->id_resources; 646264790Sbapt struct resource_list_entry *rle; 647264790Sbapt 648264790Sbapt switch (index) { 649264790Sbapt case ISA_IVAR_PORT_0: 650264790Sbapt rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 651264790Sbapt if (rle) 652264790Sbapt *result = rle->start; 653264790Sbapt else 654264790Sbapt *result = -1; 655264790Sbapt break; 656264790Sbapt 657264790Sbapt case ISA_IVAR_PORT_1: 658264790Sbapt rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 659264790Sbapt if (rle) 660264790Sbapt *result = rle->start; 661264790Sbapt else 662264790Sbapt *result = -1; 663264790Sbapt break; 664264790Sbapt 665264790Sbapt case ISA_IVAR_PORTSIZE_0: 666264790Sbapt rle = resource_list_find(rl, SYS_RES_IOPORT, 0); 667264790Sbapt if (rle) 668264790Sbapt *result = rle->count; 669264790Sbapt else 670264790Sbapt *result = 0; 671264790Sbapt break; 672264790Sbapt 673264790Sbapt case ISA_IVAR_PORTSIZE_1: 674264790Sbapt rle = resource_list_find(rl, SYS_RES_IOPORT, 1); 675264790Sbapt if (rle) 676264790Sbapt *result = rle->count; 677264790Sbapt else 678264790Sbapt *result = 0; 679264790Sbapt break; 680264790Sbapt 681264790Sbapt case ISA_IVAR_MADDR_0: 682264790Sbapt rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 683264790Sbapt if (rle) 684264790Sbapt *result = rle->start; 685264790Sbapt else 686264790Sbapt *result = -1; 687264790Sbapt break; 688264790Sbapt 689264790Sbapt case ISA_IVAR_MADDR_1: 690264790Sbapt rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 691264790Sbapt if (rle) 692264790Sbapt *result = rle->start; 693264790Sbapt else 694264790Sbapt *result = -1; 695264790Sbapt break; 696264790Sbapt 697264790Sbapt case ISA_IVAR_MEMSIZE_0: 698264790Sbapt rle = resource_list_find(rl, SYS_RES_MEMORY, 0); 699264790Sbapt if (rle) 700264790Sbapt *result = rle->count; 701264790Sbapt else 702264790Sbapt *result = 0; 703264790Sbapt break; 704264790Sbapt 705264790Sbapt case ISA_IVAR_MEMSIZE_1: 706264790Sbapt rle = resource_list_find(rl, SYS_RES_MEMORY, 1); 707264790Sbapt if (rle) 708264790Sbapt *result = rle->count; 709264790Sbapt else 710264790Sbapt *result = 0; 711264790Sbapt break; 712264790Sbapt 713264790Sbapt case ISA_IVAR_IRQ_0: 714264790Sbapt rle = resource_list_find(rl, SYS_RES_IRQ, 0); 715264790Sbapt if (rle) 716264790Sbapt *result = rle->start; 717264790Sbapt else 718264790Sbapt *result = -1; 719264790Sbapt break; 720272955Srodrigc 721272955Srodrigc case ISA_IVAR_IRQ_1: 722264790Sbapt rle = resource_list_find(rl, SYS_RES_IRQ, 1); 723264790Sbapt if (rle) 724264790Sbapt *result = rle->start; 725264790Sbapt else 726264790Sbapt *result = -1; 727264790Sbapt break; 728264790Sbapt 729264790Sbapt case ISA_IVAR_DRQ_0: 730264790Sbapt rle = resource_list_find(rl, SYS_RES_DRQ, 0); 731264790Sbapt if (rle) 732264790Sbapt *result = rle->start; 733264790Sbapt else 734264790Sbapt *result = -1; 735264790Sbapt break; 736264790Sbapt 737264790Sbapt case ISA_IVAR_DRQ_1: 738264790Sbapt rle = resource_list_find(rl, SYS_RES_DRQ, 1); 739264790Sbapt if (rle) 740264790Sbapt *result = rle->start; 741264790Sbapt else 742264790Sbapt *result = -1; 743264790Sbapt break; 744264790Sbapt 745264790Sbapt case ISA_IVAR_VENDORID: 746264790Sbapt *result = idev->id_vendorid; 747264790Sbapt break; 748264790Sbapt 749264790Sbapt case ISA_IVAR_SERIAL: 750264790Sbapt *result = idev->id_serial; 751264790Sbapt break; 752264790Sbapt 753264790Sbapt case ISA_IVAR_LOGICALID: 754264790Sbapt *result = idev->id_logicalid; 755264790Sbapt break; 756264790Sbapt 757264790Sbapt case ISA_IVAR_COMPATID: 758264790Sbapt *result = idev->id_compatid; 759264790Sbapt break; 760264790Sbapt 761264790Sbapt case ISA_IVAR_CONFIGATTR: 762264790Sbapt *result = idev->id_config_attr; 763264790Sbapt break; 764264790Sbapt 765264790Sbapt default: 766264790Sbapt return (ENOENT); 767264790Sbapt } 768264790Sbapt 769264790Sbapt return (0); 770264790Sbapt} 771264790Sbapt 772264790Sbaptstatic int 773264790Sbaptisa_write_ivar(device_t bus, device_t dev, int index, uintptr_t value) 774264790Sbapt{ 775264790Sbapt struct isa_device* idev = DEVTOISA(dev); 776264790Sbapt 777264790Sbapt switch (index) { 778264790Sbapt case ISA_IVAR_PORT_0: 779264790Sbapt case ISA_IVAR_PORT_1: 780264790Sbapt case ISA_IVAR_PORTSIZE_0: 781264790Sbapt case ISA_IVAR_PORTSIZE_1: 782264790Sbapt case ISA_IVAR_MADDR_0: 783264790Sbapt case ISA_IVAR_MADDR_1: 784264790Sbapt case ISA_IVAR_MEMSIZE_0: 785264790Sbapt case ISA_IVAR_MEMSIZE_1: 786264790Sbapt case ISA_IVAR_IRQ_0: 787264790Sbapt case ISA_IVAR_IRQ_1: 788264790Sbapt case ISA_IVAR_DRQ_0: 789264790Sbapt case ISA_IVAR_DRQ_1: 790264790Sbapt return (EINVAL); 791264790Sbapt 792264790Sbapt case ISA_IVAR_VENDORID: 793264790Sbapt idev->id_vendorid = value; 794264790Sbapt break; 795264790Sbapt 796264790Sbapt case ISA_IVAR_SERIAL: 797264790Sbapt idev->id_serial = value; 798264790Sbapt break; 799264790Sbapt 800264790Sbapt case ISA_IVAR_LOGICALID: 801264790Sbapt idev->id_logicalid = value; 802264790Sbapt break; 803264790Sbapt 804264790Sbapt case ISA_IVAR_COMPATID: 805264790Sbapt idev->id_compatid = value; 806264790Sbapt break; 807264790Sbapt 808264790Sbapt case ISA_IVAR_CONFIGATTR: 809264790Sbapt idev->id_config_attr = value; 810264790Sbapt break; 811264790Sbapt 812264790Sbapt default: 813264790Sbapt return (ENOENT); 814264790Sbapt } 815264790Sbapt 816264790Sbapt return (0); 817272955Srodrigc} 818264790Sbapt 819272955Srodrigc/* 820264790Sbapt * Free any resources which the driver missed or which we were holding for 821264790Sbapt * it (see isa_probe_children). 822272955Srodrigc */ 823264790Sbaptstatic void 824264790Sbaptisa_child_detached(device_t dev, device_t child) 825264790Sbapt{ 826264790Sbapt struct isa_device* idev = DEVTOISA(child); 827264790Sbapt struct resource_list *rl = &idev->id_resources; 828264790Sbapt struct resource_list_entry *rle; 829264790Sbapt 830264790Sbapt if (TAILQ_FIRST(&idev->id_configs)) { 831264790Sbapt /* 832264790Sbapt * Claim any unallocated resources to keep other 833264790Sbapt * devices from using them. 834264790Sbapt */ 835264790Sbapt STAILQ_FOREACH(rle, rl, link) { 836264790Sbapt if (!rle->res) { 837264790Sbapt int rid = rle->rid; 838264790Sbapt resource_list_alloc(rl, dev, child, 839264790Sbapt rle->type, 840264790Sbapt &rid, 0, ~0, 1, 0); 841264790Sbapt } 842264790Sbapt } 843264790Sbapt } 844264790Sbapt} 845264790Sbapt 846264790Sbaptstatic void 847264790Sbaptisa_driver_added(device_t dev, driver_t *driver) 848264790Sbapt{ 849264790Sbapt device_t *children; 850264790Sbapt int nchildren, i; 851264790Sbapt 852264790Sbapt /* 853264790Sbapt * Don't do anything if drivers are dynamically 854264790Sbapt * added during autoconfiguration (cf. ymf724). 855264790Sbapt * since that would end up calling identify 856264790Sbapt * twice. 857264790Sbapt */ 858264790Sbapt if (!isa_running) 859264790Sbapt return; 860264790Sbapt 861264790Sbapt DEVICE_IDENTIFY(driver, dev); 862264790Sbapt if (device_get_children(dev, &children, &nchildren)) 863264790Sbapt return; 864264790Sbapt 865264790Sbapt for (i = 0; i < nchildren; i++) { 866264790Sbapt device_t child = children[i]; 867264790Sbapt struct isa_device *idev = DEVTOISA(child); 868264790Sbapt struct resource_list *rl = &idev->id_resources; 869264790Sbapt struct resource_list_entry *rle; 870264790Sbapt 871264790Sbapt if (device_get_state(child) != DS_NOTPRESENT) 872264790Sbapt continue; 873264790Sbapt if (!device_is_enabled(child)) 874264790Sbapt continue; 875264790Sbapt 876264790Sbapt /* 877272955Srodrigc * Free resources which we were holding on behalf of 878264790Sbapt * the device. 879264790Sbapt */ 880264790Sbapt STAILQ_FOREACH(rle, &idev->id_resources, link) { 881264790Sbapt if (rle->res) 882264790Sbapt resource_list_release(rl, dev, child, 883264790Sbapt rle->type, 884264790Sbapt rle->rid, 885264790Sbapt rle->res); 886264790Sbapt } 887264790Sbapt 888264790Sbapt if (TAILQ_FIRST(&idev->id_configs)) 889264790Sbapt if (!isa_assign_resources(child)) 890264790Sbapt continue; 891264790Sbapt 892264790Sbapt device_probe_and_attach(child); 893264790Sbapt 894264790Sbapt if (TAILQ_FIRST(&idev->id_configs)) { 895264790Sbapt /* 896264790Sbapt * Claim any unallocated resources to keep other 897264790Sbapt * devices from using them. 898264790Sbapt */ 899264790Sbapt STAILQ_FOREACH(rle, rl, link) { 900264790Sbapt if (!rle->res) { 901264790Sbapt int rid = rle->rid; 902264790Sbapt resource_list_alloc(rl, dev, child, 903264790Sbapt rle->type, 904264790Sbapt &rid, 0, ~0, 1, 0); 905264790Sbapt } 906264790Sbapt } 907264790Sbapt } 908264790Sbapt } 909264790Sbapt 910264790Sbapt free(children, M_TEMP); 911264790Sbapt} 912264790Sbapt 913264790Sbaptstatic int 914264790Sbaptisa_set_resource(device_t dev, device_t child, int type, int rid, 915264790Sbapt u_long start, u_long count) 916264790Sbapt{ 917264790Sbapt struct isa_device* idev = DEVTOISA(child); 918264790Sbapt struct resource_list *rl = &idev->id_resources; 919264790Sbapt 920264790Sbapt if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 921264790Sbapt && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 922264790Sbapt return (EINVAL); 923264790Sbapt if (rid < 0) 924264790Sbapt return (EINVAL); 925264790Sbapt if (type == SYS_RES_IOPORT && rid >= ISA_NPORT) 926264790Sbapt return (EINVAL); 927264790Sbapt if (type == SYS_RES_MEMORY && rid >= ISA_NMEM) 928264790Sbapt return (EINVAL); 929264790Sbapt if (type == SYS_RES_IRQ && rid >= ISA_NIRQ) 930264790Sbapt return (EINVAL); 931264790Sbapt if (type == SYS_RES_DRQ && rid >= ISA_NDRQ) 932264790Sbapt return (EINVAL); 933264790Sbapt 934264790Sbapt resource_list_add(rl, type, rid, start, start + count - 1, count); 935264790Sbapt 936264790Sbapt return (0); 937264790Sbapt} 938264790Sbapt 939264790Sbaptstatic struct resource_list * 940264790Sbaptisa_get_resource_list (device_t dev, device_t child) 941264790Sbapt{ 942264790Sbapt struct isa_device* idev = DEVTOISA(child); 943264790Sbapt struct resource_list *rl = &idev->id_resources; 944264790Sbapt 945264790Sbapt if (!rl) 946264790Sbapt return (NULL); 947264790Sbapt 948264790Sbapt return (rl); 949264790Sbapt} 950264790Sbapt 951264790Sbaptstatic int 952264790Sbaptisa_add_config(device_t dev, device_t child, int priority, 953264790Sbapt struct isa_config *config) 954264790Sbapt{ 955264790Sbapt struct isa_device* idev = DEVTOISA(child); 956264790Sbapt struct isa_config_entry *newice, *ice; 957264790Sbapt 958264790Sbapt newice = malloc(sizeof *ice, M_DEVBUF, M_NOWAIT); 959264790Sbapt if (!newice) 960264790Sbapt return (ENOMEM); 961264790Sbapt 962264790Sbapt newice->ice_priority = priority; 963264790Sbapt newice->ice_config = *config; 964264790Sbapt 965264790Sbapt TAILQ_FOREACH(ice, &idev->id_configs, ice_link) { 966264790Sbapt if (ice->ice_priority > priority) 967264790Sbapt break; 968264790Sbapt } 969264790Sbapt if (ice) 970264790Sbapt TAILQ_INSERT_BEFORE(ice, newice, ice_link); 971272955Srodrigc else 972264790Sbapt TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); 973272955Srodrigc 974264790Sbapt return (0); 975264790Sbapt} 976272955Srodrigc 977264790Sbaptstatic void 978272955Srodrigcisa_set_config_callback(device_t dev, device_t child, isa_config_cb *fn, 979264790Sbapt void *arg) 980264790Sbapt{ 981264790Sbapt struct isa_device* idev = DEVTOISA(child); 982264790Sbapt 983264790Sbapt idev->id_config_cb = fn; 984264790Sbapt idev->id_config_arg = arg; 985264790Sbapt} 986264790Sbapt 987272955Srodrigcstatic int 988264790Sbaptisa_pnp_probe(device_t dev, device_t child, struct isa_pnp_id *ids) 989272955Srodrigc{ 990264790Sbapt struct isa_device* idev = DEVTOISA(child); 991264790Sbapt 992272955Srodrigc if (!idev->id_vendorid) 993264790Sbapt return (ENOENT); 994264790Sbapt 995264790Sbapt while (ids && ids->ip_id) { 996264790Sbapt /* 997264790Sbapt * Really ought to support >1 compat id per device. 998264790Sbapt */ 999264790Sbapt if (idev->id_logicalid == ids->ip_id 1000264790Sbapt || idev->id_compatid == ids->ip_id) { 1001264790Sbapt if (ids->ip_desc) 1002264790Sbapt device_set_desc(child, ids->ip_desc); 1003264790Sbapt return (0); 1004264790Sbapt } 1005264790Sbapt ids++; 1006264790Sbapt } 1007264790Sbapt 1008264790Sbapt return (ENXIO); 1009264790Sbapt} 1010264790Sbapt 1011264790Sbaptstatic int 1012264790Sbaptisa_child_pnpinfo_str(device_t bus, device_t child, char *buf, 1013264790Sbapt size_t buflen) 1014264790Sbapt{ 1015264790Sbapt#ifdef ISAPNP 1016264790Sbapt struct isa_device *idev = DEVTOISA(child); 1017264790Sbapt 1018264790Sbapt if (idev->id_vendorid) 1019264790Sbapt snprintf(buf, buflen, "pnpid=%s", 1020264790Sbapt pnp_eisaformat(idev->id_vendorid)); 1021264790Sbapt#endif 1022272955Srodrigc return (0); 1023264790Sbapt} 1024272955Srodrigc 1025264790Sbaptstatic int 1026264790Sbaptisa_child_location_str(device_t bus, device_t child, char *buf, 1027272955Srodrigc size_t buflen) 1028264790Sbapt{ 1029264790Sbapt /* Nothing here yet */ 1030264790Sbapt *buf = '\0'; 1031264790Sbapt return (0); 1032264790Sbapt} 1033264790Sbapt 1034264790Sbaptstatic device_method_t isa_methods[] = { 1035264790Sbapt /* Device interface */ 1036264790Sbapt DEVMETHOD(device_probe, isa_probe), 1037264790Sbapt DEVMETHOD(device_attach, isa_attach), 1038264790Sbapt DEVMETHOD(device_detach, bus_generic_detach), 1039264790Sbapt DEVMETHOD(device_shutdown, bus_generic_shutdown), 1040264790Sbapt DEVMETHOD(device_suspend, bus_generic_suspend), 1041264790Sbapt DEVMETHOD(device_resume, bus_generic_resume), 1042264790Sbapt 1043264790Sbapt /* Bus interface */ 1044264790Sbapt DEVMETHOD(bus_add_child, isa_add_child), 1045264790Sbapt DEVMETHOD(bus_print_child, isa_print_child), 1046264790Sbapt DEVMETHOD(bus_probe_nomatch, isa_probe_nomatch), 1047264790Sbapt DEVMETHOD(bus_read_ivar, isa_read_ivar), 1048264790Sbapt DEVMETHOD(bus_write_ivar, isa_write_ivar), 1049264790Sbapt DEVMETHOD(bus_child_detached, isa_child_detached), 1050264790Sbapt DEVMETHOD(bus_driver_added, isa_driver_added), 1051264790Sbapt DEVMETHOD(bus_setup_intr, isa_setup_intr), 1052264790Sbapt DEVMETHOD(bus_teardown_intr, isa_teardown_intr), 1053264790Sbapt 1054264790Sbapt DEVMETHOD(bus_get_resource_list,isa_get_resource_list), 1055264790Sbapt DEVMETHOD(bus_alloc_resource, isa_alloc_resource), 1056264790Sbapt DEVMETHOD(bus_release_resource, isa_release_resource), 1057264790Sbapt DEVMETHOD(bus_set_resource, isa_set_resource), 1058264790Sbapt DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 1059264790Sbapt DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 1060264790Sbapt DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1061264790Sbapt DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1062264790Sbapt DEVMETHOD(bus_child_pnpinfo_str, isa_child_pnpinfo_str), 1063264790Sbapt DEVMETHOD(bus_child_location_str, isa_child_location_str), 1064264790Sbapt 1065264790Sbapt /* ISA interface */ 1066264790Sbapt DEVMETHOD(isa_add_config, isa_add_config), 1067264790Sbapt DEVMETHOD(isa_set_config_callback, isa_set_config_callback), 1068264790Sbapt DEVMETHOD(isa_pnp_probe, isa_pnp_probe), 1069264790Sbapt 1070264790Sbapt { 0, 0 } 1071264790Sbapt}; 1072264790Sbapt 1073264790Sbaptdriver_t isa_driver = { 1074264790Sbapt "isa", 1075264790Sbapt isa_methods, 1076264790Sbapt 1, /* no softc */ 1077264790Sbapt}; 1078264790Sbapt 1079264790Sbaptdevclass_t isa_devclass; 1080264790Sbapt 1081264790Sbapt/* 1082264790Sbapt * ISA can be attached to a PCI-ISA bridge, or other locations on some 1083264790Sbapt * platforms. 1084264790Sbapt */ 1085264790SbaptDRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); 1086264790SbaptDRIVER_MODULE(isa, eisab, isa_driver, isa_devclass, 0, 0); 1087264790SbaptMODULE_VERSION(isa, 1); 1088264790Sbapt 1089264790Sbapt/* 1090264790Sbapt * Code common to ISA bridges. 1091264790Sbapt */ 1092264790Sbapt 1093264790Sbaptdevclass_t isab_devclass; 1094264790Sbapt 1095264790Sbaptint 1096264790Sbaptisab_attach(device_t dev) 1097264790Sbapt{ 1098264790Sbapt device_t child; 1099264790Sbapt 1100264790Sbapt child = device_add_child(dev, "isa", 0); 1101264790Sbapt if (child != NULL) 1102264790Sbapt return (bus_generic_attach(dev)); 1103264790Sbapt return (ENXIO); 1104264790Sbapt} 1105264790Sbapt