aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/eisa/eisaconf.c
diff options
context:
space:
mode:
authorJustin T. Gibbs <gibbs@FreeBSD.org>1996-01-29 03:13:23 +0000
committerJustin T. Gibbs <gibbs@FreeBSD.org>1996-01-29 03:13:23 +0000
commitb18d8f49f22d1b9dd5e2a462492473ab5fdc2d1c (patch)
tree1b6101f6ee35060aacfbf2e0aae2d6e0d2e72010 /sys/i386/eisa/eisaconf.c
parent5327d59536bfdfded3e9478aa7f1356bc3fe72c4 (diff)
downloadsrc-b18d8f49f22d1b9dd5e2a462492473ab5fdc2d1c.tar.gz
src-b18d8f49f22d1b9dd5e2a462492473ab5fdc2d1c.zip
Another pass through eisaconf. Ioaddrs and Maddrs are link lists now.
The Bt driver is the only one that actually registers multiple addresses. Probe output is formatted to 80 columns.
Notes
Notes: svn path=/head/; revision=13691
Diffstat (limited to 'sys/i386/eisa/eisaconf.c')
-rw-r--r--sys/i386/eisa/eisaconf.c342
1 files changed, 278 insertions, 64 deletions
diff --git a/sys/i386/eisa/eisaconf.c b/sys/i386/eisa/eisaconf.c
index 288c66be6612..2c583aa16b51 100644
--- a/sys/i386/eisa/eisaconf.c
+++ b/sys/i386/eisa/eisaconf.c
@@ -1,7 +1,7 @@
/*
* EISA bus probe and attach routines
*
- * Copyright (c) 1995 Justin T. Gibbs.
+ * Copyright (c) 1995, 1996 Justin T. Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -18,15 +18,15 @@
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
- * $Id: eisaconf.c,v 1.11 1995/12/10 13:33:49 phk Exp $
+ * $Id: eisaconf.c,v 1.12 1996/01/03 06:28:01 gibbs Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/devconf.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
-#include <sys/conf.h>
+#include <sys/conf.h> /* For kdc_isa */
#include <sys/malloc.h>
-#include <sys/devconf.h>
#include <i386/eisa/eisaconf.h>
@@ -77,6 +77,30 @@ static struct eisa_driver mainboard_drv = {
DATA_SET (eisadriver_set, mainboard_drv);
/*
+ * Local function declarations and static variables
+ */
+void eisa_reg_print __P((struct eisa_device *e_dev, char *string,
+ char *separator));
+static int eisa_add_resvaddr __P((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;
+
+/*
** probe for EISA devices
*/
void
@@ -112,6 +136,7 @@ eisa_configure()
}
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
@@ -131,9 +156,13 @@ eisa_configure()
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;
+
+ /* Initialize our lists of reserved addresses */
+ LIST_INIT(&(e_dev->ioconf.ioaddrs));
+ LIST_INIT(&(e_dev->ioconf.maddrs));
+
*eisa_dev_list_tail = dev_node;
eisa_dev_list_tail = &dev_node->next;
}
@@ -199,6 +228,7 @@ eisa_configure()
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.
@@ -213,20 +243,25 @@ eisa_configure()
*/
e_dev->unit = (*e_drv->unit)++;
if ((*e_drv->attach)(e_dev) < 0) {
- printf("%s0:%d <%s> attach failed\n",
+ /* 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;
e_dev->kdc->kdc_unit = e_dev->unit;
}
else {
/* Announce unattached device */
- printf("%s0:%d <%s> unknown device\n",
+ printf("%s0:%d <%s=0x%x> unknown device\n",
mainboard_drv.name,
e_dev->ioconf.slot,
- e_dev->full_name);
+ e_dev->full_name,
+ e_dev->id);
}
}
}
@@ -267,10 +302,57 @@ eisa_reg_start(e_dev)
/*
* Announce the device.
*/
- printf("%s%ld: <%s>",
- e_dev->driver->name,
- e_dev->unit,
- e_dev->full_name);
+ 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.
+ */
+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 */
@@ -278,19 +360,30 @@ void
eisa_reg_end(e_dev)
struct eisa_device *e_dev;
{
- /*
- * 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);
+ if( reg_state.in_registration )
+ {
+ /*
+ * 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.
+ */
+ char string[25];
+
+ if (e_dev->kdc && (e_dev->kdc->kdc_parent == &kdc_isa0)) {
+ sprintf(string, " on isa");
+ }
+ else {
+ sprintf(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
@@ -313,6 +406,8 @@ eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
{
int result;
int s;
+ char string[25];
+ char separator = ',';
#if NOT_YET
/*
@@ -324,28 +419,35 @@ eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
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);
+ if (reg_state.in_registration) {
+ 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 ("\neisa_reg_int: result=%d\n", result);
+ splx(s);
+ return (result);
+ };
+ update_intr_masks();
splx(s);
- return (result);
- };
- update_intr_masks();
- splx(s);
+ }
+ else
+ return EPERM;
e_dev->ioconf.irq |= 1ul << irq;
- printf(" irq %d", irq);
+ sprintf(string, " irq %d", irq);
+ eisa_reg_print(e_dev, string, reg_state.num_interrupts ?
+ &separator : NULL);
+ reg_state.num_interrupts++;
return (0);
}
@@ -398,31 +500,146 @@ eisa_enable_intr(e_dev, irq)
return 0;
}
+static int
+eisa_add_resvaddr(head, base, size, flags)
+ 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_iospace(e_dev, iobase, iosize)
+eisa_add_mspace(e_dev, mbase, msize, flags)
struct eisa_device *e_dev;
- u_long iobase;
- int iosize;
+ u_long mbase;
+ u_long msize;
+ int flags;
{
- /*
- * 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;
+ return eisa_add_resvaddr(&(e_dev->ioconf.maddrs), mbase, msize, flags);
}
int
-eisa_reg_iospace(e_dev, iobase, iosize)
+eisa_add_iospace(e_dev, iobase, iosize, flags)
struct eisa_device *e_dev;
u_long iobase;
- int iosize;
+ u_long iosize;
+ int flags;
{
- /*
- * We should develop a scheme for storing the results of
- * multiple calls to this function.
+ return eisa_add_resvaddr(&(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.
@@ -433,11 +650,8 @@ eisa_reg_iospace(e_dev, iobase, iosize)
if (haveseen_dev(dev, checkthese))
return -1;
#endif
- e_dev->ioconf.iobase = iobase;
- e_dev->ioconf.iosize = iosize;
-
- printf(" at 0x%lx-0x%lx", iobase, iobase + iosize - 1);
- return (0);
+ return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), resvaddr,
+ &(reg_state.num_ioaddrs)));
}
int