diff options
Diffstat (limited to 'sys/dev/eisa/eisaconf.c')
-rw-r--r-- | sys/dev/eisa/eisaconf.c | 661 |
1 files changed, 0 insertions, 661 deletions
diff --git a/sys/dev/eisa/eisaconf.c b/sys/dev/eisa/eisaconf.c deleted file mode 100644 index e1eee615d141..000000000000 --- a/sys/dev/eisa/eisaconf.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * EISA bus probe and attach routines - * - * Copyright (c) 1995, 1996 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: eisaconf.c,v 1.36 1998/12/04 22:54:46 archie Exp $ - */ - -#include "opt_eisa.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/linker_set.h> -#include <sys/malloc.h> - -#include <machine/limits.h> - -#include <i386/eisa/eisaconf.h> - -#include <sys/interrupt.h> - -struct eisa_device_node{ - struct eisa_device dev; - struct eisa_device_node *next; -}; - -/* - * This should probably be a list of "struct device" once it exists. - * A struct device will incorperate ioconf and driver entry point data - * regardless of how its attached to the system (via unions) as well - * as more generic information that all device types should support (unit - * number, if its installed, etc). - */ -static struct eisa_device_node *eisa_dev_list; -static struct eisa_device_node **eisa_dev_list_tail = &eisa_dev_list; -static u_long eisa_unit; - -static struct eisa_driver mainboard_drv = { - "eisa", - NULL, - NULL, - NULL, - &eisa_unit - }; - -/* - * Add the mainboard_drv to the eisa driver linkerset so that it is - * defined even if no EISA drivers are linked into the kernel. - */ -DATA_SET (eisadriver_set, mainboard_drv); - -/* - * Local function declarations and static variables - */ -static void eisa_reg_print __P((struct eisa_device *e_dev, - char *string, char *separator)); -static int eisa_add_resvaddr __P((struct eisa_device *e_dev, - struct resvlist *head, u_long base, - u_long size, int flags)); -static int eisa_reg_resvaddr __P((struct eisa_device *e_dev, - struct resvlist *head, resvaddr_t *resvaddr, - int *reg_count)); - -/* - * Keep some state about what we've printed so far - * to make probe output pretty. - */ -static struct { - int in_registration;/* reg_start has been called */ - int num_interrupts; - int num_ioaddrs; - int num_maddrs; - int column; /* How much we have output so far. */ -#define MAX_COL 80 -} reg_state; - -/* Global variable, so UserConfig can change it. */ -#ifndef EISA_SLOTS -#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */ -#endif -int num_eisa_slots = EISA_SLOTS; - -/* -** probe for EISA devices -*/ -void -eisa_configure() -{ - int i,slot; - struct eisa_device_node *dev_node; - struct eisa_driver **e_drvp; - struct eisa_driver *e_drv; - struct eisa_device *e_dev; - int eisaBase = 0xc80; - eisa_id_t eisa_id; - - e_drvp = (struct eisa_driver**)eisadriver_set.ls_items; - - for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) { - int id_size = sizeof(eisa_id); - eisa_id = 0; - for( i = 0; i < id_size; i++ ) { - outb(eisaBase,0x80 + i); /*Some cards require priming*/ - eisa_id |= inb(eisaBase+i) << ((id_size-i-1)*CHAR_BIT); - } - if (eisa_id & 0x80000000) - continue; /* no EISA card in slot */ - - /* Prepare an eisa_device_node for this slot */ - dev_node = (struct eisa_device_node *)malloc(sizeof(*dev_node), - M_DEVBUF, M_NOWAIT); - if (!dev_node) { - printf("eisa0: cannot malloc eisa_device_node"); - break; /* Try to attach what we have already */ - } - bzero(dev_node, sizeof(*dev_node)); - e_dev = &(dev_node->dev); - - e_dev->id = eisa_id; - - e_dev->full_name = "Unattached Device"; - - e_dev->ioconf.slot = slot; - - /* Initialize our lists of reserved addresses */ - LIST_INIT(&(e_dev->ioconf.ioaddrs)); - LIST_INIT(&(e_dev->ioconf.maddrs)); - TAILQ_INIT(&(e_dev->ioconf.irqs)); - - *eisa_dev_list_tail = dev_node; - eisa_dev_list_tail = &dev_node->next; - } - - dev_node = eisa_dev_list; - - /* - * "Attach" the system board - */ - - /* The first will be the motherboard in a true EISA system */ - if (dev_node && (dev_node->dev.ioconf.slot == 0)) { - char *idstring; - - e_dev = &dev_node->dev; - e_dev->driver = &mainboard_drv; - e_dev->unit = (*e_dev->driver->unit)++; - idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1, - M_DEVBUF, M_NOWAIT); - if (idstring == NULL) { - panic("Eisa probe unable to malloc"); - } - sprintf(idstring, "%c%c%c%x%x (System Board)", - EISA_MFCTR_CHAR0(e_dev->id), - EISA_MFCTR_CHAR1(e_dev->id), - EISA_MFCTR_CHAR2(e_dev->id), - EISA_PRODUCT_ID(e_dev->id), - EISA_REVISION_ID(e_dev->id)); - e_dev->full_name = idstring; - - printf("%s%ld: <%s>\n", - e_dev->driver->name, - e_dev->unit, - e_dev->full_name); - - /* Should set the iosize, but I don't have a spec handy */ - printf("Probing for devices on the EISA bus\n"); - dev_node = dev_node->next; - } - - if (!eisa_dev_list) { - /* - * No devices. - */ - return; - } - /* - * See what devices we recognize. - */ - while((e_drv = *e_drvp++)) { - if (e_drv->probe) - (*e_drv->probe)(); - } - - /* - * Attach the devices we found in slot order - */ - for (; dev_node; dev_node=dev_node->next) { - e_dev = &dev_node->dev; - e_drv = e_dev->driver; - - if (e_drv) { - /* - * Determine the proper unit number for this device. - * Here we should look in the device table generated - * by config to see if this type of device is enabled - * either generically or for this particular address - * as well as determine if a reserved unit number - * should be used. We should also ensure that the - * "next availible unit number" skips over "wired" unit - * numbers. This will be done after config is fixed or - * some other configuration method is chosen. - */ - e_dev->unit = (*e_drv->unit)++; - if ((*e_drv->attach)(e_dev) < 0) { - /* Ensure registration has ended */ - reg_state.in_registration = 0; - printf("\n%s0:%d <%s> attach failed\n", - mainboard_drv.name, - e_dev->ioconf.slot, - e_dev->full_name); - continue; - } - /* Ensure registration has ended */ - reg_state.in_registration = 0; - } - else { - /* Announce unattached device */ - printf("%s0:%d <%c%c%c%x%x=0x%x> unknown device\n", - mainboard_drv.name, - e_dev->ioconf.slot, - EISA_MFCTR_CHAR0(e_dev->id), - EISA_MFCTR_CHAR1(e_dev->id), - EISA_MFCTR_CHAR2(e_dev->id), - EISA_PRODUCT_ID(e_dev->id), - EISA_REVISION_ID(e_dev->id), - e_dev->id); - } - } -} - -struct eisa_device * -eisa_match_dev(e_dev, match_func) - struct eisa_device *e_dev; - const char* (*match_func)(eisa_id_t); -{ - struct eisa_device_node *e_node = eisa_dev_list; - - if (e_dev) { - /* Start our search from the last successful match */ - e_node = ((struct eisa_device_node *)e_dev)->next; - } - - for(; e_node; e_node = e_node->next) { - const char *result; - if (e_node->dev.driver) { - /* Already claimed */ - continue; - } - result = (*match_func)(e_node->dev.id); - if (result) { - e_node->dev.full_name = result; - return (&(e_node->dev)); - } - } - return NULL; -} - -/* Interrupt and I/O space registration facitlities */ -void -eisa_reg_start(e_dev) - struct eisa_device *e_dev; -{ - /* - * Announce the device. - */ - char *string; - - reg_state.in_registration = 1; - reg_state.num_interrupts = 0; - reg_state.num_ioaddrs = 0; - reg_state.num_maddrs = 0; - reg_state.column = 0; - - string = malloc(strlen(e_dev->full_name) + sizeof(" <>") + /*NULL*/1, - M_TEMP, M_NOWAIT); - if(!string) { - printf("eisa0: cannot malloc device description string\n"); - return; - } - sprintf(string, " <%s>", e_dev->full_name); - eisa_reg_print(e_dev, string, /*separator=*/NULL); - free(string, M_TEMP); -} - -/* - * Output registration information mindfull of screen wrap. - * Output an optional character separator before the string - * if the line does not wrap. - */ -static void -eisa_reg_print(e_dev, string, separator) - struct eisa_device *e_dev; - char *string; - char *separator; -{ - int len = strlen(string); - - if(separator) - len++; - - if(reg_state.column + len > MAX_COL) { - printf("\n"); - reg_state.column = 0; - } - else if(separator) { - printf("%c", *separator); - reg_state.column++; - } - - if(reg_state.column == 0) - reg_state.column += printf("%s%ld:%s", - e_dev->driver->name, - e_dev->unit, - string); - else - reg_state.column += printf("%s", string); -} - -/* Interrupt and I/O space registration facitlities */ -void -eisa_reg_end(e_dev) - struct eisa_device *e_dev; -{ - if( reg_state.in_registration ) - { - char string[25]; - - snprintf(string, sizeof(string), " on %s0 slot %d", - mainboard_drv.name, - e_dev->ioconf.slot); - eisa_reg_print(e_dev, string, NULL); - printf("\n"); - reg_state.in_registration = 0; - } - else - printf("eisa_reg_end called outside of a " - "registration session\n"); -} - -int -eisa_add_intr(e_dev, irq) - struct eisa_device *e_dev; - int irq; -{ - struct irq_node *irq_info; - - irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF, - M_NOWAIT); - if (irq_info == NULL) - return (1); - - irq_info->irq_no = irq; - irq_info->idesc = NULL; - TAILQ_INSERT_TAIL(&e_dev->ioconf.irqs, irq_info, links); - return 0; -} - -int -eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared) - struct eisa_device *e_dev; - int irq; - void (*func)(void *); - void *arg; - u_int *maskptr; - int shared; -{ - char string[25]; - char separator = ','; - -#if NOT_YET - /* - * Punt on conflict detection for the moment. - * I want to develop a generic routine to do - * this for all device types. - */ - int checkthese = CC_IRQ; - if (haveseen_dev(dev, checkthese)) - return 1; -#endif - if (reg_state.in_registration) { - /* - * Find the first instance of this irq that has a - * NULL idesc. - */ - struct irq_node *cur_irq; - - cur_irq = TAILQ_FIRST(&e_dev->ioconf.irqs); - while (cur_irq != NULL) { - if (cur_irq->irq_no == irq - && cur_irq->idesc == NULL) { - /* XXX use cfg->devdata */ - void *dev_instance = (void *)-1; - - cur_irq->idesc = intr_create(dev_instance, - irq, - func, - arg, - maskptr, 0); - break; - } - cur_irq = TAILQ_NEXT(cur_irq, links); - } - - if (cur_irq == NULL || cur_irq->idesc == NULL) - return (-1); - } else { - return EPERM; - } - - snprintf(string, sizeof(string), " irq %d", irq); - eisa_reg_print(e_dev, string, reg_state.num_interrupts ? - &separator : NULL); - reg_state.num_interrupts++; - return (0); -} - -int -eisa_release_intr(e_dev, irq, func) - struct eisa_device *e_dev; - int irq; - void (*func)(void *); -{ - int result; - struct irq_node *cur_irq; - - result = -1; - cur_irq = TAILQ_FIRST(&e_dev->ioconf.irqs); - while (cur_irq != NULL) { - if (cur_irq->irq_no == irq) { - struct irq_node *next_irq; - - next_irq = TAILQ_NEXT(cur_irq, links); - if (cur_irq->idesc != NULL) - intr_destroy(cur_irq->idesc); - TAILQ_REMOVE(&e_dev->ioconf.irqs, cur_irq, links); - free(cur_irq, M_DEVBUF); - cur_irq = next_irq; - result = 0; - } else { - cur_irq = TAILQ_NEXT(cur_irq, links); - } - } - if (result != 0) { - printf("%s%ld: Attempted to release an interrupt (%d) " - "it doesn't own\n", e_dev->driver->name, - e_dev->unit, irq); - } - - return (result); -} - -int -eisa_enable_intr(e_dev, irq) - struct eisa_device *e_dev; - int irq; -{ - struct irq_node *cur_irq; - int result; - - result = -1; - cur_irq = TAILQ_FIRST(&e_dev->ioconf.irqs); - while (cur_irq != NULL) { - if (cur_irq->irq_no == irq - && cur_irq->idesc != NULL) { - result = intr_connect(cur_irq->idesc); - } - cur_irq = TAILQ_NEXT(cur_irq, links); - } - return (result); -} - -static int -eisa_add_resvaddr(e_dev, head, base, size, flags) - struct eisa_device *e_dev; - struct resvlist *head; - u_long base; - u_long size; - int flags; -{ - resvaddr_t *reservation; - - reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t), - M_DEVBUF, M_NOWAIT); - if(!reservation) - return (ENOMEM); - - reservation->addr = base; - reservation->size = size; - reservation->flags = flags; - - if (!head->lh_first) { - LIST_INSERT_HEAD(head, reservation, links); - } - else { - resvaddr_t *node; - for(node = head->lh_first; node; node = node->links.le_next) { - if (node->addr > reservation->addr) { - /* - * List is sorted in increasing - * address order. - */ - LIST_INSERT_BEFORE(node, reservation, links); - break; - } - - if (node->addr == reservation->addr) { - /* - * If the entry we want to add - * matches any already in here, - * fail. - */ - free(reservation, M_DEVBUF); - return (EEXIST); - } - - if (!node->links.le_next) { - LIST_INSERT_AFTER(node, reservation, links); - break; - } - } - } - return (0); -} - -int -eisa_add_mspace(e_dev, mbase, msize, flags) - struct eisa_device *e_dev; - u_long mbase; - u_long msize; - int flags; -{ - return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize, - flags); -} - -int -eisa_add_iospace(e_dev, iobase, iosize, flags) - struct eisa_device *e_dev; - u_long iobase; - u_long iosize; - int flags; -{ - return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase, - iosize, flags); -} - -static int -eisa_reg_resvaddr(e_dev, head, resvaddr, reg_count) - struct eisa_device *e_dev; - struct resvlist *head; - resvaddr_t *resvaddr; - int *reg_count; -{ - if (reg_state.in_registration) { - resvaddr_t *node; - /* - * Ensure that this resvaddr is actually in the devices' - * reservation list. - */ - for(node = head->lh_first; node; - node = node->links.le_next) { - if (node == resvaddr) { - char buf[35]; - char separator = ','; - char *string = buf; - - if (*reg_count == 0) { - /* First time */ - string += sprintf(string, " at"); - } - - if (node->size == 1 - || (node->flags & RESVADDR_BITMASK)) - sprintf(string, " 0x%lx", node->addr); - else - sprintf(string, " 0x%lx-0x%lx", - node->addr, - node->addr + node->size - 1); - eisa_reg_print(e_dev, buf, - *reg_count ? &separator : NULL); - (*reg_count)++; - return (0); - } - } - return (ENOENT); - } - return EPERM; -} - -int -eisa_reg_mspace(e_dev, resvaddr) - struct eisa_device *e_dev; - resvaddr_t *resvaddr; -{ -#ifdef NOT_YET - /* - * Punt on conflict detection for the moment. - * I want to develop a generic routine to do - * this for all device types. - */ - int checkthese = CC_MADDR; - if (haveseen_dev(dev, checkthese)) - return -1; -#endif - return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.maddrs), resvaddr, - &(reg_state.num_maddrs))); -} - -int -eisa_reg_iospace(e_dev, resvaddr) - struct eisa_device *e_dev; - resvaddr_t *resvaddr; -{ -#ifdef NOT_YET - /* - * Punt on conflict detection for the moment. - * I want to develop a generic routine to do - * this for all device types. - */ - int checkthese = CC_IOADDR; - if (haveseen_dev(dev, checkthese)) - return -1; -#endif - return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), resvaddr, - &(reg_state.num_ioaddrs))); -} - -int -eisa_registerdev(e_dev, driver) - struct eisa_device *e_dev; - struct eisa_driver *driver; -{ - e_dev->driver = driver; /* Driver now owns this device */ - return (0); -} - |