diff options
author | gibbs <gibbs@FreeBSD.org> | 1997-09-21 21:35:24 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1997-09-21 21:35:24 +0000 |
commit | 51fbeeacb49c374db82570f339949c62d1198558 (patch) | |
tree | 8338fb3c4dad4e9a1bde40a5249f7a7f410d64ba /sys/dev/eisa | |
parent | 00881143430fb92b08e80ea8c74e6b8f07b840a4 (diff) | |
download | FreeBSD-src-51fbeeacb49c374db82570f339949c62d1198558.zip FreeBSD-src-51fbeeacb49c374db82570f339949c62d1198558.tar.gz |
Add shared EISA interrupt support.
Clean up the match routines so that they return const char *
Diffstat (limited to 'sys/dev/eisa')
-rw-r--r-- | sys/dev/eisa/eisaconf.c | 171 | ||||
-rw-r--r-- | sys/dev/eisa/eisaconf.h | 20 |
2 files changed, 106 insertions, 85 deletions
diff --git a/sys/dev/eisa/eisaconf.c b/sys/dev/eisa/eisaconf.c index cf3cd3f..0899fee 100644 --- a/sys/dev/eisa/eisaconf.c +++ b/sys/dev/eisa/eisaconf.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: eisaconf.c,v 1.29 1997/08/21 07:36:43 fsmp Exp $ + * $Id: eisaconf.c,v 1.30 1997/08/21 20:33:29 bde Exp $ */ #include "opt_eisa.h" @@ -146,30 +146,15 @@ eisa_configure() 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(8*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%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->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; @@ -183,18 +168,23 @@ eisa_configure() /* 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)++; - 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) { + idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1, + M_DEVBUF, M_NOWAIT); + if (idstring == NULL) { panic("Eisa probe unable to malloc"); } - sprintf(e_dev->full_name, "%s (System Board)", id_string); - free(id_string, M_DEVBUF); + 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, @@ -254,10 +244,14 @@ eisa_configure() } else { /* Announce unattached device */ - printf("%s0:%d <%s=0x%x> unknown device\n", + printf("%s0:%d <%c%c%c%x%x=0x%x> unknown device\n", mainboard_drv.name, e_dev->ioconf.slot, - e_dev->full_name, + 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); } } @@ -266,7 +260,7 @@ eisa_configure() struct eisa_device * eisa_match_dev(e_dev, match_func) struct eisa_device *e_dev; - char* (*match_func)(eisa_id_t); + const char* (*match_func)(eisa_id_t); { struct eisa_device_node *e_node = eisa_dev_list; @@ -276,14 +270,13 @@ eisa_match_dev(e_dev, match_func) } for(; e_node; e_node = e_node->next) { - char *result; + const 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)); } @@ -378,7 +371,18 @@ eisa_add_intr(e_dev, irq) struct eisa_device *e_dev; int irq; { - e_dev->ioconf.irq |= 1ul << irq; + struct irq_node *irq_info; + void *dev_instance = (void *)-1; /* XXX use cfg->devdata */ + void *idesc; + + 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; } @@ -386,7 +390,7 @@ int eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared) struct eisa_device *e_dev; int irq; - void (*func)(void *); + void (*func)(void *); void *arg; u_int *maskptr; int shared; @@ -407,30 +411,35 @@ eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared) return 1; #endif if (reg_state.in_registration) { - s = splhigh(); /* - * This should really go to a routine that can optionally - * handle shared interrupts. + * Find the first instance of this irq that has a + * NULL idesc. */ - result = register_intr(irq, /* isa irq */ - 0, /* deviced?? */ - 0, /* flags? */ - (inthand2_t*) func, /* handler */ - maskptr, /* mask pointer */ - (int)arg); /* handler arg */ - - if (result) { - printf ("\neisa_reg_int: result=%d\n", result); - splx(s); - return (result); - }; - update_intr_masks(); - splx(s); - } - else + 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; + } - e_dev->ioconf.irq |= 1ul << irq; sprintf(string, " irq %d", irq); eisa_reg_print(e_dev, string, reg_state.num_interrupts ? &separator : NULL); @@ -444,27 +453,28 @@ eisa_release_intr(e_dev, irq, func) int irq; void (*func)(void *); { - int result; - int s; - - if (!(e_dev->ioconf.irq & (1ul << irq))) { + 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) { + if (cur_irq->idesc != NULL) + intr_destroy(cur_irq->idesc); + cur_irq = TAILQ_NEXT(cur_irq, links); + TAILQ_REMOVE(&e_dev->ioconf.irqs, cur_irq, links); + 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 (-1); } - s = splhigh(); - INTRDIS ((1ul<<irq)); - - result = unregister_intr (irq, (inthand2_t*)func); - - if (result) - printf ("eisa_release_intr: result=%d\n", result); - - update_intr_masks(); - - splx(s); return (result); } @@ -473,18 +483,19 @@ 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); + 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); } - s = splhigh(); - INTREN((1ul << irq)); - splx(s); - return 0; + return (result); } static int diff --git a/sys/dev/eisa/eisaconf.h b/sys/dev/eisa/eisaconf.h index 38cfa94..2b2ff2d 100644 --- a/sys/dev/eisa/eisaconf.h +++ b/sys/dev/eisa/eisaconf.h @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: eisaconf.h,v 1.15 1997/03/12 17:41:24 joerg Exp $ + * $Id: eisaconf.h,v 1.16 1997/03/13 18:04:05 joerg Exp $ */ #ifndef _I386_EISA_EISACONF_H_ @@ -64,11 +64,19 @@ typedef struct resvaddr { LIST_HEAD(resvlist, resvaddr); +struct irq_node { + int irq_no; + void *idesc; + TAILQ_ENTRY(irq_node) links; +}; + +TAILQ_HEAD(irqlist, irq_node); + struct eisa_ioconf { int slot; struct resvlist ioaddrs; /* list of reserved I/O ranges */ struct resvlist maddrs; /* list of reserved memory ranges */ - u_short irq; /* bitmask of interrupt */ + struct irqlist irqs; /* list of reserved irqs */ }; struct eisa_device; @@ -90,18 +98,20 @@ struct eisa_driver { struct eisa_device { eisa_id_t id; u_long unit; - char* full_name; /* for use in the probe message */ + const char* full_name; /* for use in the probe message */ struct eisa_ioconf ioconf; struct eisa_driver* driver; }; void eisa_configure __P((void)); -struct eisa_device *eisa_match_dev __P((struct eisa_device *, char * (*)(eisa_id_t))); +struct eisa_device *eisa_match_dev __P((struct eisa_device *, + const char * (*)(eisa_id_t))); void eisa_reg_start __P((struct eisa_device *)); void eisa_reg_end __P((struct eisa_device *)); int eisa_add_intr __P((struct eisa_device *, int)); -int eisa_reg_intr __P((struct eisa_device *, int, void (*)(void *), void *, u_int *, int)); +int eisa_reg_intr __P((struct eisa_device *, int, void (*)(void *), + void *, u_int *, int)); int eisa_release_intr __P((struct eisa_device *, int, void (*)(void *))); int eisa_enable_intr __P((struct eisa_device *, int)); int eisa_add_iospace __P((struct eisa_device *, u_long, u_long, int)); |