eisaconf.c revision 45804
1/* 2 * EISA bus probe and attach routines 3 * 4 * Copyright (c) 1995, 1996 Justin T. Gibbs. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice immediately at the beginning of the file, without modification, 12 * this list of conditions, and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $Id: eisaconf.c,v 1.38 1999/04/18 15:50:33 peter Exp $ 32 */ 33 34#include "opt_eisa.h" 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/queue.h> 39#include <sys/malloc.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42#include <sys/bus.h> 43 44#include <machine/limits.h> 45#include <machine/bus.h> 46#include <machine/resource.h> 47#include <sys/rman.h> 48 49#include <i386/eisa/eisaconf.h> 50 51#include <sys/interrupt.h> 52 53typedef struct resvaddr { 54 u_long addr; /* start address */ 55 u_long size; /* size of reserved area */ 56 int flags; 57 struct resource *res; /* resource manager handle */ 58 LIST_ENTRY(resvaddr) links; /* List links */ 59} resvaddr_t; 60 61LIST_HEAD(resvlist, resvaddr); 62 63struct irq_node { 64 int irq_no; 65 void *idesc; 66 TAILQ_ENTRY(irq_node) links; 67}; 68 69TAILQ_HEAD(irqlist, irq_node); 70 71struct eisa_ioconf { 72 int slot; 73 struct resvlist ioaddrs; /* list of reserved I/O ranges */ 74 struct resvlist maddrs; /* list of reserved memory ranges */ 75 struct irqlist irqs; /* list of reserved irqs */ 76}; 77 78/* To be replaced by the "super device" generic device structure... */ 79struct eisa_device { 80 eisa_id_t id; 81 struct eisa_ioconf ioconf; 82}; 83 84 85/* 86 * Local function declarations and static variables 87 */ 88#if 0 89static void eisa_reg_print __P((struct eisa_device *e_dev, 90 char *string, char *separator)); 91static int eisa_add_resvaddr __P((struct eisa_device *e_dev, 92 struct resvlist *head, u_long base, 93 u_long size, int flags)); 94static int eisa_reg_resvaddr __P((struct eisa_device *e_dev, 95 struct resvlist *head, resvaddr_t *resvaddr, 96 int *reg_count)); 97#endif 98 99#if 0 100/* 101 * Keep some state about what we've printed so far 102 * to make probe output pretty. 103 */ 104static struct { 105 int in_registration;/* reg_start has been called */ 106 int num_interrupts; 107 int num_ioaddrs; 108 int num_maddrs; 109 int column; /* How much we have output so far. */ 110#define MAX_COL 80 111} reg_state; 112#endif 113 114/* Global variable, so UserConfig can change it. */ 115#ifndef EISA_SLOTS 116#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */ 117#endif 118int num_eisa_slots = EISA_SLOTS; 119 120static devclass_t eisa_devclass; 121 122static int 123mainboard_probe(device_t dev) 124{ 125 char *idstring; 126 eisa_id_t id = eisa_get_id(dev); 127 128 if (eisa_get_slot(dev) != 0) 129 return (ENXIO); 130 131 idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1, 132 M_DEVBUF, M_NOWAIT); 133 if (idstring == NULL) { 134 panic("Eisa probe unable to malloc"); 135 } 136 sprintf(idstring, "%c%c%c%x%x (System Board)", 137 EISA_MFCTR_CHAR0(id), 138 EISA_MFCTR_CHAR1(id), 139 EISA_MFCTR_CHAR2(id), 140 EISA_PRODUCT_ID(id), 141 EISA_REVISION_ID(id)); 142 device_set_desc(dev, idstring); 143 144 return (0); 145} 146 147static int 148mainboard_attach(device_t dev) 149{ 150 return (0); 151} 152 153static device_method_t mainboard_methods[] = { 154 /* Device interface */ 155 DEVMETHOD(device_probe, mainboard_probe), 156 DEVMETHOD(device_attach, mainboard_attach), 157 158 { 0, 0 } 159}; 160 161static driver_t mainboard_driver = { 162 "mainboard", 163 mainboard_methods, 164 DRIVER_TYPE_MISC, 165 1, 166}; 167 168static devclass_t mainboard_devclass; 169 170DRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0); 171 172/* 173** probe for EISA devices 174*/ 175static int 176eisa_probe(device_t dev) 177{ 178 int i,slot; 179 struct eisa_device *e_dev; 180 int eisaBase = 0xc80; 181 eisa_id_t eisa_id; 182 183 device_set_desc(dev, "EISA bus"); 184 185 for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) { 186 int id_size = sizeof(eisa_id); 187 eisa_id = 0; 188 for( i = 0; i < id_size; i++ ) { 189 outb(eisaBase,0x80 + i); /*Some cards require priming*/ 190 eisa_id |= inb(eisaBase+i) << ((id_size-i-1)*CHAR_BIT); 191 } 192 if (eisa_id & 0x80000000) 193 continue; /* no EISA card in slot */ 194 195 /* Prepare an eisa_device_node for this slot */ 196 e_dev = (struct eisa_device *)malloc(sizeof(*e_dev), 197 M_DEVBUF, M_NOWAIT); 198 if (!e_dev) { 199 printf("eisa0: cannot malloc eisa_device"); 200 break; /* Try to attach what we have already */ 201 } 202 bzero(e_dev, sizeof(*e_dev)); 203 204 e_dev->id = eisa_id; 205 206 e_dev->ioconf.slot = slot; 207 208 /* Initialize our lists of reserved addresses */ 209 LIST_INIT(&(e_dev->ioconf.ioaddrs)); 210 LIST_INIT(&(e_dev->ioconf.maddrs)); 211 TAILQ_INIT(&(e_dev->ioconf.irqs)); 212 213 device_add_child(dev, NULL, -1, e_dev); 214 } 215 216 return 0; 217} 218 219static void 220eisa_print_child(device_t dev, device_t child) 221{ 222 /* XXX print resource descriptions? */ 223 printf(" at slot %d", eisa_get_slot(child)); 224 printf(" on %s", device_get_nameunit(dev)); 225} 226 227static int 228eisa_find_irq(struct eisa_device *e_dev, int rid) 229{ 230 int i; 231 struct irq_node *irq; 232 233 for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 234 i < rid && irq; 235 i++, irq = TAILQ_NEXT(irq, links)) 236 ; 237 238 if (irq) 239 return irq->irq_no; 240 else 241 return -1; 242} 243 244static struct resvaddr * 245eisa_find_maddr(struct eisa_device *e_dev, int rid) 246{ 247 int i; 248 struct resvaddr *resv; 249 250 for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs); 251 i < rid && resv; 252 i++, resv = LIST_NEXT(resv, links)) 253 ; 254 255 return resv; 256} 257 258static struct resvaddr * 259eisa_find_ioaddr(struct eisa_device *e_dev, int rid) 260{ 261 int i; 262 struct resvaddr *resv; 263 264 for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs); 265 i < rid && resv; 266 i++, resv = LIST_NEXT(resv, links)) 267 ; 268 269 return resv; 270} 271 272static int 273eisa_read_ivar(device_t dev, device_t child, int which, u_long *result) 274{ 275 struct eisa_device *e_dev = device_get_ivars(child); 276 277 switch (which) { 278 case EISA_IVAR_SLOT: 279 *result = e_dev->ioconf.slot; 280 break; 281 282 case EISA_IVAR_ID: 283 *result = e_dev->id; 284 break; 285 286 case EISA_IVAR_IRQ: 287 /* XXX only first irq */ 288 *result = eisa_find_irq(e_dev, 0); 289 break; 290 291 default: 292 return (ENOENT); 293 } 294 295 return (0); 296} 297 298static int 299eisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 300{ 301 return (EINVAL); 302} 303 304static struct resource * 305eisa_alloc_resource(device_t dev, device_t child, int type, int *rid, 306 u_long start, u_long end, u_long count, u_int flags) 307{ 308 int isdefault; 309 struct eisa_device *e_dev = device_get_ivars(child); 310 struct resource *rv, **rvp = 0; 311 312 isdefault = (device_get_parent(child) == dev 313 && start == 0UL && end == ~0UL && count == 1); 314 315 switch (type) { 316 case SYS_RES_IRQ: 317 if (isdefault) { 318 int irq = eisa_find_irq(e_dev, *rid); 319 if (irq == -1) 320 return 0; 321 start = end = irq; 322 count = 1; 323 } 324 break; 325 326 case SYS_RES_MEMORY: 327 if (isdefault) { 328 struct resvaddr *resv; 329 330 resv = eisa_find_maddr(e_dev, *rid); 331 if (!resv) 332 return 0; 333 334 start = resv->addr; 335 end = resv->size - 1; 336 count = resv->size; 337 rvp = &resv->res; 338 } 339 break; 340 341 case SYS_RES_IOPORT: 342 if (isdefault) { 343 struct resvaddr *resv; 344 345 resv = eisa_find_ioaddr(e_dev, *rid); 346 if (!resv) 347 return 0; 348 349 start = resv->addr; 350 end = resv->size - 1; 351 count = resv->size; 352 rvp = &resv->res; 353 } 354 break; 355 356 default: 357 return 0; 358 } 359 360 rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 361 type, rid, start, end, count, flags); 362 if (rvp) 363 *rvp = rv; 364 365 return rv; 366} 367 368static int 369eisa_release_resource(device_t dev, device_t child, int type, int rid, 370 struct resource *r) 371{ 372 int rv; 373 struct eisa_device *e_dev = device_get_ivars(child); 374 struct resvaddr *resv = 0; 375 376 switch (type) { 377 case SYS_RES_IRQ: 378 if (eisa_find_irq(e_dev, rid) == -1) 379 return EINVAL; 380 break; 381 382 case SYS_RES_MEMORY: 383 if (device_get_parent(child) == dev) 384 resv = eisa_find_maddr(e_dev, rid); 385 break; 386 387 388 case SYS_RES_IOPORT: 389 if (device_get_parent(child) == dev) 390 resv = eisa_find_ioaddr(e_dev, rid); 391 break; 392 393 default: 394 return (ENOENT); 395 } 396 397 rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 398 399 if (rv == 0) { 400 if (resv) 401 resv->res = 0; 402 } 403 404 return rv; 405} 406 407#if 0 408 409/* Interrupt and I/O space registration facitlities */ 410void 411eisa_reg_start(e_dev) 412 struct eisa_device *e_dev; 413{ 414 /* 415 * Announce the device. 416 */ 417 char *string; 418 419 reg_state.in_registration = 1; 420 reg_state.num_interrupts = 0; 421 reg_state.num_ioaddrs = 0; 422 reg_state.num_maddrs = 0; 423 reg_state.column = 0; 424 425 string = malloc(strlen(e_dev->full_name) + sizeof(" <>") + /*NULL*/1, 426 M_TEMP, M_NOWAIT); 427 if(!string) { 428 printf("eisa0: cannot malloc device description string\n"); 429 return; 430 } 431 sprintf(string, " <%s>", e_dev->full_name); 432 eisa_reg_print(e_dev, string, /*separator=*/NULL); 433 free(string, M_TEMP); 434} 435 436/* 437 * Output registration information mindfull of screen wrap. 438 * Output an optional character separator before the string 439 * if the line does not wrap. 440 */ 441static void 442eisa_reg_print(e_dev, string, separator) 443 struct eisa_device *e_dev; 444 char *string; 445 char *separator; 446{ 447 int len = strlen(string); 448 449 if(separator) 450 len++; 451 452 if(reg_state.column + len > MAX_COL) { 453 printf("\n"); 454 reg_state.column = 0; 455 } 456 else if(separator) { 457 printf("%c", *separator); 458 reg_state.column++; 459 } 460 461 if(reg_state.column == 0) 462 reg_state.column += printf("%s%ld:%s", 463 e_dev->driver->name, 464 e_dev->unit, 465 string); 466 else 467 reg_state.column += printf("%s", string); 468} 469 470/* Interrupt and I/O space registration facitlities */ 471void 472eisa_reg_end(e_dev) 473 struct eisa_device *e_dev; 474{ 475 if( reg_state.in_registration ) 476 { 477 char string[25]; 478 479 snprintf(string, sizeof(string), " on %s0 slot %d", 480 mainboard_drv.name, 481 e_dev->ioconf.slot); 482 eisa_reg_print(e_dev, string, NULL); 483 printf("\n"); 484 reg_state.in_registration = 0; 485 } 486 else 487 printf("eisa_reg_end called outside of a " 488 "registration session\n"); 489} 490 491#endif /* 0 */ 492 493int 494eisa_add_intr(dev, irq) 495 device_t dev; 496 int irq; 497{ 498 struct eisa_device *e_dev = device_get_ivars(dev); 499 struct irq_node *irq_info; 500 501 irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF, 502 M_NOWAIT); 503 if (irq_info == NULL) 504 return (1); 505 506 irq_info->irq_no = irq; 507 irq_info->idesc = NULL; 508 TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links); 509 return 0; 510} 511 512#if 0 513 514int 515eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared) 516 struct eisa_device *e_dev; 517 int irq; 518 void (*func)(void *); 519 void *arg; 520 u_int *maskptr; 521 int shared; 522{ 523 char string[25]; 524 char separator = ','; 525 526#if NOT_YET 527 /* 528 * Punt on conflict detection for the moment. 529 * I want to develop a generic routine to do 530 * this for all device types. 531 */ 532 int checkthese = CC_IRQ; 533 if (haveseen_dev(dev, checkthese)) 534 return 1; 535#endif 536 if (reg_state.in_registration) { 537 /* 538 * Find the first instance of this irq that has a 539 * NULL idesc. 540 */ 541 struct irq_node *cur_irq; 542 543 cur_irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 544 while (cur_irq != NULL) { 545 if (cur_irq->irq_no == irq 546 && cur_irq->idesc == NULL) { 547 /* XXX use cfg->devdata */ 548 void *dev_instance = (void *)-1; 549 550 cur_irq->idesc = intr_create(dev_instance, 551 irq, 552 func, 553 arg, 554 maskptr, 0); 555 break; 556 } 557 cur_irq = TAILQ_NEXT(cur_irq, links); 558 } 559 560 if (cur_irq == NULL || cur_irq->idesc == NULL) 561 return (-1); 562 } else { 563 return EPERM; 564 } 565 566 snprintf(string, sizeof(string), " irq %d", irq); 567 eisa_reg_print(e_dev, string, reg_state.num_interrupts ? 568 &separator : NULL); 569 reg_state.num_interrupts++; 570 return (0); 571} 572 573int 574eisa_release_intr(e_dev, irq, func) 575 struct eisa_device *e_dev; 576 int irq; 577 void (*func)(void *); 578{ 579 int result; 580 struct irq_node *cur_irq; 581 582 result = -1; 583 cur_irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 584 while (cur_irq != NULL) { 585 if (cur_irq->irq_no == irq) { 586 struct irq_node *next_irq; 587 588 next_irq = TAILQ_NEXT(cur_irq, links); 589 if (cur_irq->idesc != NULL) 590 intr_destroy(cur_irq->idesc); 591 TAILQ_REMOVE(&e_dev->ioconf.irqs, cur_irq, links); 592 free(cur_irq, M_DEVBUF); 593 cur_irq = next_irq; 594 result = 0; 595 } else { 596 cur_irq = TAILQ_NEXT(cur_irq, links); 597 } 598 } 599 if (result != 0) { 600 printf("%s%ld: Attempted to release an interrupt (%d) " 601 "it doesn't own\n", e_dev->driver->name, 602 e_dev->unit, irq); 603 } 604 605 return (result); 606} 607 608int 609eisa_enable_intr(e_dev, irq) 610 struct eisa_device *e_dev; 611 int irq; 612{ 613 struct irq_node *cur_irq; 614 int result; 615 616 result = -1; 617 cur_irq = TAILQ_FIRST(&e_dev->ioconf.irqs); 618 while (cur_irq != NULL) { 619 if (cur_irq->irq_no == irq 620 && cur_irq->idesc != NULL) { 621 result = intr_connect(cur_irq->idesc); 622 } 623 cur_irq = TAILQ_NEXT(cur_irq, links); 624 } 625 return (result); 626} 627 628#endif /* 0 */ 629 630static int 631eisa_add_resvaddr(e_dev, head, base, size, flags) 632 struct eisa_device *e_dev; 633 struct resvlist *head; 634 u_long base; 635 u_long size; 636 int flags; 637{ 638 resvaddr_t *reservation; 639 640 reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t), 641 M_DEVBUF, M_NOWAIT); 642 if(!reservation) 643 return (ENOMEM); 644 645 reservation->addr = base; 646 reservation->size = size; 647 reservation->flags = flags; 648 649 if (!head->lh_first) { 650 LIST_INSERT_HEAD(head, reservation, links); 651 } 652 else { 653 resvaddr_t *node; 654 for(node = head->lh_first; node; node = node->links.le_next) { 655 if (node->addr > reservation->addr) { 656 /* 657 * List is sorted in increasing 658 * address order. 659 */ 660 LIST_INSERT_BEFORE(node, reservation, links); 661 break; 662 } 663 664 if (node->addr == reservation->addr) { 665 /* 666 * If the entry we want to add 667 * matches any already in here, 668 * fail. 669 */ 670 free(reservation, M_DEVBUF); 671 return (EEXIST); 672 } 673 674 if (!node->links.le_next) { 675 LIST_INSERT_AFTER(node, reservation, links); 676 break; 677 } 678 } 679 } 680 return (0); 681} 682 683int 684eisa_add_mspace(dev, mbase, msize, flags) 685 device_t dev; 686 u_long mbase; 687 u_long msize; 688 int flags; 689{ 690 struct eisa_device *e_dev = device_get_ivars(dev); 691 return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize, 692 flags); 693} 694 695int 696eisa_add_iospace(dev, iobase, iosize, flags) 697 device_t dev; 698 u_long iobase; 699 u_long iosize; 700 int flags; 701{ 702 struct eisa_device *e_dev = device_get_ivars(dev); 703 return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase, 704 iosize, flags); 705} 706 707#if 0 708 709static int 710eisa_reg_resvaddr(e_dev, head, resvaddr, reg_count) 711 struct eisa_device *e_dev; 712 struct resvlist *head; 713 resvaddr_t *resvaddr; 714 int *reg_count; 715{ 716 if (reg_state.in_registration) { 717 resvaddr_t *node; 718 /* 719 * Ensure that this resvaddr is actually in the devices' 720 * reservation list. 721 */ 722 for(node = head->lh_first; node; 723 node = node->links.le_next) { 724 if (node == resvaddr) { 725 char buf[35]; 726 char separator = ','; 727 char *string = buf; 728 729 if (*reg_count == 0) { 730 /* First time */ 731 string += sprintf(string, " at"); 732 } 733 734 if (node->size == 1 735 || (node->flags & RESVADDR_BITMASK)) 736 sprintf(string, " 0x%lx", node->addr); 737 else 738 sprintf(string, " 0x%lx-0x%lx", 739 node->addr, 740 node->addr + node->size - 1); 741 eisa_reg_print(e_dev, buf, 742 *reg_count ? &separator : NULL); 743 (*reg_count)++; 744 return (0); 745 } 746 } 747 return (ENOENT); 748 } 749 return EPERM; 750} 751 752int 753eisa_reg_mspace(e_dev, resvaddr) 754 struct eisa_device *e_dev; 755 resvaddr_t *resvaddr; 756{ 757#ifdef NOT_YET 758 /* 759 * Punt on conflict detection for the moment. 760 * I want to develop a generic routine to do 761 * this for all device types. 762 */ 763 int checkthese = CC_MADDR; 764 if (haveseen_dev(dev, checkthese)) 765 return -1; 766#endif 767 return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.maddrs), resvaddr, 768 &(reg_state.num_maddrs))); 769} 770 771int 772eisa_reg_iospace(e_dev, resvaddr) 773 struct eisa_device *e_dev; 774 resvaddr_t *resvaddr; 775{ 776#ifdef NOT_YET 777 /* 778 * Punt on conflict detection for the moment. 779 * I want to develop a generic routine to do 780 * this for all device types. 781 */ 782 int checkthese = CC_IOADDR; 783 if (haveseen_dev(dev, checkthese)) 784 return -1; 785#endif 786 return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), resvaddr, 787 &(reg_state.num_ioaddrs))); 788} 789 790#endif 791 792static device_method_t eisa_methods[] = { 793 /* Device interface */ 794 DEVMETHOD(device_probe, eisa_probe), 795 DEVMETHOD(device_attach, bus_generic_attach), 796 DEVMETHOD(device_shutdown, bus_generic_shutdown), 797 798 /* Bus interface */ 799 DEVMETHOD(bus_print_child, eisa_print_child), 800 DEVMETHOD(bus_read_ivar, eisa_read_ivar), 801 DEVMETHOD(bus_write_ivar, eisa_write_ivar), 802 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 803 DEVMETHOD(bus_alloc_resource, eisa_alloc_resource), 804 DEVMETHOD(bus_release_resource, eisa_release_resource), 805 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 806 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 807 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 808 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 809 810 { 0, 0 } 811}; 812 813static driver_t eisa_driver = { 814 "eisa", 815 eisa_methods, 816 DRIVER_TYPE_MISC, 817 1, /* no softc */ 818}; 819 820DRIVER_MODULE(eisa, isab, eisa_driver, eisa_devclass, 0, 0); 821