⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mca.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/arch/i386/kernel/mca.c *  Written by Martin Kolinek, February 1996 * * Changes: * *	Chris Beauregard July 28th, 1996 *	- Fixed up integrated SCSI detection * *	Chris Beauregard August 3rd, 1996 *	- Made mca_info local *	- Made integrated registers accessible through standard function calls *	- Added name field *	- More sanity checking * *	Chris Beauregard August 9th, 1996 *	- Rewrote /proc/mca * *	Chris Beauregard January 7th, 1997 *	- Added basic NMI-processing *	- Added more information to mca_info structure * *	David Weinehall October 12th, 1998 *	- Made a lot of cleaning up in the source *	- Added use of save_flags / restore_flags *	- Added the 'driver_loaded' flag in MCA_adapter *	- Added an alternative implemention of ZP Gu's mca_find_unused_adapter * *	David Weinehall March 24th, 1999 *	- Fixed the output of 'Driver Installed' in /proc/mca/pos *	- Made the Integrated Video & SCSI show up even if they have id 0000 * *	Alexander Viro November 9th, 1999 *	- Switched to regular procfs methods * *	Alfred Arnold & David Weinehall August 23rd, 2000 *	- Added support for Planar POS-registers */#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/mca.h>#include <asm/system.h>#include <asm/io.h>#include <linux/proc_fs.h>#include <linux/mman.h>#include <linux/config.h>#include <linux/mm.h>#include <linux/pagemap.h>#include <linux/ioport.h>#include <asm/uaccess.h>#include <linux/init.h>/* This structure holds MCA information. Each (plug-in) adapter has * eight POS registers. Then the machine may have integrated video and * SCSI subsystems, which also have eight POS registers. * Finally, the motherboard (planar) has got POS-registers. * Other miscellaneous information follows. */typedef enum {	MCA_ADAPTER_NORMAL = 0,	MCA_ADAPTER_NONE = 1,	MCA_ADAPTER_DISABLED = 2,	MCA_ADAPTER_ERROR = 3} MCA_AdapterStatus;struct MCA_adapter {	MCA_AdapterStatus status;	/* is there a valid adapter? */	int id;				/* adapter id value */	unsigned char pos[8];		/* POS registers */	int driver_loaded;		/* is there a driver installed? */					/* 0 - No, 1 - Yes */	char name[48];			/* adapter-name provided by driver */	char procname[8];		/* name of /proc/mca file */	MCA_ProcFn procfn;		/* /proc info callback */	void* dev;			/* device/context info for callback */};struct MCA_info {	/* one for each of the 8 possible slots, plus one for integrated SCSI	 * and one for integrated video.	 */	struct MCA_adapter slot[MCA_NUMADAPTERS];	/* two potential addresses for integrated SCSI adapter - this will	 * track which one we think it is.	 */	unsigned char which_scsi;};/* The mca_info structure pointer. If MCA bus is present, the function * mca_probe() is invoked. The function puts motherboard, then all * adapters into setup mode, allocates and fills an MCA_info structure, * and points this pointer to the structure. Otherwise the pointer * is set to zero. */static struct MCA_info* mca_info = NULL;/* MCA registers */#define MCA_MOTHERBOARD_SETUP_REG	0x94#define MCA_ADAPTER_SETUP_REG		0x96#define MCA_POS_REG(n)			(0x100+(n))#define MCA_ENABLED	0x01	/* POS 2, set if adapter enabled *//*--------------------------------------------------------------------*/#ifdef CONFIG_PROC_FSstatic void mca_do_proc_init(void);#endif/*--------------------------------------------------------------------*//* Build the status info for the adapter */static void mca_configure_adapter_status(int slot) {	mca_info->slot[slot].status = MCA_ADAPTER_NONE;	mca_info->slot[slot].id = mca_info->slot[slot].pos[0]		+ (mca_info->slot[slot].pos[1] << 8);	if(!mca_info->slot[slot].id && slot < MCA_MAX_SLOT_NR) {		/* id = 0x0000 usually indicates hardware failure,		 * however, ZP Gu (zpg@castle.net> reports that his 9556		 * has 0x0000 as id and everything still works. There		 * also seem to be an adapter with id = 0x0000; the		 * NCR Parallel Bus Memory Card. Until this is confirmed,		 * however, this code will stay.		 */		mca_info->slot[slot].status = MCA_ADAPTER_ERROR;		return;	} else if(mca_info->slot[slot].id != 0xffff) {		/* 0xffff usually indicates that there's no adapter,		 * however, some integrated adapters may have 0xffff as		 * their id and still be valid. Examples are on-board		 * VGA of the 55sx, the integrated SCSI of the 56 & 57,		 * and possibly also the 95 ULTIMEDIA.		 */		mca_info->slot[slot].status = MCA_ADAPTER_NORMAL;	}	if((mca_info->slot[slot].id == 0xffff ||	   mca_info->slot[slot].id == 0x0000) && slot >= MCA_MAX_SLOT_NR) {		int j;		for(j = 2; j < 8; j++) {			if(mca_info->slot[slot].pos[j] != 0xff) {				mca_info->slot[slot].status = MCA_ADAPTER_NORMAL;				break;			}		}	}	if(!(mca_info->slot[slot].pos[2] & MCA_ENABLED)) {		/* enabled bit is in POS 2 */		mca_info->slot[slot].status = MCA_ADAPTER_DISABLED;	}} /* mca_configure_adapter_status *//*--------------------------------------------------------------------*/struct resource mca_standard_resources[] = {	{ "system control port B (MCA)", 0x60, 0x60 },	{ "arbitration (MCA)", 0x90, 0x90 },	{ "card Select Feedback (MCA)", 0x91, 0x91 },	{ "system Control port A (MCA)", 0x92, 0x92 },	{ "system board setup (MCA)", 0x94, 0x94 },	{ "POS (MCA)", 0x96, 0x97 },	{ "POS (MCA)", 0x100, 0x107 }};#define MCA_STANDARD_RESOURCES	(sizeof(mca_standard_resources)/sizeof(struct resource))void __init mca_init(void){	unsigned int i, j;	unsigned long flags;	/* WARNING: Be careful when making changes here. Putting an adapter	 * and the motherboard simultaneously into setup mode may result in	 * damage to chips (according to The Indispensible PC Hardware Book	 * by Hans-Peter Messmer). Also, we disable system interrupts (so	 * that we are not disturbed in the middle of this).	 */	/* Make sure the MCA bus is present */	if(!MCA_bus)		return;	printk("Micro Channel bus detected.\n");	/* Allocate MCA_info structure (at address divisible by 8) */	mca_info = (struct MCA_info *)kmalloc(sizeof(struct MCA_info), GFP_KERNEL);	if(mca_info == NULL) {		printk("Failed to allocate memory for mca_info!");		return;	}	memset(mca_info, 0, sizeof(struct MCA_info));	save_flags(flags);	cli();	/* Make sure adapter setup is off */	outb_p(0, MCA_ADAPTER_SETUP_REG);	/* Read motherboard POS registers */	outb_p(0x7f, MCA_MOTHERBOARD_SETUP_REG);	mca_info->slot[MCA_MOTHERBOARD].name[0] = 0;	for(j=0; j<8; j++) {		mca_info->slot[MCA_MOTHERBOARD].pos[j] = inb_p(MCA_POS_REG(j));	}	mca_configure_adapter_status(MCA_MOTHERBOARD);	/* Put motherboard into video setup mode, read integrated video	 * POS registers, and turn motherboard setup off.	 */	outb_p(0xdf, MCA_MOTHERBOARD_SETUP_REG);	mca_info->slot[MCA_INTEGVIDEO].name[0] = 0;	for(j=0; j<8; j++) {		mca_info->slot[MCA_INTEGVIDEO].pos[j] = inb_p(MCA_POS_REG(j));	}	mca_configure_adapter_status(MCA_INTEGVIDEO);	/* Put motherboard into scsi setup mode, read integrated scsi	 * POS registers, and turn motherboard setup off.	 *	 * It seems there are two possible SCSI registers. Martin says that	 * for the 56,57, 0xf7 is the one, but fails on the 76.	 * Alfredo (apena@vnet.ibm.com) says	 * 0xfd works on his machine. We'll try both of them. I figure it's	 * a good bet that only one could be valid at a time. This could	 * screw up though if one is used for something else on the other	 * machine.	 */	outb_p(0xf7, MCA_MOTHERBOARD_SETUP_REG);	mca_info->slot[MCA_INTEGSCSI].name[0] = 0;	for(j=0; j<8; j++) {		if((mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j))) != 0xff)		{			/* 0xff all across means no device. 0x00 means			 * something's broken, but a device is probably there.			 * However, if you get 0x00 from a motherboard			 * register it won't matter what we find.  For the			 * record, on the 57SLC, the integrated SCSI			 * adapter has 0xffff for the adapter ID, but			 * nonzero for other registers.			 */			mca_info->which_scsi = 0xf7;		}	}	if(!mca_info->which_scsi) {		/* Didn't find it at 0xf7, try somewhere else... */		mca_info->which_scsi = 0xfd;		outb_p(0xfd, MCA_MOTHERBOARD_SETUP_REG);		for(j=0; j<8; j++)			mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j));	}	mca_configure_adapter_status(MCA_INTEGSCSI);	/* Turn off motherboard setup */	outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);	/* Now loop over MCA slots: put each adapter into setup mode, and	 * read its POS registers. Then put adapter setup off.	 */	for(i=0; i<MCA_MAX_SLOT_NR; i++) {		outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);		for(j=0; j<8; j++) {			mca_info->slot[i].pos[j]=inb_p(MCA_POS_REG(j));		}		mca_info->slot[i].name[0] = 0;		mca_info->slot[i].driver_loaded = 0;		mca_configure_adapter_status(i);	}	outb_p(0, MCA_ADAPTER_SETUP_REG);	/* Enable interrupts and return memory start */	restore_flags(flags);	for (i = 0; i < MCA_STANDARD_RESOURCES; i++)		request_resource(&ioport_resource, mca_standard_resources + i);#ifdef CONFIG_PROC_FS	mca_do_proc_init();#endif}/*--------------------------------------------------------------------*/static void mca_handle_nmi_slot(int slot, int check_flag){	if(slot < MCA_MAX_SLOT_NR) {		printk("NMI: caused by MCA adapter in slot %d (%s)\n", slot+1,			mca_info->slot[slot].name);	} else if(slot == MCA_INTEGSCSI) {		printk("NMI: caused by MCA integrated SCSI adapter (%s)\n",			mca_info->slot[slot].name);	} else if(slot == MCA_INTEGVIDEO) {		printk("NMI: caused by MCA integrated video adapter (%s)\n",			mca_info->slot[slot].name);	} else if(slot == MCA_MOTHERBOARD) {		printk("NMI: caused by motherboard (%s)\n",			mca_info->slot[slot].name);	}	/* More info available in POS 6 and 7? */	if(check_flag) {		unsigned char pos6, pos7;		pos6 = mca_read_pos(slot, 6);		pos7 = mca_read_pos(slot, 7);		printk("NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7);	}} /* mca_handle_nmi_slot *//*--------------------------------------------------------------------*/void mca_handle_nmi(void){	int i;	unsigned char pos5;	/* First try - scan the various adapters and see if a specific	 * adapter was responsible for the error.	 */	for(i = 0; i < MCA_NUMADAPTERS; i++) {	/* Bit 7 of POS 5 is reset when this adapter has a hardware	 * error. Bit 7 it reset if there's error information	 * available in POS 6 and 7.	 */	pos5 = mca_read_pos(i, 5);	if(!(pos5 & 0x80)) {			mca_handle_nmi_slot(i, !(pos5 & 0x40));			return;		}	}	/* If I recall correctly, there's a whole bunch of other things that	 * we can do to check for NMI problems, but that's all I know about	 * at the moment.	 */	printk("NMI generated from unknown source!\n");} /* mca_handle_nmi *//*--------------------------------------------------------------------*//** *	mca_find_adapter - scan for adapters *	@id:	MCA identification to search for *	@start:	starting slot * *	Search the MCA configuration for adapters matching the 16bit *	ID given. The first time it should be called with start as zero *	and then further calls made passing the return value of the *	previous call until %MCA_NOTFOUND is returned. * *	Disabled adapters are not reported. */int mca_find_adapter(int id, int start){	if(mca_info == NULL || id == 0xffff) {		return MCA_NOTFOUND;	}	for(; start >= 0 && start < MCA_NUMADAPTERS; start++) {		/* Not sure about this. There's no point in returning		 * adapters that aren't enabled, since they can't actually		 * be used. However, they might be needed for statistical		 * purposes or something... But if that is the case, the		 * user is free to write a routine that manually iterates		 * through the adapters.		 */		if(mca_info->slot[start].status == MCA_ADAPTER_DISABLED) {			continue;		}		if(id == mca_info->slot[start].id) {			return start;		}	}	return MCA_NOTFOUND;} /* mca_find_adapter() */EXPORT_SYMBOL(mca_find_adapter);/*--------------------------------------------------------------------*//** *	mca_find_unused_adapter - scan for unused adapters *	@id:	MCA identification to search for *	@start:	starting slot * *	Search the MCA configuration for adapters matching the 16bit *	ID given. The first time it should be called with start as zero *	and then further calls made passing the return value of the *	previous call until %MCA_NOTFOUND is returned. * *	Adapters that have been claimed by drivers and those that *	are disabled are not reported. This function thus allows a driver *	to scan for further cards when some may already be driven. */int mca_find_unused_adapter(int id, int start){	if(mca_info == NULL || id == 0xffff) {		return MCA_NOTFOUND;	}	for(; start >= 0 && start < MCA_NUMADAPTERS; start++) {		/* not sure about this. There's no point in returning		 * adapters that aren't enabled, since they can't actually		 * be used. However, they might be needed for statistical		 * purposes or something... But if that is the case, the		 * user is free to write a routine that manually iterates		 * through the adapters.		 */		if(mca_info->slot[start].status == MCA_ADAPTER_DISABLED ||		   mca_info->slot[start].driver_loaded) {			continue;		}		if(id == mca_info->slot[start].id) {			return start;		}	}	return MCA_NOTFOUND;} /* mca_find_unused_adapter() */EXPORT_SYMBOL(mca_find_unused_adapter);/*--------------------------------------------------------------------*//** *	mca_read_stored_pos - read POS register from boot data *	@slot: slot number to read from *	@reg:  register to read from * *	Fetch a POS value that was stored at boot time by the kernel *	when it scanned the MCA space. The register value is returned. *	Missing or invalid registers report 0. */unsigned char mca_read_stored_pos(int slot, int reg){	if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0;	if(reg < 0 || reg >= 8) return 0;	return mca_info->slot[slot].pos[reg];} /* mca_read_stored_pos() */

⌨️ 快捷键说明

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