eisaconf.c revision 55953
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 55953 2000-01-14 07:14:17Z peter $ 328012Sjulian */ 3323855Sjoerg 3423855Sjoerg#include "opt_eisa.h" 3523855Sjoerg 368012Sjulian#include <sys/param.h> 3712090Sgibbs#include <sys/systm.h> 3845791Speter#include <sys/queue.h> 3912090Sgibbs#include <sys/malloc.h> 4045791Speter#include <sys/kernel.h> 4145791Speter#include <sys/module.h> 4245791Speter#include <sys/bus.h> 438012Sjulian 4428551Sbde#include <machine/limits.h> 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 */ 5645791Speter LIST_ENTRY(resvaddr) links; /* List links */ 5745791Speter} resvaddr_t; 5845791Speter 5945791SpeterLIST_HEAD(resvlist, resvaddr); 6045791Speter 6145791Speterstruct irq_node { 6245791Speter int irq_no; 6349360Smdodd int irq_trigger; 6445791Speter void *idesc; 6545791Speter TAILQ_ENTRY(irq_node) links; 6612090Sgibbs}; 678012Sjulian 6845791SpeterTAILQ_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 8423855Sjoerg/* Global variable, so UserConfig can change it. */ 8549281Smdodd#define MAX_COL 79 8623855Sjoerg#ifndef EISA_SLOTS 8723855Sjoerg#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */ 8823855Sjoerg#endif 8920450Sjoergint num_eisa_slots = 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), 17645791Speter M_DEVBUF, M_NOWAIT); 17745791Speter if (!e_dev) { 17845818Speter device_printf(dev, "cannot malloc eisa_device"); 17912157Sgibbs break; /* Try to attach what we have already */ 18012157Sgibbs } 18145791Speter bzero(e_dev, sizeof(*e_dev)); 18213691Sgibbs 18312157Sgibbs e_dev->id = eisa_id; 18413691Sgibbs 18512157Sgibbs e_dev->ioconf.slot = slot; 18613691Sgibbs 18713691Sgibbs /* Initialize our lists of reserved addresses */ 18813691Sgibbs LIST_INIT(&(e_dev->ioconf.ioaddrs)); 18913691Sgibbs LIST_INIT(&(e_dev->ioconf.maddrs)); 19029674Sgibbs TAILQ_INIT(&(e_dev->ioconf.irqs)); 19113691Sgibbs 19254073Smdodd child = device_add_child(dev, NULL, -1); 19354073Smdodd device_set_ivars(child, e_dev); 19412090Sgibbs } 1958012Sjulian 19647308Speter /* 19747308Speter * EISA busses themselves are not easily detectable, the easiest way 19847308Speter * to tell if there is an eisa bus is if we found something - there 19947308Speter * should be a motherboard "card" there somewhere. 20047308Speter */ 20147308Speter return devices_found ? 0 : ENXIO; 20245791Speter} 20312157Sgibbs 20445791Speterstatic void 20548754Sdfreisa_probe_nomatch(device_t dev, device_t child) 20648754Sdfr{ 20748754Sdfr u_int32_t eisa_id = eisa_get_id(child); 20848754Sdfr u_int8_t slot = eisa_get_slot(child); 20948754Sdfr 21048754Sdfr device_printf(dev, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n", 21148754Sdfr EISA_MFCTR_CHAR0(eisa_id), 21248754Sdfr EISA_MFCTR_CHAR1(eisa_id), 21348754Sdfr EISA_MFCTR_CHAR2(eisa_id), 21448754Sdfr EISA_PRODUCT_ID(eisa_id), 21548754Sdfr EISA_REVISION_ID(eisa_id), 21648754Sdfr eisa_id, 21748754Sdfr slot); 21848754Sdfr 21948754Sdfr return; 22048754Sdfr} 22148754Sdfr 22249281Smdoddstatic void 22349281Smdoddeisa_reg_print (dev, string, separator, column) 22449281Smdodd device_t dev; 22549281Smdodd char * string; 22649281Smdodd char * separator; 22749281Smdodd int * column; 22849281Smdodd{ 22949281Smdodd int length = strlen(string); 23049281Smdodd 23149281Smdodd length += (separator ? 2 : 1); 23249281Smdodd 23349281Smdodd if (((*column) + length) >= MAX_COL) { 23449281Smdodd printf("\n"); 23549281Smdodd (*column) = 0; 23649281Smdodd } else if ((*column) != 0) { 23749281Smdodd if (separator) { 23849281Smdodd printf("%c", *separator); 23949281Smdodd (*column)++; 24049281Smdodd } 24149281Smdodd printf(" "); 24249281Smdodd (*column)++; 24349281Smdodd } 24449281Smdodd 24549281Smdodd if ((*column) == 0) { 24649281Smdodd (*column) += device_printf(dev, "%s", string); 24749281Smdodd } else { 24849281Smdodd (*column) += printf("%s", string); 24949281Smdodd } 25049281Smdodd 25149281Smdodd return; 25249281Smdodd} 25349281Smdodd 25449195Smdoddstatic int 25545791Spetereisa_print_child(device_t dev, device_t child) 25645791Speter{ 25749281Smdodd char buf[81]; 25849281Smdodd struct eisa_device * e_dev = device_get_ivars(child); 25949281Smdodd int rid; 26049382Smdodd struct irq_node * irq; 26149281Smdodd struct resvaddr * resv; 26249281Smdodd char separator = ','; 26349281Smdodd int column = 0; 26449281Smdodd int retval = 0; 26549195Smdodd 26649281Smdodd if (device_get_desc(child)) { 26749281Smdodd snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child)); 26849281Smdodd eisa_reg_print(child, buf, NULL, &column); 26949281Smdodd } 27049195Smdodd 27149281Smdodd rid = 0; 27249281Smdodd while ((resv = eisa_find_ioaddr(e_dev, rid++))) { 27349281Smdodd if ((resv->size == 1) || 27449281Smdodd (resv->flags & RESVADDR_BITMASK)) { 27549281Smdodd snprintf(buf, sizeof(buf), "%s%lx", 27649281Smdodd ((rid == 1) ? "at 0x" : "0x"), 27749281Smdodd resv->addr); 27849281Smdodd } else { 27949281Smdodd snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 28049281Smdodd ((rid == 1) ? "at 0x" : "0x"), 28149281Smdodd resv->addr, 28249281Smdodd (resv->addr + (resv->size - 1))); 28349281Smdodd } 28449281Smdodd eisa_reg_print(child, buf, 28549281Smdodd ((rid == 2) ? &separator : NULL), &column); 28649281Smdodd } 28749195Smdodd 28849281Smdodd rid = 0; 28949281Smdodd while ((resv = eisa_find_maddr(e_dev, rid++))) { 29049281Smdodd if ((resv->size == 1) || 29149281Smdodd (resv->flags & RESVADDR_BITMASK)) { 29249281Smdodd snprintf(buf, sizeof(buf), "%s%lx", 29349281Smdodd ((rid == 1) ? "at 0x" : "0x"), 29449281Smdodd resv->addr); 29549281Smdodd } else { 29649281Smdodd snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 29749281Smdodd ((rid == 1) ? "at 0x" : "0x"), 29849281Smdodd resv->addr, 29949281Smdodd (resv->addr + (resv->size - 1))); 30049281Smdodd } 30149281Smdodd eisa_reg_print(child, buf, 30249281Smdodd ((rid == 2) ? &separator : NULL), &column); 30349281Smdodd } 30449281Smdodd 30549281Smdodd rid = 0; 30649360Smdodd while ((irq = eisa_find_irq(e_dev, rid++)) != NULL) { 30749360Smdodd snprintf(buf, sizeof(buf), "irq %d (%s)", irq->irq_no, 30849360Smdodd (irq->irq_trigger ? "level" : "edge")); 30949281Smdodd eisa_reg_print(child, buf, 31049281Smdodd ((rid == 1) ? &separator : NULL), &column); 31149281Smdodd } 31249281Smdodd 31349281Smdodd snprintf(buf, sizeof(buf), "on %s slot %d\n", 31449281Smdodd device_get_nameunit(dev), eisa_get_slot(child)); 31549281Smdodd eisa_reg_print(child, buf, NULL, &column); 31649281Smdodd 31749195Smdodd return (retval); 31845791Speter} 3198012Sjulian 32049360Smdoddstatic struct irq_node * 32145791Spetereisa_find_irq(struct eisa_device *e_dev, int rid) 32245791Speter{ 32345791Speter int i; 32445791Speter struct irq_node *irq; 32529674Sgibbs 32645791Speter for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 32745791Speter i < rid && irq; 32845791Speter i++, irq = TAILQ_NEXT(irq, links)) 32945791Speter ; 33045791Speter 33145791Speter if (irq) 33249360Smdodd return (irq); 33345791Speter else 33449360Smdodd return (NULL); 33545791Speter} 3368012Sjulian 33745791Speterstatic struct resvaddr * 33845791Spetereisa_find_maddr(struct eisa_device *e_dev, int rid) 33945791Speter{ 34045791Speter int i; 34145791Speter struct resvaddr *resv; 3428012Sjulian 34345791Speter for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs); 34445791Speter i < rid && resv; 34545791Speter i++, resv = LIST_NEXT(resv, links)) 34645791Speter ; 3478012Sjulian 34845791Speter return resv; 34945791Speter} 35045791Speter 35145791Speterstatic struct resvaddr * 35245791Spetereisa_find_ioaddr(struct eisa_device *e_dev, int rid) 35345791Speter{ 35445791Speter int i; 35545791Speter struct resvaddr *resv; 35645791Speter 35745791Speter for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs); 35845791Speter i < rid && resv; 35945791Speter i++, resv = LIST_NEXT(resv, links)) 36045791Speter ; 36145791Speter 36245791Speter return resv; 36345791Speter} 36445791Speter 36545791Speterstatic int 36645791Spetereisa_read_ivar(device_t dev, device_t child, int which, u_long *result) 36745791Speter{ 36845791Speter struct eisa_device *e_dev = device_get_ivars(child); 36949360Smdodd struct irq_node *irq; 37045791Speter 37145791Speter switch (which) { 37245791Speter case EISA_IVAR_SLOT: 37345791Speter *result = e_dev->ioconf.slot; 37445791Speter break; 37545791Speter 37645791Speter case EISA_IVAR_ID: 37745791Speter *result = e_dev->id; 37845791Speter break; 37945791Speter 38045791Speter case EISA_IVAR_IRQ: 38145791Speter /* XXX only first irq */ 38249360Smdodd if ((irq = eisa_find_irq(e_dev, 0)) != NULL) { 38349360Smdodd *result = irq->irq_no; 38449360Smdodd } else { 38549360Smdodd *result = -1; 38649360Smdodd } 38745791Speter break; 38845791Speter 38945791Speter default: 39045791Speter return (ENOENT); 39112122Sgibbs } 3928012Sjulian 39345791Speter return (0); 39445791Speter} 39513691Sgibbs 39645791Speterstatic int 39745791Spetereisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 39845791Speter{ 39945791Speter return (EINVAL); 40045791Speter} 40145791Speter 40245791Speterstatic struct resource * 40345791Spetereisa_alloc_resource(device_t dev, device_t child, int type, int *rid, 40445791Speter u_long start, u_long end, u_long count, u_int flags) 40545791Speter{ 40645791Speter int isdefault; 40745791Speter struct eisa_device *e_dev = device_get_ivars(child); 40845791Speter struct resource *rv, **rvp = 0; 40945791Speter 41045791Speter isdefault = (device_get_parent(child) == dev 41145791Speter && start == 0UL && end == ~0UL && count == 1); 41245791Speter 41345791Speter switch (type) { 41445791Speter case SYS_RES_IRQ: 41545791Speter if (isdefault) { 41649360Smdodd struct irq_node * irq = eisa_find_irq(e_dev, *rid); 41749360Smdodd if (irq == NULL) 41845791Speter return 0; 41949360Smdodd start = end = irq->irq_no; 42045791Speter count = 1; 42149360Smdodd if (irq->irq_trigger == EISA_TRIGGER_LEVEL) { 42249360Smdodd flags |= RF_SHAREABLE; 42349360Smdodd } else { 42449360Smdodd flags &= ~RF_SHAREABLE; 42549360Smdodd } 42612157Sgibbs } 42745791Speter break; 42845791Speter 42945791Speter case SYS_RES_MEMORY: 43045791Speter if (isdefault) { 43145791Speter struct resvaddr *resv; 43245791Speter 43345791Speter resv = eisa_find_maddr(e_dev, *rid); 43445791Speter if (!resv) 43545791Speter return 0; 43645791Speter 43745791Speter start = resv->addr; 43847451Speter end = resv->addr + (resv->size - 1); 43945791Speter count = resv->size; 44045791Speter rvp = &resv->res; 44112157Sgibbs } 44245791Speter break; 44345791Speter 44445791Speter case SYS_RES_IOPORT: 44545791Speter if (isdefault) { 44645791Speter struct resvaddr *resv; 44745791Speter 44845791Speter resv = eisa_find_ioaddr(e_dev, *rid); 44945791Speter if (!resv) 45045791Speter return 0; 45145791Speter 45245791Speter start = resv->addr; 45347451Speter end = resv->addr + (resv->size - 1); 45445791Speter count = resv->size; 45545791Speter rvp = &resv->res; 45645791Speter } 45745791Speter break; 45845791Speter 45945791Speter default: 46045791Speter return 0; 4618012Sjulian } 46245791Speter 46345791Speter rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 46445791Speter type, rid, start, end, count, flags); 46545791Speter if (rvp) 46645791Speter *rvp = rv; 46745791Speter 46845791Speter return rv; 46912090Sgibbs} 4708012Sjulian 47145791Speterstatic int 47245791Spetereisa_release_resource(device_t dev, device_t child, int type, int rid, 47345791Speter struct resource *r) 47412090Sgibbs{ 47545791Speter int rv; 47645791Speter struct eisa_device *e_dev = device_get_ivars(child); 47745791Speter struct resvaddr *resv = 0; 47812090Sgibbs 47945791Speter switch (type) { 48045791Speter case SYS_RES_IRQ: 48149360Smdodd if (eisa_find_irq(e_dev, rid) == NULL) 48245791Speter return EINVAL; 48345791Speter break; 48445791Speter 48545791Speter case SYS_RES_MEMORY: 48645791Speter if (device_get_parent(child) == dev) 48745791Speter resv = eisa_find_maddr(e_dev, rid); 48845791Speter break; 48945791Speter 49045791Speter 49145791Speter case SYS_RES_IOPORT: 49245791Speter if (device_get_parent(child) == dev) 49345791Speter resv = eisa_find_ioaddr(e_dev, rid); 49445791Speter break; 49545791Speter 49645791Speter default: 49745791Speter return (ENOENT); 49812157Sgibbs } 49912090Sgibbs 50045791Speter rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 50145791Speter 50245791Speter if (rv == 0) { 50345791Speter if (resv) 50445791Speter resv->res = 0; 5058012Sjulian } 50645791Speter 50745791Speter return rv; 50812090Sgibbs} 5098012Sjulian 51012090Sgibbsint 51149360Smdoddeisa_add_intr(device_t dev, int irq, int trigger) 51212090Sgibbs{ 51345791Speter struct eisa_device *e_dev = device_get_ivars(dev); 51449360Smdodd struct irq_node *irq_info; 51529674Sgibbs 51629674Sgibbs irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF, 51729674Sgibbs M_NOWAIT); 51829674Sgibbs if (irq_info == NULL) 51929674Sgibbs return (1); 52029674Sgibbs 52129674Sgibbs irq_info->irq_no = irq; 52249360Smdodd irq_info->irq_trigger = trigger; 52329674Sgibbs irq_info->idesc = NULL; 52429674Sgibbs TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links); 52512157Sgibbs return 0; 52612090Sgibbs} 52712090Sgibbs 52813691Sgibbsstatic int 52946601Spetereisa_add_resvaddr(struct eisa_device *e_dev, struct resvlist *head, u_long base, 53046601Speter u_long size, int flags) 53113691Sgibbs{ 53213691Sgibbs resvaddr_t *reservation; 53313691Sgibbs 53413691Sgibbs reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t), 53513691Sgibbs M_DEVBUF, M_NOWAIT); 53613691Sgibbs if(!reservation) 53713691Sgibbs return (ENOMEM); 53813691Sgibbs 53913691Sgibbs reservation->addr = base; 54013691Sgibbs reservation->size = size; 54113691Sgibbs reservation->flags = flags; 54213691Sgibbs 54313691Sgibbs if (!head->lh_first) { 54413691Sgibbs LIST_INSERT_HEAD(head, reservation, links); 54513691Sgibbs } 54613691Sgibbs else { 54713691Sgibbs resvaddr_t *node; 54813691Sgibbs for(node = head->lh_first; node; node = node->links.le_next) { 54913691Sgibbs if (node->addr > reservation->addr) { 55013691Sgibbs /* 55113691Sgibbs * List is sorted in increasing 55213691Sgibbs * address order. 55313691Sgibbs */ 55413691Sgibbs LIST_INSERT_BEFORE(node, reservation, links); 55513691Sgibbs break; 55613691Sgibbs } 55713691Sgibbs 55813691Sgibbs if (node->addr == reservation->addr) { 55913691Sgibbs /* 56013691Sgibbs * If the entry we want to add 56113691Sgibbs * matches any already in here, 56213691Sgibbs * fail. 56313691Sgibbs */ 56413691Sgibbs free(reservation, M_DEVBUF); 56513691Sgibbs return (EEXIST); 56613691Sgibbs } 56713691Sgibbs 56813691Sgibbs if (!node->links.le_next) { 56913691Sgibbs LIST_INSERT_AFTER(node, reservation, links); 57013691Sgibbs break; 57113691Sgibbs } 57213691Sgibbs } 57313691Sgibbs } 57413691Sgibbs return (0); 57513691Sgibbs} 57613691Sgibbs 57712090Sgibbsint 57846601Spetereisa_add_mspace(device_t dev, u_long mbase, u_long msize, int flags) 57912090Sgibbs{ 58045791Speter struct eisa_device *e_dev = device_get_ivars(dev); 58146601Speter 58213804Sgibbs return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize, 58313804Sgibbs flags); 58412090Sgibbs} 58512090Sgibbs 58612090Sgibbsint 58746601Spetereisa_add_iospace(device_t dev, u_long iobase, u_long iosize, int flags) 58812090Sgibbs{ 58945791Speter struct eisa_device *e_dev = device_get_ivars(dev); 59046601Speter 59113804Sgibbs return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase, 59213804Sgibbs iosize, flags); 59313691Sgibbs} 59413691Sgibbs 59545791Speterstatic device_method_t eisa_methods[] = { 59645791Speter /* Device interface */ 59745791Speter DEVMETHOD(device_probe, eisa_probe), 59845791Speter DEVMETHOD(device_attach, bus_generic_attach), 59945791Speter DEVMETHOD(device_shutdown, bus_generic_shutdown), 60048100Speter DEVMETHOD(device_suspend, bus_generic_suspend), 60148100Speter DEVMETHOD(device_resume, bus_generic_resume), 60245791Speter 60345791Speter /* Bus interface */ 60445791Speter DEVMETHOD(bus_print_child, eisa_print_child), 60548754Sdfr DEVMETHOD(bus_probe_nomatch, eisa_probe_nomatch), 60645791Speter DEVMETHOD(bus_read_ivar, eisa_read_ivar), 60745791Speter DEVMETHOD(bus_write_ivar, eisa_write_ivar), 60845791Speter DEVMETHOD(bus_driver_added, bus_generic_driver_added), 60945791Speter DEVMETHOD(bus_alloc_resource, eisa_alloc_resource), 61045791Speter DEVMETHOD(bus_release_resource, eisa_release_resource), 61145791Speter DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 61245791Speter DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 61345791Speter DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 61445791Speter DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 61545791Speter 61645791Speter { 0, 0 } 61745791Speter}; 61845791Speter 61945791Speterstatic driver_t eisa_driver = { 62045791Speter "eisa", 62145791Speter eisa_methods, 62245791Speter 1, /* no softc */ 62345791Speter}; 62445791Speter 62545791SpeterDRIVER_MODULE(eisa, isab, eisa_driver, eisa_devclass, 0, 0); 62645807SpeterDRIVER_MODULE(eisa, nexus, eisa_driver, eisa_devclass, 0, 0); 627