eisaconf.c revision 143759
11558Srgrimes/*- 21558Srgrimes * EISA bus probe and attach routines 31558Srgrimes * 41558Srgrimes * Copyright (c) 1995, 1996 Justin T. Gibbs. 51558Srgrimes * All rights reserved. 61558Srgrimes * 71558Srgrimes * Redistribution and use in source and binary forms, with or without 81558Srgrimes * modification, are permitted provided that the following conditions 91558Srgrimes * are met: 101558Srgrimes * 1. Redistributions of source code must retain the above copyright 111558Srgrimes * notice immediately at the beginning of the file, without modification, 121558Srgrimes * this list of conditions, and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. The name of the author may not be used to endorse or promote products 171558Srgrimes * derived from this software without specific prior written permission. 181558Srgrimes * 191558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 201558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 231558Srgrimes * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 291558Srgrimes * SUCH DAMAGE. 301558Srgrimes * 311558Srgrimes */ 321558Srgrimes 331558Srgrimes#include <sys/cdefs.h> 341558Srgrimes__FBSDID("$FreeBSD: head/sys/dev/eisa/eisaconf.c 143759 2005-03-17 17:36:07Z imp $"); 3541477Sjulian 3623675Speter#include "opt_eisa.h" 3741477Sjulian 3841477Sjulian#include <sys/param.h> 3950476Speter#include <sys/systm.h> 401558Srgrimes#include <sys/queue.h> 411558Srgrimes#include <sys/limits.h> 421558Srgrimes#include <sys/malloc.h> 4366861Sadrian#include <sys/kernel.h> 4466861Sadrian#include <sys/module.h> 4523675Speter#include <sys/bus.h> 461558Srgrimes 471558Srgrimes#include <machine/bus.h> 481558Srgrimes#include <machine/resource.h> 4923799Sbde#include <sys/rman.h> 5023675Speter 5166861Sadrian#include <dev/eisa/eisaconf.h> 5223799Sbde 5366861Sadriantypedef struct resvaddr { 5466861Sadrian u_long addr; /* start address */ 5566861Sadrian u_long size; /* size of reserved area */ 5666861Sadrian int flags; 5766861Sadrian struct resource *res; /* resource manager handle */ 5823675Speter LIST_ENTRY(resvaddr) links; /* List links */ 591558Srgrimes} resvaddr_t; 601558Srgrimes 611558SrgrimesLIST_HEAD(resvlist, resvaddr); 621558Srgrimes 6323675Speterstruct irq_node { 647585Sbde int irq_no; 657585Sbde int irq_trigger; 661558Srgrimes void *idesc; 671558Srgrimes TAILQ_ENTRY(irq_node) links; 681558Srgrimes}; 691558Srgrimes 701558SrgrimesTAILQ_HEAD(irqlist, irq_node); 711558Srgrimes 721558Srgrimesstruct eisa_ioconf { 731558Srgrimes int slot; 741558Srgrimes struct resvlist ioaddrs; /* list of reserved I/O ranges */ 751558Srgrimes struct resvlist maddrs; /* list of reserved memory ranges */ 761558Srgrimes struct irqlist irqs; /* list of reserved irqs */ 771558Srgrimes}; 781558Srgrimes 791558Srgrimes/* To be replaced by the "super device" generic device structure... */ 801558Srgrimesstruct eisa_device { 811558Srgrimes eisa_id_t id; 821558Srgrimes struct eisa_ioconf ioconf; 831558Srgrimes}; 841558Srgrimes 851558Srgrimes 861558Srgrimes#define MAX_COL 79 877585Sbde#ifndef EISA_SLOTS 881558Srgrimes#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */ 891558Srgrimes#endif 901558Srgrimesint num_eisa_slots = EISA_SLOTS; 911558SrgrimesTUNABLE_INT("hw.eisa_slots", &num_eisa_slots); 921558Srgrimes 931558Srgrimesstatic devclass_t eisa_devclass; 941558Srgrimes 951558Srgrimesstatic int eisa_probe_slot(int slot, eisa_id_t *eisa_id); 961558Srgrimesstatic void eisa_reg_print (device_t, char *, char *, int *); 971558Srgrimesstatic struct irq_node * eisa_find_irq(struct eisa_device *e_dev, int rid); 981558Srgrimesstatic struct resvaddr * eisa_find_maddr(struct eisa_device *e_dev, int rid); 991558Srgrimesstatic struct resvaddr * eisa_find_ioaddr(struct eisa_device *e_dev, int rid); 10034266Sjulian 1011558Srgrimesstatic int 1021558Srgrimesmainboard_probe(device_t dev) 1031558Srgrimes{ 1041558Srgrimes char *idstring; 1051558Srgrimes eisa_id_t id = eisa_get_id(dev); 1061558Srgrimes 1071558Srgrimes if (eisa_get_slot(dev) != 0) 1081558Srgrimes return (ENXIO); 1091558Srgrimes 1101558Srgrimes idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1, 11134266Sjulian M_DEVBUF, M_NOWAIT); 11234266Sjulian if (idstring == NULL) 11334266Sjulian panic("Eisa probe unable to malloc"); 1141558Srgrimes sprintf(idstring, "%c%c%c%03x%01x (System Board)", 11534266Sjulian EISA_MFCTR_CHAR0(id), EISA_MFCTR_CHAR1(id), EISA_MFCTR_CHAR2(id), 11634266Sjulian EISA_PRODUCT_ID(id), EISA_REVISION_ID(id)); 1171558Srgrimes device_set_desc(dev, idstring); 1181558Srgrimes 1191558Srgrimes return (0); 1201558Srgrimes} 12134266Sjulian 1221558Srgrimesstatic int 1231558Srgrimesmainboard_attach(device_t dev) 1241558Srgrimes{ 1251558Srgrimes return (0); 12641474Sjulian} 12741474Sjulian 12841474Sjulianstatic device_method_t mainboard_methods[] = { 12941474Sjulian /* Device interface */ 13041474Sjulian DEVMETHOD(device_probe, mainboard_probe), 13141474Sjulian DEVMETHOD(device_attach, mainboard_attach), 13241474Sjulian 13341474Sjulian { 0, 0 } 13441474Sjulian}; 13541474Sjulian 13641474Sjulianstatic driver_t mainboard_driver = { 13741474Sjulian "mainboard", 13841474Sjulian mainboard_methods, 13941474Sjulian 1, 14041474Sjulian}; 14141474Sjulian 14241474Sjulianstatic devclass_t mainboard_devclass; 14341474Sjulian 14441474SjulianDRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0); 14541474Sjulian 1461558Srgrimes/* 1471558Srgrimes** probe for EISA devices 1487585Sbde*/ 1491558Srgrimesstatic int 1501558Srgrimeseisa_probe(device_t dev) 1511558Srgrimes{ 1521558Srgrimes int devices_found, slot; 1531558Srgrimes struct eisa_device *e_dev; 1541558Srgrimes device_t child; 1551558Srgrimes eisa_id_t eisa_id; 1561558Srgrimes 1571558Srgrimes device_set_desc(dev, "EISA bus"); 15823675Speter 1591558Srgrimes devices_found = 0; 1601558Srgrimes for (slot = 0; slot < num_eisa_slots; slot++) { 1611558Srgrimes eisa_id = 0; 1621558Srgrimes if (eisa_probe_slot(slot, &eisa_id)) { 1631558Srgrimes /* 1641558Srgrimes * If there's no card in the first slot (the 1651558Srgrimes * mainboard), then the system doesn't have EISA. 1661558Srgrimes * We abort the probe early in this case since 1671558Srgrimes * continuing on causes a hang on some systems. 1681558Srgrimes * Interestingly enough, the inb has been seen to 1691558Srgrimes * cause the hang. 1701558Srgrimes */ 17123675Speter if (slot == 0) 1721558Srgrimes break; 1731558Srgrimes continue; 1741558Srgrimes } 1751558Srgrimes 1761558Srgrimes devices_found++; 1771558Srgrimes 1781558Srgrimes /* Prepare an eisa_device_node for this slot */ 1791558Srgrimes e_dev = (struct eisa_device *)malloc(sizeof(*e_dev), 1801558Srgrimes M_DEVBUF, M_NOWAIT|M_ZERO); 1811558Srgrimes if (!e_dev) { 1821558Srgrimes device_printf(dev, "cannot malloc eisa_device"); 1831558Srgrimes break; /* Try to attach what we have already */ 1841558Srgrimes } 1851558Srgrimes 1861558Srgrimes e_dev->id = eisa_id; 1871558Srgrimes e_dev->ioconf.slot = slot; 18823675Speter 1891558Srgrimes /* Initialize our lists of reserved addresses */ 1901558Srgrimes LIST_INIT(&(e_dev->ioconf.ioaddrs)); 1911558Srgrimes LIST_INIT(&(e_dev->ioconf.maddrs)); 1921558Srgrimes TAILQ_INIT(&(e_dev->ioconf.irqs)); 1931558Srgrimes 1941558Srgrimes child = device_add_child(dev, NULL, -1); 1951558Srgrimes device_set_ivars(child, e_dev); 1961558Srgrimes } 1971558Srgrimes 1981558Srgrimes /* 1991558Srgrimes * EISA busses themselves are not easily detectable, the easiest way 20023675Speter * to tell if there is an eisa bus is if we found something - there 2011558Srgrimes * should be a motherboard "card" there somewhere. 2021558Srgrimes */ 2031558Srgrimes return (devices_found ? 0 : ENXIO); 2041558Srgrimes} 2051558Srgrimes 2061558Srgrimesstatic int 2071558Srgrimeseisa_probe_slot(int slot, eisa_id_t *eisa_id) 2081558Srgrimes{ 2091558Srgrimes eisa_id_t probe_id; 2101558Srgrimes int base, i, id_size; 2111558Srgrimes 2121558Srgrimes probe_id = 0; 2131558Srgrimes id_size = sizeof(probe_id); 2141558Srgrimes base = 0x0c80 + (slot * 0x1000); 2151558Srgrimes 2161558Srgrimes for (i = 0; i < id_size; i++) 2171558Srgrimes probe_id |= inb(base + i) << ((id_size - i - 1) * CHAR_BIT); 21823675Speter 2191558Srgrimes /* If we found a card, return its EISA id. */ 2201558Srgrimes if ((probe_id & 0x80000000) == 0) { 22123675Speter *eisa_id = probe_id; 2221558Srgrimes return (0); 2231558Srgrimes } 2241558Srgrimes 2251558Srgrimes return (ENXIO); 2261558Srgrimes} 2271558Srgrimes 2281558Srgrimesstatic void 2291558Srgrimeseisa_probe_nomatch(device_t dev, device_t child) 2301558Srgrimes{ 2311558Srgrimes u_int32_t eisa_id = eisa_get_id(child); 2321558Srgrimes u_int8_t slot = eisa_get_slot(child); 2337585Sbde 2341558Srgrimes device_printf(dev, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n", 2351558Srgrimes EISA_MFCTR_CHAR0(eisa_id), EISA_MFCTR_CHAR1(eisa_id), 2361558Srgrimes EISA_MFCTR_CHAR2(eisa_id), EISA_PRODUCT_ID(eisa_id), 2371558Srgrimes EISA_REVISION_ID(eisa_id), eisa_id, slot); 2381558Srgrimes return; 2391558Srgrimes} 2401558Srgrimes 2411558Srgrimesstatic void 2421558Srgrimeseisa_reg_print (device_t dev, char *string, char *separator, int *column) 2431558Srgrimes{ 2441558Srgrimes int length = strlen(string); 2451558Srgrimes 2461558Srgrimes length += (separator ? 2 : 1); 2471558Srgrimes 2481558Srgrimes if (((*column) + length) >= MAX_COL) { 2491558Srgrimes printf("\n"); 2501558Srgrimes (*column) = 0; 2511558Srgrimes } else if ((*column) != 0) { 2521558Srgrimes if (separator) { 2531558Srgrimes printf("%c", *separator); 2541558Srgrimes (*column)++; 2551558Srgrimes } 2561558Srgrimes printf(" "); 2571558Srgrimes (*column)++; 2581558Srgrimes } 25923675Speter 2601558Srgrimes if ((*column) == 0) 2611558Srgrimes (*column) += device_printf(dev, "%s", string); 26223675Speter else 2631558Srgrimes (*column) += printf("%s", string); 2641558Srgrimes 2651558Srgrimes return; 2661558Srgrimes} 2671558Srgrimes 2681558Srgrimesstatic int 26923675Spetereisa_print_child(device_t dev, device_t child) 2701558Srgrimes{ 2711558Srgrimes char buf[81]; 2727585Sbde struct eisa_device * e_dev = device_get_ivars(child); 27323675Speter int rid; 27423675Speter struct irq_node * irq; 2751558Srgrimes struct resvaddr * resv; 2761558Srgrimes char separator = ','; 27723675Speter int column = 0; 2781558Srgrimes int retval = 0; 2791558Srgrimes 2801558Srgrimes if (device_get_desc(child)) { 2811558Srgrimes snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child)); 2821558Srgrimes eisa_reg_print(child, buf, NULL, &column); 2831558Srgrimes } 2841558Srgrimes 2851558Srgrimes rid = 0; 2861558Srgrimes while ((resv = eisa_find_ioaddr(e_dev, rid++))) { 2871558Srgrimes if (resv->size == 1 || (resv->flags & RESVADDR_BITMASK)) 2881558Srgrimes snprintf(buf, sizeof(buf), "%s%lx", 2891558Srgrimes rid == 1 ? "at 0x" : "0x", resv->addr); 2901558Srgrimes else 2911558Srgrimes snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 2921558Srgrimes rid == 1 ? "at 0x" : "0x", resv->addr, 2931558Srgrimes resv->addr + resv->size - 1); 2941558Srgrimes eisa_reg_print(child, buf, rid == 2 ? &separator : NULL, 2951558Srgrimes &column); 2961558Srgrimes } 2971558Srgrimes 2981558Srgrimes rid = 0; 2991558Srgrimes while ((resv = eisa_find_maddr(e_dev, rid++))) { 30041477Sjulian if (resv->size == 1 || (resv->flags & RESVADDR_BITMASK)) 3011558Srgrimes snprintf(buf, sizeof(buf), "%s%lx", 30241474Sjulian rid == 1 ? "at 0x" : "0x", resv->addr); 30341474Sjulian else 30423675Speter snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 30523675Speter rid == 1 ? "at 0x" : "0x", 30623675Speter resv->addr, resv->addr + resv->size - 1); 30723675Speter eisa_reg_print(child, buf, rid == 2 ? &separator : NULL, 30841474Sjulian &column); 30941474Sjulian } 31041474Sjulian 31141474Sjulian rid = 0; 31241474Sjulian while ((irq = eisa_find_irq(e_dev, rid++)) != NULL) { 31341474Sjulian snprintf(buf, sizeof(buf), "irq %d (%s)", irq->irq_no, 31441474Sjulian irq->irq_trigger ? "level" : "edge"); 31541474Sjulian eisa_reg_print(child, buf, rid == 1 ? &separator : NULL, 31641474Sjulian &column); 31723675Speter } 3181558Srgrimes 3191558Srgrimes snprintf(buf, sizeof(buf), "on %s slot %d\n", 3201558Srgrimes device_get_nameunit(dev), eisa_get_slot(child)); 3211558Srgrimes eisa_reg_print(child, buf, NULL, &column); 3221558Srgrimes 3231558Srgrimes return (retval); 3241558Srgrimes} 3257585Sbde 3261558Srgrimesstatic struct irq_node * 3271558Srgrimeseisa_find_irq(struct eisa_device *e_dev, int rid) 3281558Srgrimes{ 32923675Speter int i; 3301558Srgrimes struct irq_node *irq; 3311558Srgrimes 3321558Srgrimes for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 3331558Srgrimes i < rid && irq != NULL; i++, irq = TAILQ_NEXT(irq, links)) 3341558Srgrimes continue; 3351558Srgrimes 3361558Srgrimes return (irq); 3371558Srgrimes} 3381558Srgrimes 3391558Srgrimesstatic struct resvaddr * 3401558Srgrimeseisa_find_maddr(struct eisa_device *e_dev, int rid) 3411558Srgrimes{ 3421558Srgrimes int i; 3431558Srgrimes struct resvaddr *resv; 3441558Srgrimes 3451558Srgrimes for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs); 34623675Speter i < rid && resv != NULL; i++, resv = LIST_NEXT(resv, links)) 3471558Srgrimes continue; 3481558Srgrimes 3491558Srgrimes return (resv); 3501558Srgrimes} 3511558Srgrimes 3521558Srgrimesstatic struct resvaddr * 3531558Srgrimeseisa_find_ioaddr(struct eisa_device *e_dev, int rid) 3541558Srgrimes{ 3551558Srgrimes int i; 3561558Srgrimes struct resvaddr *resv; 3571558Srgrimes 3581558Srgrimes for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs); 3591558Srgrimes i < rid && resv != NULL; i++, resv = LIST_NEXT(resv, links)) 3601558Srgrimes continue; 36141474Sjulian 36241474Sjulian return (resv); 3631558Srgrimes} 3641558Srgrimes 3651558Srgrimesstatic int 3667585Sbdeeisa_read_ivar(device_t dev, device_t child, int which, u_long *result) 3671558Srgrimes{ 3681558Srgrimes struct eisa_device *e_dev = device_get_ivars(child); 3691558Srgrimes struct irq_node *irq; 37023675Speter 3711558Srgrimes switch (which) { 3721558Srgrimes case EISA_IVAR_SLOT: 3731558Srgrimes *result = e_dev->ioconf.slot; 3741558Srgrimes break; 3751558Srgrimes 3761558Srgrimes case EISA_IVAR_ID: 3771558Srgrimes *result = e_dev->id; 3781558Srgrimes break; 3791558Srgrimes 3801558Srgrimes case EISA_IVAR_IRQ: 3811558Srgrimes /* XXX only first irq */ 3821558Srgrimes if ((irq = eisa_find_irq(e_dev, 0)) != NULL) 3831558Srgrimes *result = irq->irq_no; 3841558Srgrimes else 3851558Srgrimes *result = -1; 3861558Srgrimes break; 38741474Sjulian 3881558Srgrimes default: 3891558Srgrimes return (ENOENT); 3901558Srgrimes } 3911558Srgrimes 3921558Srgrimes return (0); 3931558Srgrimes} 3941558Srgrimes 3951558Srgrimesstatic int 3961558Srgrimeseisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 3971558Srgrimes{ 3981558Srgrimes return (EINVAL); 3991558Srgrimes} 4001558Srgrimes 4011558Srgrimesstatic struct resource * 4021558Srgrimeseisa_alloc_resource(device_t dev, device_t child, int type, int *rid, 4031558Srgrimes u_long start, u_long end, u_long count, u_int flags) 40423675Speter{ 4051558Srgrimes int isdefault; 4061558Srgrimes struct eisa_device *e_dev = device_get_ivars(child); 4071558Srgrimes struct resource *rv, **rvp = 0; 40834266Sjulian 40934266Sjulian isdefault = (device_get_parent(child) == dev && 4101558Srgrimes start == 0UL && end == ~0UL && count == 1); 4111558Srgrimes 4121558Srgrimes switch (type) { 4131558Srgrimes case SYS_RES_IRQ: 4141558Srgrimes if (isdefault) { 4151558Srgrimes struct irq_node * irq = eisa_find_irq(e_dev, *rid); 4161558Srgrimes if (irq == NULL) 4171558Srgrimes return (NULL); 4181558Srgrimes start = end = irq->irq_no; 4191558Srgrimes count = 1; 4201558Srgrimes if (irq->irq_trigger == EISA_TRIGGER_LEVEL) 4211558Srgrimes flags |= RF_SHAREABLE; 4221558Srgrimes else 4231558Srgrimes flags &= ~RF_SHAREABLE; 42434266Sjulian } 42534266Sjulian break; 42634266Sjulian 42734266Sjulian case SYS_RES_MEMORY: 42834266Sjulian if (isdefault) { 42934266Sjulian struct resvaddr *resv; 4301558Srgrimes 43134266Sjulian resv = eisa_find_maddr(e_dev, *rid); 43234266Sjulian if (resv == NULL) 4331558Srgrimes return (NULL); 43434266Sjulian 43534266Sjulian start = resv->addr; 43634266Sjulian end = resv->addr + (resv->size - 1); 43734266Sjulian count = resv->size; 43834266Sjulian rvp = &resv->res; 4391558Srgrimes } 4401558Srgrimes break; 4411558Srgrimes 4421558Srgrimes case SYS_RES_IOPORT: 4431558Srgrimes if (isdefault) { 4441558Srgrimes struct resvaddr *resv; 4451558Srgrimes 4461558Srgrimes resv = eisa_find_ioaddr(e_dev, *rid); 4471558Srgrimes if (resv == NULL) 4487585Sbde return (NULL); 4491558Srgrimes 45023675Speter start = resv->addr; 4511558Srgrimes end = resv->addr + (resv->size - 1); 4521558Srgrimes count = resv->size; 4531558Srgrimes rvp = &resv->res; 4541558Srgrimes } 4551558Srgrimes break; 4561558Srgrimes 4571558Srgrimes default: 4581558Srgrimes return 0; 4591558Srgrimes } 4601558Srgrimes 4611558Srgrimes rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 4621558Srgrimes type, rid, start, end, count, flags); 4637585Sbde if (rvp) 4641558Srgrimes *rvp = rv; 4651558Srgrimes 4661558Srgrimes return (rv); 4671558Srgrimes} 4681558Srgrimes 4691558Srgrimesstatic int 4701558Srgrimeseisa_release_resource(device_t dev, device_t child, int type, int rid, 4711558Srgrimes struct resource *r) 4721558Srgrimes{ 4731558Srgrimes int rv; 4741558Srgrimes struct eisa_device *e_dev = device_get_ivars(child); 4751558Srgrimes struct resvaddr *resv = 0; 4761558Srgrimes 4771558Srgrimes switch (type) { 47841474Sjulian case SYS_RES_IRQ: 47941474Sjulian if (eisa_find_irq(e_dev, rid) == NULL) 4801558Srgrimes return (EINVAL); 4811558Srgrimes break; 4821558Srgrimes 4831558Srgrimes case SYS_RES_MEMORY: 48423675Speter if (device_get_parent(child) == dev) 4851558Srgrimes resv = eisa_find_maddr(e_dev, rid); 4861558Srgrimes break; 4871558Srgrimes 4881558Srgrimes 4891558Srgrimes case SYS_RES_IOPORT: 4901558Srgrimes if (device_get_parent(child) == dev) 4911558Srgrimes resv = eisa_find_ioaddr(e_dev, rid); 4921558Srgrimes break; 4931558Srgrimes 4941558Srgrimes default: 4951558Srgrimes return (ENOENT); 4961558Srgrimes } 4971558Srgrimes 4981558Srgrimes rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 4991558Srgrimes 5001558Srgrimes if (rv == 0) { 5011558Srgrimes if (resv != NULL) 5021558Srgrimes resv->res = 0; 5031558Srgrimes } 5041558Srgrimes 5051558Srgrimes return (rv); 5061558Srgrimes} 5071558Srgrimes 50823675Speterstatic int 5091558Srgrimeseisa_add_intr_m(device_t eisa, device_t dev, int irq, int trigger) 5101558Srgrimes{ 5111558Srgrimes struct eisa_device *e_dev = device_get_ivars(dev); 5121558Srgrimes struct irq_node *irq_info; 5131558Srgrimes 5141558Srgrimes irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF, 5151558Srgrimes M_NOWAIT); 5161558Srgrimes if (irq_info == NULL) 51723675Speter return (1); 5181558Srgrimes 5191558Srgrimes irq_info->irq_no = irq; 5201558Srgrimes irq_info->irq_trigger = trigger; 52123675Speter irq_info->idesc = NULL; 52223675Speter TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links); 5231558Srgrimes return (0); 5241558Srgrimes} 52523675Speter 5261558Srgrimesstatic int 5271558Srgrimeseisa_add_resvaddr(struct eisa_device *e_dev, struct resvlist *head, u_long base, 5281558Srgrimes u_long size, int flags) 5291558Srgrimes{ 5301558Srgrimes resvaddr_t *reservation; 5311558Srgrimes 5321558Srgrimes reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t), 5331558Srgrimes M_DEVBUF, M_NOWAIT); 5341558Srgrimes if(!reservation) 53523675Speter return (ENOMEM); 53623675Speter 5371558Srgrimes reservation->addr = base; 5381558Srgrimes reservation->size = size; 5391558Srgrimes reservation->flags = flags; 5401558Srgrimes 5411558Srgrimes if (!LIST_FIRST(head)) { 5421558Srgrimes LIST_INSERT_HEAD(head, reservation, links); 5431558Srgrimes } 5441558Srgrimes else { 5451558Srgrimes resvaddr_t *node; 5461558Srgrimes LIST_FOREACH(node, head, links) { 5471558Srgrimes if (node->addr > reservation->addr) { 54823675Speter /* 54923675Speter * List is sorted in increasing 5501558Srgrimes * address order. 5511558Srgrimes */ 5521558Srgrimes LIST_INSERT_BEFORE(node, reservation, links); 5531558Srgrimes break; 5541558Srgrimes } 5551558Srgrimes 5561558Srgrimes if (node->addr == reservation->addr) { 5571558Srgrimes /* 5581558Srgrimes * If the entry we want to add 5591558Srgrimes * matches any already in here, 5607585Sbde * fail. 5611558Srgrimes */ 5621558Srgrimes free(reservation, M_DEVBUF); 5631558Srgrimes return (EEXIST); 5641558Srgrimes } 5651558Srgrimes 5661558Srgrimes if (!LIST_NEXT(node, links)) { 5671558Srgrimes LIST_INSERT_AFTER(node, reservation, links); 5681558Srgrimes break; 5691558Srgrimes } 5701558Srgrimes } 5711558Srgrimes } 57266861Sadrian return (0); 5731558Srgrimes} 5741558Srgrimes 5751558Srgrimesstatic int 5761558Srgrimeseisa_add_mspace_m(device_t eisa, device_t dev, u_long mbase, u_long msize, 5771558Srgrimes int flags) 5781558Srgrimes{ 5791558Srgrimes struct eisa_device *e_dev = device_get_ivars(dev); 5801558Srgrimes 5811558Srgrimes return (eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize, 5821558Srgrimes flags)); 5831558Srgrimes} 5841558Srgrimes 5851558Srgrimesstatic int 5861558Srgrimeseisa_add_iospace_m(device_t eisa, device_t dev, u_long iobase, u_long iosize, 5871558Srgrimes int flags) 5881558Srgrimes{ 5891558Srgrimes struct eisa_device *e_dev = device_get_ivars(dev); 5901558Srgrimes 5911558Srgrimes return (eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase, 5921558Srgrimes iosize, flags)); 59323675Speter} 5941558Srgrimes 5951558Srgrimesstatic device_method_t eisa_methods[] = { 59623675Speter /* Device interface */ 5971558Srgrimes DEVMETHOD(device_probe, eisa_probe), 5981558Srgrimes DEVMETHOD(device_attach, bus_generic_attach), 59923675Speter DEVMETHOD(device_shutdown, bus_generic_shutdown), 60023675Speter DEVMETHOD(device_suspend, bus_generic_suspend), 60123675Speter DEVMETHOD(device_resume, bus_generic_resume), 60223675Speter 60323675Speter /* Bus interface */ 6041558Srgrimes DEVMETHOD(bus_print_child, eisa_print_child), 6051558Srgrimes DEVMETHOD(bus_probe_nomatch, eisa_probe_nomatch), 6061558Srgrimes DEVMETHOD(bus_read_ivar, eisa_read_ivar), 60734266Sjulian DEVMETHOD(bus_write_ivar, eisa_write_ivar), 60834266Sjulian DEVMETHOD(bus_driver_added, bus_generic_driver_added), 6091558Srgrimes DEVMETHOD(bus_alloc_resource, eisa_alloc_resource), 6107585Sbde DEVMETHOD(bus_release_resource, eisa_release_resource), 61123675Speter DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 61223675Speter DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 61323675Speter DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 61423675Speter DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 61523675Speter 61623675Speter /* EISA interface */ 61723675Speter DEVMETHOD(eisa_add_intr, eisa_add_intr_m), 6181558Srgrimes DEVMETHOD(eisa_add_iospace, eisa_add_iospace_m), 6197585Sbde DEVMETHOD(eisa_add_mspace, eisa_add_mspace_m), 62023675Speter 62123675Speter { 0, 0 } 62223675Speter}; 62323675Speter 62423675Speterstatic driver_t eisa_driver = { 62523675Speter "eisa", 62623675Speter eisa_methods, 62723675Speter 1, /* no softc */ 62834266Sjulian}; 62934266Sjulian 63041474SjulianDRIVER_MODULE(eisa, eisab, eisa_driver, eisa_devclass, 0, 0); 63123675SpeterDRIVER_MODULE(eisa, legacy, eisa_driver, eisa_devclass, 0, 0); 6321558Srgrimes