diff options
author | gibbs <gibbs@FreeBSD.org> | 1995-11-09 07:14:11 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1995-11-09 07:14:11 +0000 |
commit | 7b39ff1acd679291e1eaa968c4a256d7c6e3b22f (patch) | |
tree | 483847a276e57960bd0b67138144a9277c259822 /sys/dev/eisa | |
parent | 0476cdd071ff3a1b62b39cd2939ba60377a46755 (diff) | |
download | FreeBSD-src-7b39ff1acd679291e1eaa968c4a256d7c6e3b22f.zip FreeBSD-src-7b39ff1acd679291e1eaa968c4a256d7c6e3b22f.tar.gz |
Second pass on this. Sentinal device node was an uneeded complication.
Handle kdc registration correctly. Catch ISA devices that use eisa
registration and output probe information accordingly.
lsdev will have to be updated to handle EISA devices correctly.
aic7770.c:
Set kdc_isa0 as the parent for 284X cards since its a VL card.
Diffstat (limited to 'sys/dev/eisa')
-rw-r--r-- | sys/dev/eisa/eisaconf.c | 589 |
1 files changed, 286 insertions, 303 deletions
diff --git a/sys/dev/eisa/eisaconf.c b/sys/dev/eisa/eisaconf.c index cddaa1b7..f108693 100644 --- a/sys/dev/eisa/eisaconf.c +++ b/sys/dev/eisa/eisaconf.c @@ -18,22 +18,21 @@ * 4. Modifications may be freely made to this file if the above conditions * are met. * - * $Id: eisaconf.c,v 1.3 1995/11/05 04:42:49 gibbs Exp $ + * $Id: eisaconf.c,v 1.4 1995/11/06 05:20:59 gibbs Exp $ */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/conf.h> #include <sys/malloc.h> +#include <sys/devconf.h> -#include "sys/types.h" #include "i386/isa/icu.h" /* Hmmm. Interrupt stuff? */ -#include <sys/devconf.h> #include "eisaconf.h" struct eisa_device_node{ - struct eisa_device dev; - struct eisa_device_node *next; + struct eisa_device dev; + struct eisa_device_node *next; }; extern struct kern_devconf kdc_cpu0; @@ -74,173 +73,144 @@ static struct eisa_driver mainboard_drv = { void eisa_configure() { - int i,slot; - char *id_string; - struct eisa_device_node *dev_node; - struct eisa_driver **e_drvp = (struct eisa_driver**)eisadriver_set.ls_items; - struct eisa_driver *e_drv; - struct eisa_device *e_dev; - int eisaBase = 0xC80; - int first_slot = 0; - eisa_id_t eisa_id; - - outb(eisaBase,0xFF); - eisa_id = inb(eisaBase); - if (eisa_id & 0x80) { - /* - * Not an EISA machine. We still want to find boards like the - * Adaptec 284x that respond to EISA probes, so we "fake" the - * system board entry which the rest of the code uses as the - * sentinal node in the eisa_dev_list. - */ - first_slot = 1; /* Start at slot 1 just to be safe */ - eisaBase+=0x1000; - dev_node = (struct eisa_device_node *)malloc(sizeof(*dev_node), - M_DEVBUF, M_NOWAIT); - if (!dev_node) { - printf("eisa0: cannot malloc eisa_device_node"); - return; - } - bzero(dev_node, sizeof(*dev_node)); - e_dev = &(dev_node->dev); - e_dev->ioconf.slot = 0; - *eisa_dev_list_tail = dev_node; - eisa_dev_list_tail = &dev_node->next; - } - - for (slot = first_slot; slot < EISA_SLOTS; eisaBase+=0x1000, slot++) { - int id_size = sizeof(eisa_id); - eisa_id = 0; - for( i = 0; i < id_size; i++ ) { - outb(eisaBase,0xc80 + 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; - /* - * Add an EISA ID based descriptive name incase we don't - * have a driver for it. We do this now instead of after all - * probes because in the future, the eisa module will only - * be responsible for creating the list of devices in the system - * for the configuration manager to use. - */ - e_dev->full_name = (char *)malloc(14*sizeof(char), M_DEVBUF, M_NOWAIT); - if (!e_dev->full_name) { - panic("Eisa probe unable to malloc"); - } - sprintf(e_dev->full_name, "%c%c%c%x rev %x", - 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->ioconf.slot = slot; - /* Is iobase defined in any EISA specs? */ - e_dev->ioconf.iobase = eisaBase & 0xff00; - *eisa_dev_list_tail = dev_node; - eisa_dev_list_tail = &dev_node->next; - } - - dev_node = eisa_dev_list; - - /* - * "Attach" the system board - */ - - /* The first entry had better be the motherboard */ - if (!dev_node || (dev_node->dev.ioconf.slot != 0)) - panic("EISA system board not in eisa_dev_list"); - - e_dev = &dev_node->dev; - e_dev->driver = &mainboard_drv; - e_dev->unit = (*e_dev->driver->unit)++; - - if (e_dev->full_name) { /* This is a real EISA system */ - id_string = e_dev->full_name; - e_dev->full_name = (char *)malloc(strlen(e_dev->full_name) - + sizeof(" (System Board)") - + 1, M_DEVBUF, M_NOWAIT); - if (!e_dev->full_name) { - panic("Eisa probe unable to malloc"); + int i,slot; + char *id_string; + 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 < EISA_SLOTS; eisaBase+=0x1000, slot++) { + int id_size = sizeof(eisa_id); + eisa_id = 0; + for( i = 0; i < id_size; i++ ) { + outb(eisaBase,0xc80 + 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; + /* + * Add an EISA ID based descriptive name incase we don't + * have a driver for it. We do this now instead of after all + * probes because in the future, the eisa module will only + * be responsible for creating the list of devices in the system + * for the configuration manager to use. + */ + e_dev->full_name = (char *)malloc(14*sizeof(char), + M_DEVBUF, M_NOWAIT); + if (!e_dev->full_name) { + panic("Eisa probe unable to malloc"); + } + sprintf(e_dev->full_name, "%c%c%c%x rev %x", + 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->ioconf.slot = slot; + /* Is iobase defined in any EISA specs? */ + e_dev->ioconf.iobase = eisaBase & 0xff00; + *eisa_dev_list_tail = dev_node; + eisa_dev_list_tail = &dev_node->next; } - sprintf(e_dev->full_name, "%s (System Board)", id_string); - free(id_string, M_DEVBUF); - printf("%s%ld: <%s>\n", - e_dev->driver->name, - e_dev->unit, - e_dev->full_name); + dev_node = eisa_dev_list; - /* Should set the iosize, but I don't have a spec handy */ + /* + * "Attach" the system board + */ - dev_attach(&kdc_eisa0); /* - * Hmm. Do I need to do this attach always - * in case I attach a 284x in an otherwise - * non-EISA machine? - */ - printf("Probing for devices on the EISA bus\n"); - } + /* The first will be the motherboard in a true EISA system */ + if (dev_node && (dev_node->dev.ioconf.slot == 0)) { + e_dev = &dev_node->dev; + e_dev->driver = &mainboard_drv; + e_dev->unit = (*e_dev->driver->unit)++; + id_string = e_dev->full_name; + e_dev->full_name = (char *)malloc(strlen(e_dev->full_name) + + sizeof(" (System Board)") + + 1, M_DEVBUF, M_NOWAIT); + if (!e_dev->full_name) { + panic("Eisa probe unable to malloc"); + } + sprintf(e_dev->full_name, "%s (System Board)", id_string); + free(id_string, M_DEVBUF); + + 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 */ + kdc_eisa0.kdc_parentdata = e_dev; + dev_attach(&kdc_eisa0); + printf("Probing for devices on the EISA bus\n"); + dev_node = dev_node->next; + } - if (!eisa_dev_list->next) { + if (!eisa_dev_list) { + /* + * No devices. + */ + return; + } /* - * No devices. - * We may be able to remove the sentinal node in the non-EISA - * system case here depending on whether we had to do the - * dev_attach(&kdc_eisa0) up above. + * See what devices we recognize. */ - return; - } - /* - * See what devices we recognize. - */ - while((e_drv = *e_drvp++)) { - (*e_drv->probe)(); - } - - /* - * Attach the devices we found in slot order - */ - for (dev_node = eisa_dev_list->next; 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) { - /* Clean up after the device?? */ - } - e_dev->kdc->kdc_unit = e_dev->unit; + while((e_drv = *e_drvp++)) { + (*e_drv->probe)(); } - else { - /* Announce unattached device */ - printf("%s%ld:%d <%s> unknown device\n", - eisa_dev_list->dev.driver->name, /* Mainboard */ - eisa_dev_list->dev.unit, - e_dev->ioconf.slot, - e_dev->full_name); + + /* + * 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) { + printf("%s0:%d <%s> attach failed\n", + mainboard_drv.name, + e_dev->ioconf.slot, + e_dev->full_name); + continue; + } + e_dev->kdc->kdc_unit = e_dev->unit; + } + else { + /* Announce unattached device */ + printf("%s0:%d <%s> unknown device\n", + mainboard_drv.name, + e_dev->ioconf.slot, + e_dev->full_name); + } } - } } struct eisa_device * @@ -248,32 +218,27 @@ eisa_match_dev(e_dev, match_func) struct eisa_device *e_dev; 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; - } - - /* - * The first node in the list is the motherboard, so don't bother - * to look at it. - */ - while (e_node->next != NULL) { - char *result; - e_node = e_node->next; - if (e_node->dev.driver) { - /* Already claimed */ - continue; + 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; } - result = (*match_func)(e_node->dev.id); - if (result) { - free(e_node->dev.full_name, M_DEVBUF); - e_node->dev.full_name = result; - return (&(e_node->dev)); + + for(; e_node; e_node = e_node->next) { + char *result; + if (e_node->dev.driver) { + /* Already claimed */ + continue; + } + result = (*match_func)(e_node->dev.id); + if (result) { + free(e_node->dev.full_name, M_DEVBUF); + e_node->dev.full_name = result; + return (&(e_node->dev)); + } } - } - return NULL; + return NULL; } /* Interrupt and I/O space registration facitlities */ @@ -281,13 +246,13 @@ void eisa_reg_start(e_dev) struct eisa_device *e_dev; { - /* - * Announce the device. - */ - printf("%s%ld: <%s>", - e_dev->driver->name, - e_dev->unit, - e_dev->full_name); + /* + * Announce the device. + */ + printf("%s%ld: <%s>", + e_dev->driver->name, + e_dev->unit, + e_dev->full_name); } /* Interrupt and I/O space registration facitlities */ @@ -295,10 +260,19 @@ void eisa_reg_end(e_dev) struct eisa_device *e_dev; { - printf(" on %s%ld slot %d\n", - eisa_dev_list->dev.driver->name, /* Mainboard */ - eisa_dev_list->dev.unit, - e_dev->ioconf.slot); + /* + * The device should have called eisa_registerdev() + * during its probe. So hopefully we can use the kdc + * to weed out ISA/VL devices that use EISA id registers. + */ + if (e_dev->kdc && (e_dev->kdc->kdc_parent == &kdc_isa0)) { + printf(" on isa\n"); + } + else { + printf(" on %s0 slot %d\n", + mainboard_drv.name, + e_dev->ioconf.slot); + } } int @@ -306,8 +280,8 @@ eisa_add_intr(e_dev, irq) struct eisa_device *e_dev; int irq; { - e_dev->ioconf.irq |= 1ul << irq; - return 0; + e_dev->ioconf.irq |= 1ul << irq; + return 0; } int @@ -319,42 +293,42 @@ eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared) u_int *maskptr; int shared; { - int result; - int s; + int result; + int s; #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; + /* + * 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 - s = splhigh(); - /* - * This should really go to a routine that can optionally - * handle shared interrupts. - */ - result = register_intr(irq, /* isa irq */ - 0, /* deviced?? */ - 0, /* flags? */ - (inthand2_t*) func, /* handler */ - maskptr, /* mask pointer */ - (int)arg); /* handler arg */ - - if (result) { - printf ("eisa_reg_int: result=%d\n", result); + s = splhigh(); + /* + * This should really go to a routine that can optionally + * handle shared interrupts. + */ + result = register_intr(irq, /* isa irq */ + 0, /* deviced?? */ + 0, /* flags? */ + (inthand2_t*) func, /* handler */ + maskptr, /* mask pointer */ + (int)arg); /* handler arg */ + + if (result) { + printf ("eisa_reg_int: result=%d\n", result); + splx(s); + return (result); + }; + update_intr_masks(); splx(s); - return (result); - }; - update_intr_masks(); - splx(s); - - e_dev->ioconf.irq |= 1ul << irq; - printf(" irq %d", irq); - return (0); + + e_dev->ioconf.irq |= 1ul << irq; + printf(" irq %d", irq); + return (0); } int @@ -363,27 +337,28 @@ eisa_release_intr(e_dev, irq, func) int irq; void (*func)(void *); { - int result; - int s; - - if (!(e_dev->ioconf.irq & (1ul << irq))) { - printf("%s%ld: Attempted to release an interrupt (%d) it doesn't own\n", - e_dev->driver->name, e_dev->unit, irq); - return (-1); - } - - s = splhigh(); - INTRDIS ((1ul<<irq)); - - result = unregister_intr (irq, (inthand2_t*)func); + int result; + int s; + + if (!(e_dev->ioconf.irq & (1ul << irq))) { + printf("%s%ld: Attempted to release an interrupt (%d) " + "it doesn't own\n", e_dev->driver->name, + e_dev->unit, irq); + return (-1); + } + + s = splhigh(); + INTRDIS ((1ul<<irq)); + + result = unregister_intr (irq, (inthand2_t*)func); - if (result) - printf ("eisa_release_intr: result=%d\n", result); + if (result) + printf ("eisa_release_intr: result=%d\n", result); - update_intr_masks(); + update_intr_masks(); - splx(s); - return (result); + splx(s); + return (result); } int @@ -391,17 +366,18 @@ eisa_enable_intr(e_dev, irq) struct eisa_device *e_dev; int irq; { - int s; - - if (!(e_dev->ioconf.irq & (1ul << irq))) { - printf("%s%ld: Attempted to enable an interrupt (%d) it doesn't own\n", - e_dev->driver->name, e_dev->unit, irq); - return (-1); - } - s = splhigh(); - INTREN((1ul << irq)); - splx(s); - return 0; + int s; + + if (!(e_dev->ioconf.irq & (1ul << irq))) { + printf("%s%ld: Attempted to enable an interrupt (%d) " + "it doesn't own\n", e_dev->driver->name, + e_dev->unit, irq); + return (-1); + } + s = splhigh(); + INTREN((1ul << irq)); + splx(s); + return 0; } int @@ -410,13 +386,13 @@ eisa_add_iospace(e_dev, iobase, iosize) u_long iobase; int iosize; { - /* - * We should develop a scheme for storing the results of - * multiple calls to this function. - */ - e_dev->ioconf.iobase = iobase; - e_dev->ioconf.iosize = iosize; - return 0; + /* + * We should develop a scheme for storing the results of + * multiple calls to this function. + */ + e_dev->ioconf.iobase = iobase; + e_dev->ioconf.iosize = iosize; + return 0; } int @@ -425,25 +401,25 @@ eisa_reg_iospace(e_dev, iobase, iosize) u_long iobase; int iosize; { - /* - * We should develop a scheme for storing the results of - * multiple calls to this function. - */ + /* + * We should develop a scheme for storing the results of + * multiple calls to this function. + */ #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; + /* + * 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 - e_dev->ioconf.iobase = iobase; - e_dev->ioconf.iosize = iosize; + e_dev->ioconf.iobase = iobase; + e_dev->ioconf.iosize = iosize; - printf(" at 0x%lx-0x%lx", iobase, iobase + iosize - 1); - return (0); + printf(" at 0x%lx-0x%lx", iobase, iobase + iosize - 1); + return (0); } int @@ -452,18 +428,19 @@ eisa_registerdev(e_dev, driver, kdc_template) struct eisa_driver *driver; struct kern_devconf *kdc_template; { - e_dev->driver = driver; /* Driver now owns this device */ - e_dev->kdc = (struct kern_devconf *)malloc(sizeof(struct kern_devconf), + e_dev->driver = driver; /* Driver now owns this device */ + e_dev->kdc = (struct kern_devconf *)malloc(sizeof(struct kern_devconf), M_DEVBUF, M_NOWAIT); - if (!e_dev->kdc) { - printf("WARNING: eisa_registerdev unable to malloc! " - "Device kdc will not be registerd\n"); - return 1; - } - bcopy(kdc_template, e_dev->kdc, sizeof(*kdc_template)); - e_dev->kdc->kdc_description = e_dev->full_name; - dev_attach(e_dev->kdc); - return (0); + if (!e_dev->kdc) { + printf("WARNING: eisa_registerdev unable to malloc! " + "Device kdc will not be registerd\n"); + return 1; + } + bcopy(kdc_template, e_dev->kdc, sizeof(*kdc_template)); + e_dev->kdc->kdc_description = e_dev->full_name; + e_dev->kdc->kdc_parentdata = e_dev; + dev_attach(e_dev->kdc); + return (0); } /* @@ -471,19 +448,25 @@ eisa_registerdev(e_dev, driver, kdc_template) * hw.devconf interface. */ int -eisa_externalize(struct eisa_device *id, void *userp, size_t *maxlen) +eisa_externalize(id, userp, maxlen) + struct eisa_device *id; + void *userp; + size_t *maxlen; { - if(*maxlen < (sizeof *id)) { - return ENOMEM; - } - *maxlen -= (sizeof *id); - return (copyout(id, userp, sizeof *id)); + if (*maxlen < (sizeof *id)) { + return ENOMEM; + } + *maxlen -= (sizeof *id); + return (copyout(id, userp, sizeof *id)); } int -eisa_generic_externalize(struct proc *p, struct kern_devconf *kdc, - void *userp, size_t l) +eisa_generic_externalize(p, kdc, userp, l) + struct proc *p; + struct kern_devconf *kdc; + void *userp; + size_t l; { return eisa_externalize(kdc->kdc_eisa, userp, &l); } |