summaryrefslogtreecommitdiff
path: root/sys/dev/eisa
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/dev/eisa
parent5327d59536bfdfded3e9478aa7f1356bc3fe72c4 (diff)
Notes
Diffstat (limited to 'sys/dev/eisa')
-rw-r--r--sys/dev/eisa/eisaconf.c342
-rw-r--r--sys/dev/eisa/eisaconf.h37
2 files changed, 305 insertions, 74 deletions
diff --git a/sys/dev/eisa/eisaconf.c b/sys/dev/eisa/eisaconf.c
index 288c66be6612b..2c583aa16b516 100644
--- a/sys/dev/eisa/eisaconf.c
+++ b/sys/dev/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
diff --git a/sys/dev/eisa/eisaconf.h b/sys/dev/eisa/eisaconf.h
index 93cecf3da7722..181c7688fb5dd 100644
--- a/sys/dev/eisa/eisaconf.h
+++ b/sys/dev/eisa/eisaconf.h
@@ -18,13 +18,16 @@
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
- * $Id: eisaconf.h,v 1.5 1995/11/20 12:41:13 phk Exp $
+ * $Id: eisaconf.h,v 1.6 1995/11/21 12:52:49 bde Exp $
*/
#ifndef _I386_EISA_EISACONF_H_
#define _I386_EISA_EISACONF_H_ 1
+#include <sys/queue.h>
+
#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
+#define EISA_SLOT_SIZE 0x1000
#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
#define EISA_MFCTR_CHAR1(ID) (char)(((ID>>21) & 0x1F) | '@') /* Bits 21-25 */
@@ -35,15 +38,27 @@
extern struct linker_set eisadriver_set;
-typedef u_long eisa_id_t; /* Should use u_int32? */
+typedef u_int32_t eisa_id_t;
+
+typedef struct resvaddr {
+ u_long addr; /* start address */
+ u_long size; /* size of reserved area */
+ int flags;
+#define RESVADDR_NONE 0x00
+#define RESVADDR_BITMASK 0x01 /* size is a mask of reserved
+ * bits at addr
+ */
+#define RESVADDR_RELOCATABLE 0x02
+ LIST_ENTRY(resvaddr) links; /* List links */
+} resvaddr_t;
+
+LIST_HEAD(resvlist, resvaddr);
struct eisa_ioconf {
- int slot;
- u_long iobase; /* base i/o address */
- int iosize; /* size of i/o space */
- u_short irq; /* interrupt request */
- caddr_t maddr; /* physical i/o memory address on bus (if any)*/
- int msize; /* size of i/o memory */
+ 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 kern_devconf;
@@ -81,8 +96,10 @@ 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_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, int));
-int eisa_reg_iospace __P((struct eisa_device *, u_long, int));
+int eisa_add_iospace __P((struct eisa_device *, u_long, u_long, int));
+int eisa_reg_iospace __P((struct eisa_device *, resvaddr_t *));
+int eisa_add_mspace __P((struct eisa_device *, u_long, u_long, int));
+int eisa_reg_mspace __P((struct eisa_device *, resvaddr_t *));
int eisa_registerdev __P((struct eisa_device *, struct eisa_driver *, struct kern_devconf *));