eisaconf.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 662 行 · 第 1/2 页

C
662
字号
/* * EISA bus probe and attach routines  * * Copyright (c) 1995, 1996 Justin T. Gibbs. * All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice immediately at the beginning of the file, without modification, *    this list of conditions, and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	$Id: eisaconf.c,v 1.37 1999/01/14 06:22:03 jdp Exp $ */#include "opt_eisa.h"#include <sys/param.h>#include <sys/systm.h>#include <sys/linker_set.h>#include <sys/malloc.h>#include <machine/limits.h>#include <i386/eisa/eisaconf.h>#include <sys/interrupt.h>struct eisa_device_node{	struct	eisa_device dev;	struct	eisa_device_node *next;};/*  * This should probably be a list of "struct device" once it exists. * A struct device will incorperate ioconf and driver entry point data * regardless of how its attached to the system (via unions) as well * as more generic information that all device types should support (unit * number, if its installed, etc). */static struct eisa_device_node *eisa_dev_list;static struct eisa_device_node **eisa_dev_list_tail = &eisa_dev_list;static u_long eisa_unit;static struct eisa_driver mainboard_drv = {				     "eisa",				     NULL,				     NULL,				     NULL,				     &eisa_unit				   };/* * Add the mainboard_drv to the eisa driver linkerset so that it is * defined even if no EISA drivers are linked into the kernel. */DATA_SET (eisadriver_set, mainboard_drv);/* * Local function declarations and static variables */static void eisa_reg_print __P((struct eisa_device *e_dev,				char *string, char *separator));static int eisa_add_resvaddr __P((struct eisa_device *e_dev,				  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;/* Global variable, so UserConfig can change it. */#ifndef EISA_SLOTS#define EISA_SLOTS 10   /* PCI clashes with higher ones.. fix later */#endifint num_eisa_slots = EISA_SLOTS;		/*** probe for EISA devices*/voideisa_configure(){	int i,slot;	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 < num_eisa_slots; eisaBase+=0x1000, slot++) {		int id_size = sizeof(eisa_id);		eisa_id = 0;    		for( i = 0; i < id_size; i++ ) {			outb(eisaBase,0x80 + 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;		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;	}	dev_node = eisa_dev_list;	/*	 * "Attach" the system board	 */	/* 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)++; 		idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,					  M_DEVBUF, M_NOWAIT);		if (idstring == NULL) {			panic("Eisa probe unable to malloc");		}		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,		       e_dev->unit,		       e_dev->full_name);		/* Should set the iosize, but I don't have a spec handy */		printf("Probing for devices on the EISA bus\n");		dev_node = dev_node->next;	}	if (!eisa_dev_list) {		/*		 * No devices.		 */		return;    	}	/*	 * See what devices we recognize.	 */	while((e_drv = *e_drvp++)) {		if (e_drv->probe)			(*e_drv->probe)();	}	/*	 * 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) {				/* 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;		}		else {			/* Announce unattached device */			printf("%s0:%d <%c%c%c%x%x=0x%x> unknown device\n",				mainboard_drv.name,				e_dev->ioconf.slot,				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);		}	}}struct eisa_device *eisa_match_dev(e_dev, match_func)	struct eisa_device *e_dev;	const 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)->next;	}	for(; e_node; e_node = e_node->next) {		const char *result;		if (e_node->dev.driver) {			/* Already claimed */			continue;		}		result = (*match_func)(e_node->dev.id);		if (result) {			e_node->dev.full_name = result;			return (&(e_node->dev));		}	}	return NULL;}/* Interrupt and I/O space registration facitlities */voideisa_reg_start(e_dev)	struct eisa_device *e_dev;{	/*	 * Announce the device.	 */	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. */static voideisa_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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?