1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-13 10:02:38 +00:00

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.
This commit is contained in:
Justin T. Gibbs 1995-11-09 07:14:11 +00:00
parent 4652247a48
commit 932c2f65d3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=12157
3 changed files with 564 additions and 594 deletions

View File

@ -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/types.h"
#include "i386/isa/icu.h" /* Hmmm. Interrupt stuff? */
#include <sys/devconf.h>
#include "i386/isa/icu.h" /* Hmmm. Interrupt stuff? */
#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;
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;
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;
}
e_drvp = (struct eisa_driver**)eisadriver_set.ls_items;
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 */
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 */
/* 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;
}
bzero(dev_node, sizeof(*dev_node));
e_dev = &(dev_node->dev);
e_dev->id = eisa_id;
dev_node = eisa_dev_list;
/*
* 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.
* "Attach" the system board
*/
e_dev->full_name = (char *)malloc(14*sizeof(char), M_DEVBUF, M_NOWAIT);
if (!e_dev->full_name) {
panic("Eisa probe unable to malloc");
/* 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;
}
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");
}
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 */
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");
}
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)();
}
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;
/*
* 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);
}
}
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);
}
}
}
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;
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;
}
if (e_dev) {
/* Start our search from the last successful match */
e_node = ((struct eisa_device_node *)e_dev)->next;
}
/*
* 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;
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));
}
}
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 */
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 (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);
}
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));
s = splhigh();
INTRDIS ((1ul<<irq));
result = unregister_intr (irq, (inthand2_t*)func);
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;
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;
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);
}

View File

@ -19,7 +19,7 @@
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
* $Id: aic7770.c,v 1.16 1995/09/05 23:39:31 gibbs Exp $
* $Id: aic7770.c,v 1.17 1995/11/05 04:42:47 gibbs Exp $
*/
#include "eisa.h"
@ -128,11 +128,15 @@ aic7770probe(void)
printf("aic7770 at slot %d: illegal "
"irq setting %d\n", e_dev->ioconf.slot,
intdef);
DELAY(10000000);
continue;
}
eisa_add_intr(e_dev, irq);
eisa_registerdev(e_dev, &ahc_eisa_driver, &kdc_aic7770);
if(e_dev->id == EISA_DEVICE_ID_ADAPTEC_284xB
|| e_dev->id == EISA_DEVICE_ID_ADAPTEC_284x) {
/* Our real parent is the isa bus. Say so */
e_dev->kdc->kdc_parent = &kdc_isa0;
}
count++;
}
return count;

View File

@ -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/types.h"
#include "i386/isa/icu.h" /* Hmmm. Interrupt stuff? */
#include <sys/devconf.h>
#include "i386/isa/icu.h" /* Hmmm. Interrupt stuff? */
#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;
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;
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;
}
e_drvp = (struct eisa_driver**)eisadriver_set.ls_items;
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 */
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 */
/* 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;
}
bzero(dev_node, sizeof(*dev_node));
e_dev = &(dev_node->dev);
e_dev->id = eisa_id;
dev_node = eisa_dev_list;
/*
* 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.
* "Attach" the system board
*/
e_dev->full_name = (char *)malloc(14*sizeof(char), M_DEVBUF, M_NOWAIT);
if (!e_dev->full_name) {
panic("Eisa probe unable to malloc");
/* 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;
}
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");
}
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 */
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");
}
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)();
}
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;
/*
* 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);
}
}
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);
}
}
}
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;
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;
}
if (e_dev) {
/* Start our search from the last successful match */
e_node = ((struct eisa_device_node *)e_dev)->next;
}
/*
* 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;
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));
}
}
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 */
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 (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);
}
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));
s = splhigh();
INTRDIS ((1ul<<irq));
result = unregister_intr (irq, (inthand2_t*)func);
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;
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;
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);
}