eisaconf.c revision 133059
1111072Sjake/* 2111072Sjake * EISA bus probe and attach routines 3167308Smarius * 4111072Sjake * Copyright (c) 1995, 1996 Justin T. Gibbs. 5111072Sjake * All rights reserved. 6111072Sjake * 7111072Sjake * Redistribution and use in source and binary forms, with or without 8111072Sjake * modification, are permitted provided that the following conditions 9111072Sjake * are met: 10111072Sjake * 1. Redistributions of source code must retain the above copyright 11111072Sjake * notice immediately at the beginning of the file, without modification, 12111072Sjake * this list of conditions, and the following disclaimer. 13111072Sjake * 2. Redistributions in binary form must reproduce the above copyright 14111072Sjake * notice, this list of conditions and the following disclaimer in the 15111072Sjake * documentation and/or other materials provided with the distribution. 16111072Sjake * 3. The name of the author may not be used to endorse or promote products 17111072Sjake * derived from this software without specific prior written permission. 18111072Sjake * 19111072Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20111072Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21111072Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22111072Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23111072Sjake * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24111072Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25111072Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26111072Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27111072Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28143129Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29143129Smarius * SUCH DAMAGE. 30143129Smarius * 31111072Sjake */ 32111072Sjake 33111072Sjake#include <sys/cdefs.h> 34111072Sjake__FBSDID("$FreeBSD: head/sys/dev/eisa/eisaconf.c 133059 2004-08-03 06:48:36Z njl $"); 35111072Sjake 36167308Smarius#include "opt_eisa.h" 37111123Sjake 38111072Sjake#include <sys/param.h> 39143826Smarius#include <sys/systm.h> 40133589Smarius#include <sys/queue.h> 41152684Smarius#include <sys/limits.h> 42111072Sjake#include <sys/malloc.h> 43111072Sjake#include <sys/kernel.h> 44111072Sjake#include <sys/module.h> 45111072Sjake#include <sys/bus.h> 46111072Sjake 47111072Sjake#include <machine/bus.h> 48111072Sjake#include <machine/resource.h> 49111072Sjake#include <sys/rman.h> 50111072Sjake 51111072Sjake#include <dev/eisa/eisaconf.h> 52111072Sjake 53111072Sjaketypedef struct resvaddr { 54152684Smarius u_long addr; /* start address */ 55111072Sjake u_long size; /* size of reserved area */ 56111072Sjake int flags; 57111072Sjake struct resource *res; /* resource manager handle */ 58167308Smarius LIST_ENTRY(resvaddr) links; /* List links */ 59172066Smarius} resvaddr_t; 60167308Smarius 61167308SmariusLIST_HEAD(resvlist, resvaddr); 62167308Smarius 63167308Smariusstruct irq_node { 64167308Smarius int irq_no; 65167308Smarius int irq_trigger; 66167308Smarius void *idesc; 67167308Smarius TAILQ_ENTRY(irq_node) links; 68167308Smarius}; 69167308Smarius 70167308SmariusTAILQ_HEAD(irqlist, irq_node); 71167308Smarius 72167308Smariusstruct eisa_ioconf { 73167308Smarius int slot; 74167308Smarius struct resvlist ioaddrs; /* list of reserved I/O ranges */ 75172066Smarius struct resvlist maddrs; /* list of reserved memory ranges */ 76172066Smarius struct irqlist irqs; /* list of reserved irqs */ 77178443Smarius}; 78178443Smarius 79143826Smarius/* To be replaced by the "super device" generic device structure... */ 80152684Smariusstruct eisa_device { 81111123Sjake eisa_id_t id; 82167308Smarius struct eisa_ioconf ioconf; 83167308Smarius}; 84167308Smarius 85167308Smarius 86167308Smarius#define MAX_COL 79 87167308Smarius#ifndef EISA_SLOTS 88167308Smarius#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */ 89167308Smarius#endif 90167308Smariusint num_eisa_slots = EISA_SLOTS; 91167308SmariusTUNABLE_INT("hw.eisa_slots", &num_eisa_slots); 92167308Smarius 93167308Smariusstatic devclass_t eisa_devclass; 94167308Smarius 95167308Smariusstatic int eisa_probe_slot(int slot, eisa_id_t *eisa_id); 96190098Smariusstatic void eisa_reg_print (device_t, char *, char *, int *); 97190098Smariusstatic struct irq_node * eisa_find_irq(struct eisa_device *e_dev, int rid); 98190098Smariusstatic struct resvaddr * eisa_find_maddr(struct eisa_device *e_dev, int rid); 99190098Smariusstatic struct resvaddr * eisa_find_ioaddr(struct eisa_device *e_dev, int rid); 100167308Smarius 101167308Smariusstatic int 102167308Smariusmainboard_probe(device_t dev) 103167308Smarius{ 104167308Smarius char *idstring; 105167308Smarius eisa_id_t id = eisa_get_id(dev); 106167308Smarius 107167308Smarius if (eisa_get_slot(dev) != 0) 108167308Smarius return (ENXIO); 109167308Smarius 110190098Smarius idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1, 111167308Smarius M_DEVBUF, M_NOWAIT); 112167308Smarius if (idstring == NULL) { 113167308Smarius panic("Eisa probe unable to malloc"); 114167308Smarius } 115167308Smarius sprintf(idstring, "%c%c%c%03x%01x (System Board)", 116167308Smarius EISA_MFCTR_CHAR0(id), 117167308Smarius EISA_MFCTR_CHAR1(id), 118167308Smarius EISA_MFCTR_CHAR2(id), 119167308Smarius EISA_PRODUCT_ID(id), 120167308Smarius EISA_REVISION_ID(id)); 121167308Smarius device_set_desc(dev, idstring); 122167308Smarius 123182070Smarius return (0); 124182070Smarius} 125167308Smarius 126172066Smariusstatic int 127172066Smariusmainboard_attach(device_t dev) 128172066Smarius{ 129178443Smarius return (0); 130178443Smarius} 131172066Smarius 132172066Smariusstatic device_method_t mainboard_methods[] = { 133172066Smarius /* Device interface */ 134172066Smarius DEVMETHOD(device_probe, mainboard_probe), 135172066Smarius DEVMETHOD(device_attach, mainboard_attach), 136172066Smarius 137172066Smarius { 0, 0 } 138167308Smarius}; 139111072Sjake 140111072Sjakestatic driver_t mainboard_driver = { 141111072Sjake "mainboard", 142167308Smarius mainboard_methods, 143167308Smarius 1, 144167308Smarius}; 145167308Smarius 146167308Smariusstatic devclass_t mainboard_devclass; 147111072Sjake 148111072SjakeDRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0); 149167308Smarius 150111072Sjake/* 151111072Sjake** probe for EISA devices 152143826Smarius*/ 153111072Sjakestatic int 154172066Smariuseisa_probe(device_t dev) 155172066Smarius{ 156111072Sjake int devices_found, slot; 157111072Sjake struct eisa_device *e_dev; 158111072Sjake device_t child; 159111072Sjake eisa_id_t eisa_id; 160167308Smarius 161111123Sjake device_set_desc(dev, "EISA bus"); 162143142Smarius 163143142Smarius devices_found = 0; 164111072Sjake for (slot = 0; slot < num_eisa_slots; slot++) { 165172066Smarius eisa_id = 0; 166167308Smarius if (eisa_probe_slot(slot, &eisa_id)) { 167167308Smarius /* 168190098Smarius * If there's no card in the first slot (the 169111072Sjake * mainboard), then the system doesn't have EISA. 170111072Sjake * We abort the probe early in this case since 171167308Smarius * continuing on causes a hang on some systems. 172111072Sjake * Interestingly enough, the inb has been seen to 173172066Smarius * cause the hang. However, aborting here causes 174167308Smarius * the Adaptec 2842 probe to fail so that driver 175172066Smarius * needs to be fixed separately. 176167308Smarius */ 177167308Smarius if (slot == 0) 178190098Smarius break; 179167308Smarius continue; 180190098Smarius } 181167308Smarius 182167308Smarius devices_found++; 183167308Smarius 184167308Smarius /* Prepare an eisa_device_node for this slot */ 185167308Smarius e_dev = (struct eisa_device *)malloc(sizeof(*e_dev), 186167308Smarius M_DEVBUF, M_NOWAIT|M_ZERO); 187167308Smarius if (!e_dev) { 188172066Smarius device_printf(dev, "cannot malloc eisa_device"); 189172066Smarius break; /* Try to attach what we have already */ 190172066Smarius } 191167308Smarius 192172066Smarius e_dev->id = eisa_id; 193167308Smarius e_dev->ioconf.slot = slot; 194167308Smarius 195167308Smarius /* Initialize our lists of reserved addresses */ 196167308Smarius LIST_INIT(&(e_dev->ioconf.ioaddrs)); 197167308Smarius LIST_INIT(&(e_dev->ioconf.maddrs)); 198167308Smarius TAILQ_INIT(&(e_dev->ioconf.irqs)); 199172066Smarius 200143129Smarius child = device_add_child(dev, NULL, -1); 201143826Smarius device_set_ivars(child, e_dev); 202143129Smarius } 203143826Smarius 204143826Smarius /* 205143129Smarius * EISA busses themselves are not easily detectable, the easiest way 206111072Sjake * to tell if there is an eisa bus is if we found something - there 207172066Smarius * should be a motherboard "card" there somewhere. 208172066Smarius */ 209111072Sjake return devices_found ? 0 : ENXIO; 210111072Sjake} 211172066Smarius 212172066Smariusstatic int 213172066Smariuseisa_probe_slot(int slot, eisa_id_t *eisa_id) 214111123Sjake{ 215172066Smarius eisa_id_t probe_id; 216172066Smarius int base, i, id_size, ret; 217111123Sjake 218111123Sjake ret = ENXIO; 219172066Smarius probe_id = 0; 220172066Smarius id_size = sizeof(probe_id); 221111123Sjake base = 0x0c80 + (slot * 0x1000); 222111072Sjake 223111072Sjake for (i = 0; i < id_size; i++) { 224111072Sjake outb(base, 0x80 + i); /* Some cards require priming. */ 225167308Smarius probe_id |= inb(base + i) << ((id_size - i - 1) * CHAR_BIT); 226167308Smarius } 227167308Smarius 228111072Sjake /* If we found a card, return its EISA id. */ 229111072Sjake if ((probe_id & 0x80000000) == 0) { 230172066Smarius *eisa_id = probe_id; 231172066Smarius ret = 0; 232172066Smarius } 233172066Smarius 234172066Smarius return (ret); 235172066Smarius} 236172066Smarius 237172066Smariusstatic void 238172066Smariuseisa_probe_nomatch(device_t dev, device_t child) 239172066Smarius{ 240190098Smarius u_int32_t eisa_id = eisa_get_id(child); 241190098Smarius u_int8_t slot = eisa_get_slot(child); 242172066Smarius 243172066Smarius device_printf(dev, "unknown card %c%c%c%03x%01x (0x%08x) at slot %d\n", 244172066Smarius EISA_MFCTR_CHAR0(eisa_id), 245172066Smarius EISA_MFCTR_CHAR1(eisa_id), 246172066Smarius EISA_MFCTR_CHAR2(eisa_id), 247172066Smarius EISA_PRODUCT_ID(eisa_id), 248172066Smarius EISA_REVISION_ID(eisa_id), 249172066Smarius eisa_id, 250172066Smarius slot); 251172066Smarius 252172066Smarius return; 253172066Smarius} 254172066Smarius 255172066Smariusstatic void 256172066Smariuseisa_reg_print (dev, string, separator, column) 257172066Smarius device_t dev; 258172066Smarius char * string; 259172066Smarius char * separator; 260172066Smarius int * column; 261190098Smarius{ 262172066Smarius int length = strlen(string); 263190098Smarius 264190098Smarius length += (separator ? 2 : 1); 265190098Smarius 266190098Smarius if (((*column) + length) >= MAX_COL) { 267190098Smarius printf("\n"); 268172066Smarius (*column) = 0; 269172066Smarius } else if ((*column) != 0) { 270172066Smarius if (separator) { 271143826Smarius printf("%c", *separator); 272143826Smarius (*column)++; 273143826Smarius } 274111072Sjake printf(" "); 275152684Smarius (*column)++; 276152684Smarius } 277152684Smarius 278111072Sjake if ((*column) == 0) { 279152684Smarius (*column) += device_printf(dev, "%s", string); 280190098Smarius } else { 281152684Smarius (*column) += printf("%s", string); 282190098Smarius } 283152684Smarius 284152684Smarius return; 285152684Smarius} 286152684Smarius 287152684Smariusstatic int 288152684Smariuseisa_print_child(device_t dev, device_t child) 289152684Smarius{ 290190098Smarius char buf[81]; 291190098Smarius struct eisa_device * e_dev = device_get_ivars(child); 292190098Smarius int rid; 293190098Smarius struct irq_node * irq; 294152684Smarius struct resvaddr * resv; 295172066Smarius char separator = ','; 296190098Smarius int column = 0; 297172066Smarius int retval = 0; 298190098Smarius 299190098Smarius if (device_get_desc(child)) { 300190098Smarius snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child)); 301172066Smarius eisa_reg_print(child, buf, NULL, &column); 302190098Smarius } 303172066Smarius 304172066Smarius rid = 0; 305152684Smarius while ((resv = eisa_find_ioaddr(e_dev, rid++))) { 306152684Smarius if ((resv->size == 1) || 307111072Sjake (resv->flags & RESVADDR_BITMASK)) { 308152684Smarius snprintf(buf, sizeof(buf), "%s%lx", 309152684Smarius ((rid == 1) ? "at 0x" : "0x"), 310152684Smarius resv->addr); 311152684Smarius } else { 312152684Smarius snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 313152684Smarius ((rid == 1) ? "at 0x" : "0x"), 314152684Smarius resv->addr, 315152684Smarius (resv->addr + (resv->size - 1))); 316152684Smarius } 317111072Sjake eisa_reg_print(child, buf, 318111072Sjake ((rid == 2) ? &separator : NULL), &column); 319111072Sjake } 320167308Smarius 321167308Smarius rid = 0; 322167308Smarius while ((resv = eisa_find_maddr(e_dev, rid++))) { 323167308Smarius if ((resv->size == 1) || 324167308Smarius (resv->flags & RESVADDR_BITMASK)) { 325167308Smarius snprintf(buf, sizeof(buf), "%s%lx", 326182070Smarius ((rid == 1) ? "at 0x" : "0x"), 327111072Sjake resv->addr); 328111072Sjake } else { 329167308Smarius snprintf(buf, sizeof(buf), "%s%lx-0x%lx", 330111072Sjake ((rid == 1) ? "at 0x" : "0x"), 331111072Sjake resv->addr, 332111072Sjake (resv->addr + (resv->size - 1))); 333111072Sjake } 334111072Sjake eisa_reg_print(child, buf, 335152684Smarius ((rid == 2) ? &separator : NULL), &column); 336111072Sjake } 337111072Sjake 338111072Sjake rid = 0; 339111072Sjake while ((irq = eisa_find_irq(e_dev, rid++)) != NULL) { 340167308Smarius snprintf(buf, sizeof(buf), "irq %d (%s)", irq->irq_no, 341111072Sjake (irq->irq_trigger ? "level" : "edge")); 342111072Sjake eisa_reg_print(child, buf, 343152684Smarius ((rid == 1) ? &separator : NULL), &column); 344111072Sjake } 345152684Smarius 346152684Smarius snprintf(buf, sizeof(buf), "on %s slot %d\n", 347152684Smarius device_get_nameunit(dev), eisa_get_slot(child)); 348111072Sjake eisa_reg_print(child, buf, NULL, &column); 349152684Smarius 350111072Sjake return (retval); 351111072Sjake} 352172066Smarius 353172066Smariusstatic struct irq_node * 354111072Sjakeeisa_find_irq(struct eisa_device *e_dev, int rid) 355172066Smarius{ 356172066Smarius int i; 357111072Sjake struct irq_node *irq; 358172066Smarius 359172066Smarius for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 360172066Smarius i < rid && irq; 361111072Sjake i++, irq = TAILQ_NEXT(irq, links)) 362111072Sjake ; 363172066Smarius 364172066Smarius if (irq) 365111072Sjake return (irq); 366172066Smarius else 367172066Smarius return (NULL); 368111072Sjake} 369172066Smarius 370172066Smariusstatic struct resvaddr * 371111072Sjakeeisa_find_maddr(struct eisa_device *e_dev, int rid) 372111072Sjake{ 373172066Smarius int i; 374178443Smarius struct resvaddr *resv; 375170387Spiso 376172066Smarius for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs); 377172066Smarius i < rid && resv; 378170387Spiso i++, resv = LIST_NEXT(resv, links)) 379178443Smarius ; 380178443Smarius 381178443Smarius return resv; 382178443Smarius} 383178443Smarius 384178443Smariusstatic struct resvaddr * 385178443Smariuseisa_find_ioaddr(struct eisa_device *e_dev, int rid) 386178443Smarius{ 387178443Smarius int i; 388178443Smarius struct resvaddr *resv; 389178443Smarius 390172066Smarius for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs); 391172066Smarius i < rid && resv; 392170387Spiso i++, resv = LIST_NEXT(resv, links)) 393170387Spiso ; 394172066Smarius 395172066Smarius return resv; 396172066Smarius} 397111123Sjake 398172066Smariusstatic int 399172066Smariuseisa_read_ivar(device_t dev, device_t child, int which, u_long *result) 400111123Sjake{ 401172066Smarius struct eisa_device *e_dev = device_get_ivars(child); 402172066Smarius struct irq_node *irq; 403172066Smarius 404172066Smarius switch (which) { 405182070Smarius case EISA_IVAR_SLOT: 406172066Smarius *result = e_dev->ioconf.slot; 407172066Smarius break; 408172066Smarius 409182070Smarius case EISA_IVAR_ID: 410182070Smarius *result = e_dev->id; 411172066Smarius break; 412172066Smarius 413111123Sjake case EISA_IVAR_IRQ: 414111123Sjake /* XXX only first irq */ 415167308Smarius if ((irq = eisa_find_irq(e_dev, 0)) != NULL) { 416111072Sjake *result = irq->irq_no; 417111072Sjake } else { 418111072Sjake *result = -1; 419143826Smarius } 420111072Sjake break; 421111072Sjake 422111072Sjake default: 423111072Sjake return (ENOENT); 424111072Sjake } 425111072Sjake 426111072Sjake return (0); 427143826Smarius} 428111072Sjake 429111072Sjakestatic int 430111072Sjakeeisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 431143826Smarius{ 432111072Sjake return (EINVAL); 433143826Smarius} 434143826Smarius 435111072Sjakestatic struct resource * 436111072Sjakeeisa_alloc_resource(device_t dev, device_t child, int type, int *rid, 437111072Sjake u_long start, u_long end, u_long count, u_int flags) 438143826Smarius{ 439143826Smarius int isdefault; 440111072Sjake struct eisa_device *e_dev = device_get_ivars(child); 441143826Smarius struct resource *rv, **rvp = 0; 442172066Smarius 443143826Smarius isdefault = (device_get_parent(child) == dev 444143826Smarius && start == 0UL && end == ~0UL && count == 1); 445143826Smarius 446143826Smarius switch (type) { 447143826Smarius case SYS_RES_IRQ: 448143826Smarius if (isdefault) { 449143826Smarius struct irq_node * irq = eisa_find_irq(e_dev, *rid); 450143826Smarius if (irq == NULL) 451143826Smarius return 0; 452143826Smarius start = end = irq->irq_no; 453111072Sjake count = 1; 454111072Sjake if (irq->irq_trigger == EISA_TRIGGER_LEVEL) { 455111072Sjake flags |= RF_SHAREABLE; 456111072Sjake } else { 457111072Sjake flags &= ~RF_SHAREABLE; 458111072Sjake } 459111072Sjake } 460111072Sjake break; 461111072Sjake 462111072Sjake case SYS_RES_MEMORY: 463111072Sjake if (isdefault) { 464143826Smarius struct resvaddr *resv; 465143826Smarius 466111072Sjake resv = eisa_find_maddr(e_dev, *rid); 467111072Sjake if (!resv) 468111072Sjake return 0; 469111072Sjake 470111072Sjake start = resv->addr; 471111072Sjake end = resv->addr + (resv->size - 1); 472111072Sjake count = resv->size; 473111072Sjake rvp = &resv->res; 474167308Smarius } 475143826Smarius break; 476111072Sjake 477111072Sjake case SYS_RES_IOPORT: 478111072Sjake if (isdefault) { 479111072Sjake struct resvaddr *resv; 480143826Smarius 481111072Sjake resv = eisa_find_ioaddr(e_dev, *rid); 482133589Smarius if (!resv) 483167308Smarius return 0; 484152684Smarius 485152684Smarius start = resv->addr; 486152684Smarius end = resv->addr + (resv->size - 1); 487152684Smarius count = resv->size; 488152684Smarius rvp = &resv->res; 489152684Smarius } 490152684Smarius break; 491152684Smarius 492143826Smarius default: 493143826Smarius return 0; 494143826Smarius } 495143826Smarius 496143826Smarius rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 497143826Smarius type, rid, start, end, count, flags); 498143826Smarius if (rvp) 499143826Smarius *rvp = rv; 500172066Smarius 501143826Smarius return rv; 502143826Smarius} 503143826Smarius 504143826Smariusstatic int 505143826Smariuseisa_release_resource(device_t dev, device_t child, int type, int rid, 506172066Smarius struct resource *r) 507172066Smarius{ 508143826Smarius int rv; 509143826Smarius struct eisa_device *e_dev = device_get_ivars(child); 510152684Smarius struct resvaddr *resv = 0; 511152684Smarius 512133589Smarius switch (type) { 513152684Smarius case SYS_RES_IRQ: 514133589Smarius if (eisa_find_irq(e_dev, rid) == NULL) 515152684Smarius return EINVAL; 516152684Smarius break; 517152684Smarius 518152684Smarius case SYS_RES_MEMORY: 519152684Smarius if (device_get_parent(child) == dev) 520133589Smarius resv = eisa_find_maddr(e_dev, rid); 521 break; 522 523 524 case SYS_RES_IOPORT: 525 if (device_get_parent(child) == dev) 526 resv = eisa_find_ioaddr(e_dev, rid); 527 break; 528 529 default: 530 return (ENOENT); 531 } 532 533 rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 534 535 if (rv == 0) { 536 if (resv) 537 resv->res = 0; 538 } 539 540 return rv; 541} 542 543static int 544eisa_add_intr_m(device_t eisa, device_t dev, int irq, int trigger) 545{ 546 struct eisa_device *e_dev = device_get_ivars(dev); 547 struct irq_node *irq_info; 548 549 irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF, 550 M_NOWAIT); 551 if (irq_info == NULL) 552 return (1); 553 554 irq_info->irq_no = irq; 555 irq_info->irq_trigger = trigger; 556 irq_info->idesc = NULL; 557 TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links); 558 return 0; 559} 560 561static int 562eisa_add_resvaddr(struct eisa_device *e_dev, struct resvlist *head, u_long base, 563 u_long size, int flags) 564{ 565 resvaddr_t *reservation; 566 567 reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t), 568 M_DEVBUF, M_NOWAIT); 569 if(!reservation) 570 return (ENOMEM); 571 572 reservation->addr = base; 573 reservation->size = size; 574 reservation->flags = flags; 575 576 if (!LIST_FIRST(head)) { 577 LIST_INSERT_HEAD(head, reservation, links); 578 } 579 else { 580 resvaddr_t *node; 581 LIST_FOREACH(node, head, links) { 582 if (node->addr > reservation->addr) { 583 /* 584 * List is sorted in increasing 585 * address order. 586 */ 587 LIST_INSERT_BEFORE(node, reservation, links); 588 break; 589 } 590 591 if (node->addr == reservation->addr) { 592 /* 593 * If the entry we want to add 594 * matches any already in here, 595 * fail. 596 */ 597 free(reservation, M_DEVBUF); 598 return (EEXIST); 599 } 600 601 if (!LIST_NEXT(node, links)) { 602 LIST_INSERT_AFTER(node, reservation, links); 603 break; 604 } 605 } 606 } 607 return (0); 608} 609 610static int 611eisa_add_mspace_m(device_t eisa, device_t dev, u_long mbase, u_long msize, 612 int flags) 613{ 614 struct eisa_device *e_dev = device_get_ivars(dev); 615 616 return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize, 617 flags); 618} 619 620static int 621eisa_add_iospace_m(device_t eisa, device_t dev, u_long iobase, u_long iosize, 622 int flags) 623{ 624 struct eisa_device *e_dev = device_get_ivars(dev); 625 626 return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase, 627 iosize, flags); 628} 629 630static device_method_t eisa_methods[] = { 631 /* Device interface */ 632 DEVMETHOD(device_probe, eisa_probe), 633 DEVMETHOD(device_attach, bus_generic_attach), 634 DEVMETHOD(device_shutdown, bus_generic_shutdown), 635 DEVMETHOD(device_suspend, bus_generic_suspend), 636 DEVMETHOD(device_resume, bus_generic_resume), 637 638 /* Bus interface */ 639 DEVMETHOD(bus_print_child, eisa_print_child), 640 DEVMETHOD(bus_probe_nomatch, eisa_probe_nomatch), 641 DEVMETHOD(bus_read_ivar, eisa_read_ivar), 642 DEVMETHOD(bus_write_ivar, eisa_write_ivar), 643 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 644 DEVMETHOD(bus_alloc_resource, eisa_alloc_resource), 645 DEVMETHOD(bus_release_resource, eisa_release_resource), 646 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 647 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 648 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 649 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 650 651 /* EISA interface */ 652 DEVMETHOD(eisa_add_intr, eisa_add_intr_m), 653 DEVMETHOD(eisa_add_iospace, eisa_add_iospace_m), 654 DEVMETHOD(eisa_add_mspace, eisa_add_mspace_m), 655 656 { 0, 0 } 657}; 658 659static driver_t eisa_driver = { 660 "eisa", 661 eisa_methods, 662 1, /* no softc */ 663}; 664 665DRIVER_MODULE(eisa, eisab, eisa_driver, eisa_devclass, 0, 0); 666DRIVER_MODULE(eisa, legacy, eisa_driver, eisa_devclass, 0, 0); 667