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

📄 bios32.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * bios32.c - BIOS32, PCI BIOS functions. * * $Id: bios32.c,v 1.1 1999/04/26 05:50:57 tb Exp $ * * Sponsored by *	iX Multiuser Multitasking Magazine *	Hannover, Germany *	hm@ix.de * * Copyright 1993, 1994 Drew Eckhardt *      Visionary Computing *      (Unix and Linux consulting and custom programming) *      Drew@Colorado.EDU *      +1 (303) 786-7975 * * For more information, please consult * * PCI BIOS Specification Revision * PCI Local Bus Specification * PCI System Design Guide * * PCI Special Interest Group * M/S HF3-15A * 5200 N.E. Elam Young Parkway * Hillsboro, Oregon 97124-6497 * +1 (503) 696-2000 * +1 (800) 433-5177 * * Manuals are $25 each or $50 for all three, plus $7 shipping * within the United States, $35 abroad. * * * CHANGELOG : * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION *	Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard. * * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic *     Potter, potter@cao-vlsi.ibp.fr * * Jan 10, 1995 : Modified to store the information about configured pci *      devices into a list, which can be accessed via /proc/pci by *      Curtis Varner, cvarner@cs.ucr.edu * * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter. *	Alpha version. Intel & UMC chipset support only. * * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code *	moved to drivers/pci/pci.c. * * Dec 7, 1996  : Added support for direct configuration access of boards *      with Intel compatible access schemes (tsbogend@alpha.franken.de) * * Feb 3, 1997  : Set internal functions to static, save/restore flags *	avoid dead locks reading broken PCI BIOS, werner@suse.de  * * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS *	(mj@atrey.karlin.mff.cuni.cz) * * May 7,  1997 : Added some missing cli()'s. [mj] *  * Jun 20, 1997 : Corrected problems in "conf1" type accesses. *      (paubert@iram.es) */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/bios32.h>#include <linux/pci.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/io.h>#define PCIBIOS_PCI_FUNCTION_ID 	0xb1XX#define PCIBIOS_PCI_BIOS_PRESENT 	0xb101#define PCIBIOS_FIND_PCI_DEVICE		0xb102#define PCIBIOS_FIND_PCI_CLASS_CODE	0xb103#define PCIBIOS_GENERATE_SPECIAL_CYCLE	0xb106#define PCIBIOS_READ_CONFIG_BYTE	0xb108#define PCIBIOS_READ_CONFIG_WORD	0xb109#define PCIBIOS_READ_CONFIG_DWORD	0xb10a#define PCIBIOS_WRITE_CONFIG_BYTE	0xb10b#define PCIBIOS_WRITE_CONFIG_WORD	0xb10c#define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d/* BIOS32 signature: "_32_" */#define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))/* PCI signature: "PCI " */#define PCI_SIGNATURE		(('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))/* PCI service signature: "$PCI" */#define PCI_SERVICE		(('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))/* * This is the standard structure used to identify the entry point * to the BIOS32 Service Directory, as documented in * 	Standard BIOS 32-bit Service Directory Proposal * 	Revision 0.4 May 24, 1993 * 	Phoenix Technologies Ltd. *	Norwood, MA * and the PCI BIOS specification. */union bios32 {	struct {		unsigned long signature;	/* _32_ */		unsigned long entry;		/* 32 bit physical address */		unsigned char revision;		/* Revision level, 0 */		unsigned char length;		/* Length in paragraphs should be 01 */		unsigned char checksum;		/* All bytes must add up to zero */		unsigned char reserved[5]; 	/* Must be zero */	} fields;	char chars[16];};#ifdef CONFIG_PCI/* * Physical address of the service directory.  I don't know if we're * allowed to have more than one of these or not, so just in case * we'll make pcibios_present() take a memory start parameter and store * the array there. */static unsigned long bios32_entry = 0;static struct {	unsigned long address;	unsigned short segment;} bios32_indirect = { 0, KERNEL_CS };/* * function table for accessing PCI configuration space */struct pci_access {    int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);    int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);    int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);    int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);    int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);    int (*write_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char);    int (*write_config_word)(unsigned char, unsigned char, unsigned char, unsigned short);    int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);};/* * pointer to selected PCI access function table */static struct pci_access *access_pci = NULL;/* * Returns the entry point for the given service, NULL on error */static unsigned long bios32_service(unsigned long service){	unsigned char return_code;	/* %al */	unsigned long address;		/* %ebx */	unsigned long length;		/* %ecx */	unsigned long entry;		/* %edx */	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%edi)"		: "=a" (return_code),		  "=b" (address),		  "=c" (length),		  "=d" (entry)		: "0" (service),		  "1" (0),		  "D" (&bios32_indirect));	restore_flags(flags);	switch (return_code) {		case 0:			return address + entry;		case 0x80:	/* Not present */			printk("bios32_service(0x%lx) : not present\n", service);			return 0;		default: /* Shouldn't happen */			printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n",				service, return_code);			return 0;	}}static long pcibios_entry = 0;static struct {	unsigned long address;	unsigned short segment;} pci_indirect = { 0, KERNEL_CS };static int check_pcibios(void){	unsigned long signature;	unsigned char present_status;	unsigned char major_revision;	unsigned char minor_revision;	unsigned long flags;	int pack;	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {		pci_indirect.address = pcibios_entry;		save_flags(flags); cli();		__asm__("lcall (%%edi)\n\t"			"jc 1f\n\t"			"xor %%ah, %%ah\n"			"1:\tshl $8, %%eax\n\t"			"movw %%bx, %%ax"			: "=d" (signature),			  "=a" (pack)			: "1" (PCIBIOS_PCI_BIOS_PRESENT),			  "D" (&pci_indirect)			: "bx", "cx");		restore_flags(flags);		present_status = (pack >> 16) & 0xff;		major_revision = (pack >> 8) & 0xff;		minor_revision = pack & 0xff;		if (present_status || (signature != PCI_SIGNATURE)) {			printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"				"	but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"				"	and signature of 0x%08lx (%c%c%c%c).  mail drew@Colorado.EDU\n",				(signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",				present_status, signature,				(char) (signature >>  0), (char) (signature >>  8),				(char) (signature >> 16), (char) (signature >> 24));			if (signature != PCI_SIGNATURE)				pcibios_entry = 0;		}		if (pcibios_entry) {			printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",				major_revision, minor_revision, pcibios_entry);			return 1;		}	}	return 0;}static int pci_bios_find_class (unsigned int class_code, unsigned short index,	unsigned char *bus, unsigned char *device_fn){	unsigned long bx;	unsigned long ret;	unsigned long flags;	save_flags(flags); cli();	__asm__ ("lcall (%%edi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=b" (bx),		  "=a" (ret)		: "1" (PCIBIOS_FIND_PCI_CLASS_CODE),		  "c" (class_code),		  "S" ((int) index),		  "D" (&pci_indirect));	restore_flags(flags);	*bus = (bx >> 8) & 0xff;	*device_fn = bx & 0xff;	return (int) (ret & 0xff00) >> 8;}static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,	unsigned short index, unsigned char *bus, unsigned char *device_fn){	unsigned short bx;	unsigned short ret;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%edi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=b" (bx),		  "=a" (ret)		: "1" (PCIBIOS_FIND_PCI_DEVICE),		  "c" (device_id),		  "d" (vendor),		  "S" ((int) index),		  "D" (&pci_indirect));	restore_flags(flags);	*bus = (bx >> 8) & 0xff;	*device_fn = bx & 0xff;	return (int) (ret & 0xff00) >> 8;}static int pci_bios_read_config_byte(unsigned char bus,	unsigned char device_fn, unsigned char where, unsigned char *value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%esi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=c" (*value),		  "=a" (ret)		: "1" (PCIBIOS_READ_CONFIG_BYTE),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}static int pci_bios_read_config_word (unsigned char bus,	unsigned char device_fn, unsigned char where, unsigned short *value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%esi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=c" (*value),		  "=a" (ret)		: "1" (PCIBIOS_READ_CONFIG_WORD),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}static int pci_bios_read_config_dword (unsigned char bus,	unsigned char device_fn, unsigned char where, unsigned int *value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%esi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=c" (*value),		  "=a" (ret)		: "1" (PCIBIOS_READ_CONFIG_DWORD),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}static int pci_bios_write_config_byte (unsigned char bus,	unsigned char device_fn, unsigned char where, unsigned char value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%esi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=a" (ret)		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),		  "c" (value),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}static int pci_bios_write_config_word (unsigned char bus,	unsigned char device_fn, unsigned char where, unsigned short value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%esi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=a" (ret)		: "0" (PCIBIOS_WRITE_CONFIG_WORD),		  "c" (value),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}static int pci_bios_write_config_dword (unsigned char bus,	unsigned char device_fn, unsigned char where, unsigned int value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__("lcall (%%esi)\n\t"		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=a" (ret)		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),		  "c" (value),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}/* * function table for BIOS32 access */static struct pci_access pci_bios_access = {      pci_bios_find_device,      pci_bios_find_class,      pci_bios_read_config_byte,      pci_bios_read_config_word,      pci_bios_read_config_dword,      pci_bios_write_config_byte,      pci_bios_write_config_word,      pci_bios_write_config_dword};/* * Given the vendor and device ids, find the n'th instance of that device * in the system.   */static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,			   unsigned short index, unsigned char *bus,			   unsigned char *devfn){    unsigned int curr = 0;    struct pci_dev *dev;    for (dev = pci_devices; dev; dev = dev->next) {

⌨️ 快捷键说明

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