eisaconf.c revision 114216
18012Sjulian/* 212090Sgibbs * EISA bus probe and attach routines 38012Sjulian * 413691Sgibbs * Copyright (c) 1995, 1996 Justin T. Gibbs. 512090Sgibbs * All rights reserved. 615329Sgibbs * 712090Sgibbs * Redistribution and use in source and binary forms, with or without 812090Sgibbs * modification, are permitted provided that the following conditions 912090Sgibbs * are met: 1012090Sgibbs * 1. Redistributions of source code must retain the above copyright 1112090Sgibbs * notice immediately at the beginning of the file, without modification, 1212090Sgibbs * this list of conditions, and the following disclaimer. 1312090Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1412090Sgibbs * notice, this list of conditions and the following disclaimer in the 1512090Sgibbs * documentation and/or other materials provided with the distribution. 1615329Sgibbs * 3. The name of the author may not be used to endorse or promote products 1715329Sgibbs * derived from this software without specific prior written permission. 1815329Sgibbs * 1915329Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2015329Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2115329Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2215329Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2315329Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2415329Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2515329Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2615329Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2715329Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2815329Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2915329Sgibbs * SUCH DAMAGE. 308012Sjulian * 3150477Speter * $FreeBSD: head/sys/dev/eisa/eisaconf.c 114216 2003-04-29 13:36:06Z kan $ 328012Sjulian */ 3323855Sjoerg 3423855Sjoerg#include "opt_eisa.h" 3523855Sjoerg 368012Sjulian#include <sys/param.h> 3712090Sgibbs#include <sys/systm.h> 3845791Speter#include <sys/queue.h> 39114216Skan#include <sys/limits.h> 4012090Sgibbs#include <sys/malloc.h> 4145791Speter#include <sys/kernel.h> 4245791Speter#include <sys/module.h> 4345791Speter#include <sys/bus.h> 448012Sjulian 4545791Speter#include <machine/bus.h> 4645791Speter#include <machine/resource.h> 4745791Speter#include <sys/rman.h> 4828551Sbde 4955953Speter#include <dev/eisa/eisaconf.h> 508012Sjulian 5145791Spetertypedef struct resvaddr { 5245791Speter u_long addr; /* start address */ 5345791Speter u_long size; /* size of reserved area */ 5445791Speter int flags; 5545791Speter struct resource *res; /* resource manager handle */ 5660938Sjake LIST_ENTRY(resvaddr) links; /* List links */ 5745791Speter} resvaddr_t; 5845791Speter 5960938SjakeLIST_HEAD(resvlist, resvaddr); 6045791Speter 6145791Speterstruct irq_node { 6245791Speter int irq_no; 6349360Smdodd int irq_trigger; 6445791Speter void *idesc; 6560938Sjake TAILQ_ENTRY(irq_node) links; 6612090Sgibbs}; 678012Sjulian 6860938SjakeTAILQ_HEAD(irqlist, irq_node); 6912090Sgibbs 7045791Speterstruct eisa_ioconf { 7145791Speter int slot; 7245791Speter struct resvlist ioaddrs; /* list of reserved I/O ranges */ 7345791Speter struct resvlist maddrs; /* list of reserved memory ranges */ 7445791Speter struct irqlist irqs; /* list of reserved irqs */ 7545791Speter}; 7612177Sgibbs 7745791Speter/* To be replaced by the "super device" generic device structure... */ 7845791Speterstruct eisa_device { 7945791Speter eisa_id_t id; 8045791Speter struct eisa_ioconf ioconf; 8145791Speter}; 8212177Sgibbs 8345791Speter 8449281Smdodd#define MAX_COL 79 8523855Sjoerg#ifndef EISA_SLOTS 8623855Sjoerg#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */ 8723855Sjoerg#endif 8820450Sjoergint num_eisa_slots = EISA_SLOTS; 89106229SpeterTUNABLE_INT("hw.eisa_slots", &num_eisa_slots); 9045791Speter 9145791Speterstatic devclass_t eisa_devclass; 9245791Speter 9349281Smdoddstatic void eisa_reg_print (device_t, char *, char *, int *); 9449360Smdoddstatic struct irq_node * eisa_find_irq(struct eisa_device *e_dev, int rid); 9549281Smdoddstatic struct resvaddr * eisa_find_maddr(struct eisa_device *e_dev, int rid); 9649281Smdoddstatic struct resvaddr * eisa_find_ioaddr(struct eisa_device *e_dev, int rid); 9749281Smdodd 9845791Speterstatic int 9945791Spetermainboard_probe(device_t dev) 10045791Speter{ 10145791Speter char *idstring; 10245791Speter eisa_id_t id = eisa_get_id(dev); 10345791Speter 10445791Speter if (eisa_get_slot(dev) != 0) 10545791Speter return (ENXIO); 10645791Speter 10745791Speter idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1, 10845791Speter M_DEVBUF, M_NOWAIT); 10945791Speter if (idstring == NULL) { 11045791Speter panic("Eisa probe unable to malloc"); 11145791Speter } 11248754Sdfr sprintf(idstring, "%c%c%c%03x%01x (System Board)", 11345791Speter EISA_MFCTR_CHAR0(id), 11445791Speter EISA_MFCTR_CHAR1(id), 11545791Speter EISA_MFCTR_CHAR2(id), 11645791Speter EISA_PRODUCT_ID(id), 11745791Speter EISA_REVISION_ID(id)); 11845791Speter device_set_desc(dev, idstring); 11945791Speter 12045791Speter return (0); 12145791Speter} 12245791Speter 12345791Speterstatic int 12445791Spetermainboard_attach(device_t dev) 12545791Speter{ 12645818Speter return (0); 12745791Speter} 12845791Speter 12945791Speterstatic device_method_t mainboard_methods[] = { 13045791Speter /* Device interface */ 13145791Speter DEVMETHOD(device_probe, mainboard_probe), 13245791Speter DEVMETHOD(device_attach, mainboard_attach), 13345791Speter 13445791Speter { 0, 0 } 13545791Speter}; 13645791Speter 13745791Speterstatic driver_t mainboard_driver = { 13845791Speter "mainboard", 13945791Speter mainboard_methods, 14045791Speter 1, 14145791Speter}; 14245791Speter 14345791Speterstatic devclass_t mainboard_devclass; 14445791Speter 14545791SpeterDRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0); 14613691Sgibbs 14713691Sgibbs/* 1488012Sjulian** probe for EISA devices 1498012Sjulian*/ 15045791Speterstatic int 15145791Spetereisa_probe(device_t dev) 1528012Sjulian{ 15312157Sgibbs int i,slot; 15412157Sgibbs struct eisa_device *e_dev; 15554073Smdodd device_t child; 15612157Sgibbs int eisaBase = 0xc80; 15712157Sgibbs eisa_id_t eisa_id; 15847308Speter int devices_found = 0; 1598012Sjulian 16045804Speter device_set_desc(dev, "EISA bus"); 16145804Speter 16220450Sjoerg for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) { 16312157Sgibbs int id_size = sizeof(eisa_id); 16412157Sgibbs eisa_id = 0; 16512157Sgibbs for( i = 0; i < id_size; i++ ) { 16613179Sgibbs outb(eisaBase,0x80 + i); /*Some cards require priming*/ 16712157Sgibbs eisa_id |= inb(eisaBase+i) << ((id_size-i-1)*CHAR_BIT); 16812157Sgibbs } 16912157Sgibbs if (eisa_id & 0x80000000) 17012157Sgibbs continue; /* no EISA card in slot */ 17112157Sgibbs 17247308Speter devices_found++; 17347308Speter 17412157Sgibbs /* Prepare an eisa_device_node for this slot */ 17545791Speter e_dev = (struct eisa_device *)malloc(sizeof(*e_dev), 17669781Sdwmalone M_DEVBUF, M_NOWAIT|M_ZERO); 17745791Speter if (!e_dev) { 17845818Speter device_printf(dev, "cannot malloc eisa_device"); 17912157Sgibbs break; /* Try to attach what we have already */ 18012157Sgibbs } 18113691Sgibbs 18212157Sgibbs e_dev->id = eisa_id; 18313691Sgibbs 18412157Sgibbs e_dev->ioconf.slot = slot; 18513691Sgibbs 18613691Sgibbs /* Initialize our lists of reserved addresses */ 18713691Sgibbs LIST_INIT(&(e_dev->ioconf.ioaddrs)); 18813691Sgibbs LIST_INIT(&(e_dev->ioconf.maddrs)); 18929674Sgibbs TAILQ_INIT(&(e_dev->ioconf.irqs)); 19013691Sgibbs 19154073Smdodd child = device_add_child(dev, NULL, -1); 19254073Smdodd device_set_ivars(child, e_dev); 19312090Sgibbs } 1948012Sjulian 19547308Speter /* 19647308Speter * EISA busses themselves are not easily detectable, the easiest way 19747308Speter * to tell if there is an eisa bus is if we found something - there 19847308Speter * should be a motherboard "card" there somewhere. 19947308Speter */ 20047308Speter return devices_found ? 0 : ENXIO; 20145791Speter} 20212157Sgibbs 20345791Speterstatic void 20448754Sdfreisa_probe_nomatch(device_t dev, device_t child) 20548754Sdfr{ 20648754Sdfr u_int32_t eisa_id = eisa_get_id(child); 20748754Sdfr u_int8_t slot = eisa_get_slot(child); 20848754Sdfr 20948754Sdfr device_printf(dev, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n", 21048754Sdfr EISA_MFCTR_CHAR0(eisa_id), 21148754Sdfr EISA_MFCTR_CHAR1(eisa_id), 21248754Sdfr EISA_MFCTR_CHAR2(eisa_id), 21348754Sdfr EISA_PRODUCT_ID(eisa_id), 21448754Sdfr EISA_REVISION_ID(eisa_id), 21548754Sdfr eisa_id, 21648754Sdfr slot); 21748754Sdfr 21848754Sdfr return; 21948754Sdfr} 22048754Sdfr 22149281Smdoddstatic void 22249281Smdoddeisa_reg_print (dev, string, separator, column) 22349281Smdodd device_t dev; 22449281Smdodd char * string; 22549281Smdodd char * separator; 22649281Smdodd int * column; 22749281Smdodd{ 22849281Smdodd int length = strlen(string); 22949281Smdodd 23049281Smdodd length += (separator ? 2 : 1); 23149281Smdodd 23249281Smdodd if (((*column) + length) >= MAX_COL) { 23349281Smdodd printf("\n"); 23449281Smdodd (*column) = 0; 23549281Smdodd } else if ((*column) != 0) { 23649281Smdodd if (separator) { 23749281Smdodd printf("%c", *separator); 23849281Smdodd (*column)++; 23949281Smdodd } 24049281Smdodd printf(" "); 24149281Smdodd (*column)++; 24249281Smdodd } 24349281Smdodd 24449281Smdodd if ((*column) == 0) { 24549281Smdodd (*column) += device_printf(dev, "%s", string); 24649281Smdodd } else { 24749281Smdodd (*column) += printf("%s", string); 24849281Smdodd } 24949281Smdodd 25049281Smdodd return; 25149281Smdodd} 25249281Smdodd 25349195Smdoddstatic int 25445791Spetereisa_print_child(device_t dev, device_t child) 25545791Speter{ 25649281Smdodd char buf[81]; 25749281Smdodd struct eisa_device * e_dev = device_get_ivars(child); 25849281Smdodd int rid; 25949382Smdodd struct irq_node * irq; 26049281Smdodd struct resvaddr * resv; 26149281Smdodd char separator = ','; 26249281Smdodd int column = 0; 26349281Smdodd int retval = 0; 26449195Smdodd 26549281Smdodd if (device_get_desc(child)) { 26649281Smdodd snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child)); 26749281Smdodd eisa_reg_print(child, buf, NULL, &column); 26849281Smdodd } 26949195Smdodd 27049281Smdodd rid = 0; 27149281Smdodd while ((resv = eisa_find_ioaddr(e_dev, rid++))) { 27249281Smdodd if ((resv->size == 1) || 27349281Smdodd (resv->flags & RESVADDR_BITMASK)) { 27449281Smdodd snprintf(buf, sizeof(buf), "%s%lx", 27549281Smdodd ((rid == 1) ? "at 0x" : "0x"), 27649281Smdodd resv->addr); 27749281Smdodd } else { 27849281Smdodd snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 27949281Smdodd ((rid == 1) ? "at 0x" : "0x"), 28049281Smdodd resv->addr, 28149281Smdodd (resv->addr + (resv->size - 1))); 28249281Smdodd } 28349281Smdodd eisa_reg_print(child, buf, 28449281Smdodd ((rid == 2) ? &separator : NULL), &column); 28549281Smdodd } 28649195Smdodd 28749281Smdodd rid = 0; 28849281Smdodd while ((resv = eisa_find_maddr(e_dev, rid++))) { 28949281Smdodd if ((resv->size == 1) || 29049281Smdodd (resv->flags & RESVADDR_BITMASK)) { 29149281Smdodd snprintf(buf, sizeof(buf), "%s%lx", 29249281Smdodd ((rid == 1) ? "at 0x" : "0x"), 29349281Smdodd resv->addr); 29449281Smdodd } else { 29549281Smdodd snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 29649281Smdodd ((rid == 1) ? "at 0x" : "0x"), 29749281Smdodd resv->addr, 29849281Smdodd (resv->addr + (resv->size - 1))); 29949281Smdodd } 30049281Smdodd eisa_reg_print(child, buf, 30149281Smdodd ((rid == 2) ? &separator : NULL), &column); 30249281Smdodd } 30349281Smdodd 30449281Smdodd rid = 0; 30549360Smdodd while ((irq = eisa_find_irq(e_dev, rid++)) != NULL) { 30649360Smdodd snprintf(buf, sizeof(buf), "irq %d (%s)", irq->irq_no, 30749360Smdodd (irq->irq_trigger ? "level" : "edge")); 30849281Smdodd eisa_reg_print(child, buf, 30949281Smdodd ((rid == 1) ? &separator : NULL), &column); 31049281Smdodd } 31149281Smdodd 31249281Smdodd snprintf(buf, sizeof(buf), "on %s slot %d\n", 31349281Smdodd device_get_nameunit(dev), eisa_get_slot(child)); 31449281Smdodd eisa_reg_print(child, buf, NULL, &column); 31549281Smdodd 31649195Smdodd return (retval); 31745791Speter} 3188012Sjulian 31949360Smdoddstatic struct irq_node * 32045791Spetereisa_find_irq(struct eisa_device *e_dev, int rid) 32145791Speter{ 32245791Speter int i; 32345791Speter struct irq_node *irq; 32429674Sgibbs 32545791Speter for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 32645791Speter i < rid && irq; 32745791Speter i++, irq = TAILQ_NEXT(irq, links)) 32845791Speter ; 32945791Speter 33045791Speter if (irq) 33149360Smdodd return (irq); 33245791Speter else 33349360Smdodd return (NULL); 33445791Speter} 3358012Sjulian 33645791Speterstatic struct resvaddr * 33745791Spetereisa_find_maddr(struct eisa_device *e_dev, int rid) 33845791Speter{ 33945791Speter int i; 34045791Speter struct resvaddr *resv; 3418012Sjulian 34245791Speter for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs); 34345791Speter i < rid && resv; 34445791Speter i++, resv = LIST_NEXT(resv, links)) 34545791Speter ; 3468012Sjulian 34745791Speter return resv; 34845791Speter} 34945791Speter 35045791Speterstatic struct resvaddr * 35145791Spetereisa_find_ioaddr(struct eisa_device *e_dev, int rid) 35245791Speter{ 35345791Speter int i; 35445791Speter struct resvaddr *resv; 35545791Speter 35645791Speter for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs); 35745791Speter i < rid && resv; 35845791Speter i++, resv = LIST_NEXT(resv, links)) 35945791Speter ; 36045791Speter 36145791Speter return resv; 36245791Speter} 36345791Speter 36445791Speterstatic int 36545791Spetereisa_read_ivar(device_t dev, device_t child, int which, u_long *result) 36645791Speter{ 36745791Speter struct eisa_device *e_dev = device_get_ivars(child); 36849360Smdodd struct irq_node *irq; 36945791Speter 37045791Speter switch (which) { 37145791Speter case EISA_IVAR_SLOT: 37245791Speter *result = e_dev->ioconf.slot; 37345791Speter break; 37445791Speter 37545791Speter case EISA_IVAR_ID: 37645791Speter *result = e_dev->id; 37745791Speter break; 37845791Speter 37945791Speter case EISA_IVAR_IRQ: 38045791Speter /* XXX only first irq */ 38149360Smdodd if ((irq = eisa_find_irq(e_dev, 0)) != NULL) { 38249360Smdodd *result = irq->irq_no; 38349360Smdodd } else { 38449360Smdodd *result = -1; 38549360Smdodd } 38645791Speter break; 38745791Speter 38845791Speter default: 38945791Speter return (ENOENT); 39012122Sgibbs } 3918012Sjulian 39245791Speter return (0); 39345791Speter} 39413691Sgibbs 39545791Speterstatic int 39645791Spetereisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 39745791Speter{ 39845791Speter return (EINVAL); 39945791Speter} 40045791Speter 40145791Speterstatic struct resource * 40245791Spetereisa_alloc_resource(device_t dev, device_t child, int type, int *rid, 40345791Speter u_long start, u_long end, u_long count, u_int flags) 40445791Speter{ 40545791Speter int isdefault; 40645791Speter struct eisa_device *e_dev = device_get_ivars(child); 40745791Speter struct resource *rv, **rvp = 0; 40845791Speter 40945791Speter isdefault = (device_get_parent(child) == dev 41045791Speter && start == 0UL && end == ~0UL && count == 1); 41145791Speter 41245791Speter switch (type) { 41345791Speter case SYS_RES_IRQ: 41445791Speter if (isdefault) { 41549360Smdodd struct irq_node * irq = eisa_find_irq(e_dev, *rid); 41649360Smdodd if (irq == NULL) 41745791Speter return 0; 41849360Smdodd start = end = irq->irq_no; 41945791Speter count = 1; 42049360Smdodd if (irq->irq_trigger == EISA_TRIGGER_LEVEL) { 42149360Smdodd flags |= RF_SHAREABLE; 42249360Smdodd } else { 42349360Smdodd flags &= ~RF_SHAREABLE; 42449360Smdodd } 42512157Sgibbs } 42645791Speter break; 42745791Speter 42845791Speter case SYS_RES_MEMORY: 42945791Speter if (isdefault) { 43045791Speter struct resvaddr *resv; 43145791Speter 43245791Speter resv = eisa_find_maddr(e_dev, *rid); 43345791Speter if (!resv) 43445791Speter return 0; 43545791Speter 43645791Speter start = resv->addr; 43747451Speter end = resv->addr + (resv->size - 1); 43845791Speter count = resv->size; 43945791Speter rvp = &resv->res; 44012157Sgibbs } 44145791Speter break; 44245791Speter 44345791Speter case SYS_RES_IOPORT: 44445791Speter if (isdefault) { 44545791Speter struct resvaddr *resv; 44645791Speter 44745791Speter resv = eisa_find_ioaddr(e_dev, *rid); 44845791Speter if (!resv) 44945791Speter return 0; 45045791Speter 45145791Speter start = resv->addr; 45247451Speter end = resv->addr + (resv->size - 1); 45345791Speter count = resv->size; 45445791Speter rvp = &resv->res; 45545791Speter } 45645791Speter break; 45745791Speter 45845791Speter default: 45945791Speter return 0; 4608012Sjulian } 46145791Speter 46245791Speter rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 46345791Speter type, rid, start, end, count, flags); 46445791Speter if (rvp) 46545791Speter *rvp = rv; 46645791Speter 46745791Speter return rv; 46812090Sgibbs} 4698012Sjulian 47045791Speterstatic int 47145791Spetereisa_release_resource(device_t dev, device_t child, int type, int rid, 47245791Speter struct resource *r) 47312090Sgibbs{ 47445791Speter int rv; 47545791Speter struct eisa_device *e_dev = device_get_ivars(child); 47645791Speter struct resvaddr *resv = 0; 47712090Sgibbs 47845791Speter switch (type) { 47945791Speter case SYS_RES_IRQ: 48049360Smdodd if (eisa_find_irq(e_dev, rid) == NULL) 48145791Speter return EINVAL; 48245791Speter break; 48345791Speter 48445791Speter case SYS_RES_MEMORY: 48545791Speter if (device_get_parent(child) == dev) 48645791Speter resv = eisa_find_maddr(e_dev, rid); 48745791Speter break; 48845791Speter 48945791Speter 49045791Speter case SYS_RES_IOPORT: 49145791Speter if (device_get_parent(child) == dev) 49245791Speter resv = eisa_find_ioaddr(e_dev, rid); 49345791Speter break; 49445791Speter 49545791Speter default: 49645791Speter return (ENOENT); 49712157Sgibbs } 49812090Sgibbs 49945791Speter rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 50045791Speter 50145791Speter if (rv == 0) { 50245791Speter if (resv) 50345791Speter resv->res = 0; 5048012Sjulian } 50545791Speter 50645791Speter return rv; 50712090Sgibbs} 5088012Sjulian 50912090Sgibbsint 51049360Smdoddeisa_add_intr(device_t dev, int irq, int trigger) 51112090Sgibbs{ 51245791Speter struct eisa_device *e_dev = device_get_ivars(dev); 51349360Smdodd struct irq_node *irq_info; 51429674Sgibbs 51529674Sgibbs irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF, 51629674Sgibbs M_NOWAIT); 51729674Sgibbs if (irq_info == NULL) 51829674Sgibbs return (1); 51929674Sgibbs 52029674Sgibbs irq_info->irq_no = irq; 52149360Smdodd irq_info->irq_trigger = trigger; 52229674Sgibbs irq_info->idesc = NULL; 52329674Sgibbs TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links); 52412157Sgibbs return 0; 52512090Sgibbs} 52612090Sgibbs 52713691Sgibbsstatic int 52846601Spetereisa_add_resvaddr(struct eisa_device *e_dev, struct resvlist *head, u_long base, 52946601Speter u_long size, int flags) 53013691Sgibbs{ 53113691Sgibbs resvaddr_t *reservation; 53213691Sgibbs 53313691Sgibbs reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t), 53413691Sgibbs M_DEVBUF, M_NOWAIT); 53513691Sgibbs if(!reservation) 53613691Sgibbs return (ENOMEM); 53713691Sgibbs 53813691Sgibbs reservation->addr = base; 53913691Sgibbs reservation->size = size; 54013691Sgibbs reservation->flags = flags; 54113691Sgibbs 54271999Sphk if (!LIST_FIRST(head)) { 54313691Sgibbs LIST_INSERT_HEAD(head, reservation, links); 54413691Sgibbs } 54513691Sgibbs else { 54613691Sgibbs resvaddr_t *node; 54771999Sphk LIST_FOREACH(node, head, links) { 54813691Sgibbs if (node->addr > reservation->addr) { 54913691Sgibbs /* 55013691Sgibbs * List is sorted in increasing 55113691Sgibbs * address order. 55213691Sgibbs */ 55313691Sgibbs LIST_INSERT_BEFORE(node, reservation, links); 55413691Sgibbs break; 55513691Sgibbs } 55613691Sgibbs 55713691Sgibbs if (node->addr == reservation->addr) { 55813691Sgibbs /* 55913691Sgibbs * If the entry we want to add 56013691Sgibbs * matches any already in here, 56113691Sgibbs * fail. 56213691Sgibbs */ 56313691Sgibbs free(reservation, M_DEVBUF); 56413691Sgibbs return (EEXIST); 56513691Sgibbs } 56613691Sgibbs 56771999Sphk if (!LIST_NEXT(node, links)) { 56813691Sgibbs LIST_INSERT_AFTER(node, reservation, links); 56913691Sgibbs break; 57013691Sgibbs } 57113691Sgibbs } 57213691Sgibbs } 57313691Sgibbs return (0); 57413691Sgibbs} 57513691Sgibbs 57612090Sgibbsint 57746601Spetereisa_add_mspace(device_t dev, u_long mbase, u_long msize, int flags) 57812090Sgibbs{ 57945791Speter struct eisa_device *e_dev = device_get_ivars(dev); 58046601Speter 58113804Sgibbs return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize, 58213804Sgibbs flags); 58312090Sgibbs} 58412090Sgibbs 58512090Sgibbsint 58646601Spetereisa_add_iospace(device_t dev, u_long iobase, u_long iosize, int flags) 58712090Sgibbs{ 58845791Speter struct eisa_device *e_dev = device_get_ivars(dev); 58946601Speter 59013804Sgibbs return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase, 59113804Sgibbs iosize, flags); 59213691Sgibbs} 59313691Sgibbs 59445791Speterstatic device_method_t eisa_methods[] = { 59545791Speter /* Device interface */ 59645791Speter DEVMETHOD(device_probe, eisa_probe), 59745791Speter DEVMETHOD(device_attach, bus_generic_attach), 59845791Speter DEVMETHOD(device_shutdown, bus_generic_shutdown), 59948100Speter DEVMETHOD(device_suspend, bus_generic_suspend), 60048100Speter DEVMETHOD(device_resume, bus_generic_resume), 60145791Speter 60245791Speter /* Bus interface */ 60345791Speter DEVMETHOD(bus_print_child, eisa_print_child), 60448754Sdfr DEVMETHOD(bus_probe_nomatch, eisa_probe_nomatch), 60545791Speter DEVMETHOD(bus_read_ivar, eisa_read_ivar), 60645791Speter DEVMETHOD(bus_write_ivar, eisa_write_ivar), 60745791Speter DEVMETHOD(bus_driver_added, bus_generic_driver_added), 60845791Speter DEVMETHOD(bus_alloc_resource, eisa_alloc_resource), 60945791Speter DEVMETHOD(bus_release_resource, eisa_release_resource), 61045791Speter DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 61145791Speter DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 61245791Speter DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 61345791Speter DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 61445791Speter 61545791Speter { 0, 0 } 61645791Speter}; 61745791Speter 61845791Speterstatic driver_t eisa_driver = { 61945791Speter "eisa", 62045791Speter eisa_methods, 62145791Speter 1, /* no softc */ 62245791Speter}; 62345791Speter 62472228SjoergDRIVER_MODULE(eisa, eisab, eisa_driver, eisa_devclass, 0, 0); 625104015SjhbDRIVER_MODULE(eisa, legacy, eisa_driver, eisa_devclass, 0, 0); 626