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

📄 pcilib.c

📁 BIOS emulator and interface to Realmode X86 Emulator Library Can emulate a PCI Graphic Controller V
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************					SciTech OS Portability Manager Library**  ========================================================================**    The contents of this file are subject to the SciTech MGL Public*    License Version 1.0 (the "License"); you may not use this file*    except in compliance with the License. You may obtain a copy of*    the License at http://www.scitechsoft.com/mgl-license.txt**    Software distributed under the License is distributed on an*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*    implied. See the License for the specific language governing*    rights and limitations under the License.**    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.**    The Initial Developer of the Original Code is SciTech Software, Inc.*    All Rights Reserved.**  ========================================================================** Language:		ANSI C* Environment:	Any** Description:  Module for interfacing to the PCI bus and configuration*				space registers.*****************************************************************************/#include "pmapi.h"#include "pcilib.h"#ifndef	__WIN32_VXD__#include <string.h>#endif/*---------------------- Macros and type definitions ----------------------*/#pragma pack(1)/* Length of the memory mapping for the PCI BIOS */#define	BIOS_LIMIT			(128 * 1024L - 1)/* Macros for accessing the PCI BIOS functions from 32-bit protected mode */#define BIOS32_SIGNATURE    (((ulong)'_' << 0) + ((ulong)'3' << 8) + ((ulong)'2' << 16) + ((ulong)'_' << 24))#define PCI_SIGNATURE       (((ulong)'P' << 0) + ((ulong)'C' << 8) + ((ulong)'I' << 16) + ((ulong)' ' << 24))#define PCI_SERVICE       	(((ulong)'$' << 0) + ((ulong)'P' << 8) + ((ulong)'C' << 16) + ((ulong)'I' << 24))#define	PCI_BIOS_PRESENT	0xB101#define	FIND_PCI_DEVICE		0xB102#define	FIND_PCI_CLASS		0xB103#define	GENERATE_SPECIAL	0xB106#define	READ_CONFIG_BYTE	0xB108#define	READ_CONFIG_WORD	0xB109#define	READ_CONFIG_DWORD	0xB10A#define	WRITE_CONFIG_BYTE	0xB10B#define	WRITE_CONFIG_WORD	0xB10C#define	WRITE_CONFIG_DWORD	0xB10D#define	GET_IRQ_ROUTING_OPT	0xB10E#define	SET_PCI_IRQ			0xB10F/* This is the standard structure used to identify the entry point to the * BIOS32 Service Directory, as documented in PCI 2.1 BIOS Specicition. */typedef union {	struct {		ulong signature;        /* _32_ 								*/		ulong entry;            /* 32 bit physical address 				*/		uchar revision;         /* Revision level, 0 					*/		uchar length;           /* Length in paragraphs should be 01 	*/		uchar checksum;         /* All bytes must add up to zero 		*/		uchar reserved[5];      /* Must be zero 						*/		} fields;	char chars[16];	} PCI_bios32;/* Structure for a far pointer to call the PCI BIOS services with */typedef struct {	ulong	address;	ushort	segment;	} PCIBIOS_entry;/* Macros to copy a structure that includes dwSize members */#define	COPY_STRUCTURE(d,s)	memcpy(d,s,MIN((s)->dwSize,(d)->dwSize))#pragma pack()/*--------------------------- Global variables ----------------------------*/static uchar 			*BIOSImage = NULL;	/* BIOS image mapping 		*/static PCIBIOS_entry	PCIEntry;			/* PCI services entry point	*/static ulong			PCIPhysEntry = 0;	/* Physical address			*//*----------------------------- Implementation ----------------------------*//* External assembler helper functions */uchar 	_ASMAPI _BIOS32_service(ulong service,ulong function,ulong *physBase,ulong *length,ulong *serviceOffset,PCIBIOS_entry entry);ushort	_ASMAPI _PCIBIOS_isPresent(ulong i_eax,ulong *o_edx,ushort *o_ax,uchar *o_cl,PCIBIOS_entry entry);ulong 	_ASMAPI _PCIBIOS_service(ulong r_eax,ulong r_ebx,ulong r_edi,ulong r_ecx,PCIBIOS_entry entry);int		_ASMAPI _PCIBIOS_getRouting(PCIRoutingOptionsBuffer *buf,PCIBIOS_entry entry);ibool	_ASMAPI _PCIBIOS_setIRQ(int busDev,int intPin,int IRQ,PCIBIOS_entry entry);ulong 	_ASMAPI _PCIBIOS_specialCycle(int bus,ulong data,PCIBIOS_entry entry);ushort 	_ASMAPI _PCI_getCS(void);/****************************************************************************REMARKS:This functions returns the physical address of the PCI BIOS entry point.****************************************************************************/ulong _ASMAPI PCIBIOS_getEntry(void){ return PCIPhysEntry; }/****************************************************************************PARAMETERS:hwType	- Place to store the PCI hardware access mechanism flagslastBus	- Place to store the index of the last PCI bus in the systemRETURNS:Version number of the PCI BIOS found.REMARKS:This function determines if the PCI BIOS is present in the system, and ifso returns the information returned by the PCI BIOS detect function.****************************************************************************/static int PCIBIOS_detect(	uchar *hwType,	uchar *lastBus){	ulong	signature;	ushort	stat,version;#ifndef	__16BIT__	PCIBIOS_entry	BIOSEntry = {0};	uchar			*BIOSEnd;	PCI_bios32		*BIOSDir;	ulong			physBase,length,offset;	/* First scan the memory from 0xE0000 to 0xFFFFF looking for the	 * BIOS32 service directory, so we can determine if we can call it	 * from 32-bit protected mode.	 */	if (!BIOSImage) {		BIOSImage = PM_mapPhysicalAddr(0xE0000,BIOS_LIMIT,false);		if (!BIOSImage)			return 0;		BIOSEnd = BIOSImage + 0x20000;		for (BIOSDir = (PCI_bios32*)BIOSImage; BIOSDir < (PCI_bios32*)BIOSEnd; BIOSDir++) {			uchar 	sum;			int 	i,length;			if (BIOSDir->fields.signature != BIOS32_SIGNATURE)				continue;			length = BIOSDir->fields.length * 16;			if (!length)				continue;			for (sum = i = 0; i < length ; i++)				sum += BIOSDir->chars[i];			if (sum != 0)				continue;			BIOSEntry.address = (ulong)BIOSImage + (BIOSDir->fields.entry - 0xE0000);			BIOSEntry.segment = _PCI_getCS();			break;			}		/* If we found the BIOS32 directory, call it to get the address of the		 * PCI services.		 */		if (BIOSEntry.address == 0)			return 0;		if (_BIOS32_service(PCI_SERVICE,0,&physBase,&length,&offset,BIOSEntry) != 0)			return 0;		PCIPhysEntry = physBase + offset;		PCIEntry.address = (ulong)BIOSImage + (PCIPhysEntry - 0xE0000);		PCIEntry.segment = _PCI_getCS();		}#endif	/* We found the BIOS entry, so now do the version check */	version = _PCIBIOS_isPresent(PCI_BIOS_PRESENT,&signature,&stat,lastBus,PCIEntry);	if (version > 0 && ((stat >> 8) == 0) && signature == PCI_SIGNATURE) {		*hwType = stat & 0xFF;		return version;		}	return 0;}/****************************************************************************REMARKS:This function maps in any shared memory needed by the PCI BIOS functions.****************************************************************************/void _ASMAPI PCI_mapShared(void){	PM_mapToProcess(BIOSImage,BIOS_LIMIT);}/****************************************************************************PARAMETERS:info	- Array of PCIDeviceInfo structures to check againstindex	- Index of the current device to checkRETURNS:True if the device is a duplicate, false if not.REMARKS:This function goes through the list of all devices preceeding the newlyfound device in the info structure, and checks that the device is not aduplicate of a previous device. Some devices incorrectly enumeratethemselves at different function addresses so we check here to excludethose cases.****************************************************************************/static ibool CheckDuplicate(	PCIDeviceInfo info[],	int index){	int i,duplicate;	/* Ignore devices with a vendor ID of 0 */	if (info[index].VendorID == 0)		return 1;	/* NOTE: We only check against the current device on	 *		 the bus to ensure that we do not exclude	 *		 multiple controllers of the same device ID.	 */	for (i = duplicate = 0; i < index; i++) {		if (info[i].slot.p.Bus == info[index].slot.p.Bus &&			info[i].slot.p.Device == info[index].slot.p.Device &&			info[i].DeviceID == info[index].DeviceID) {			duplicate = 1;			break;			}		}	return duplicate;}/****************************************************************************PARAMETERS:info		- Array of PCIDeviceInfo structures to fill inmaxDevices	- Maximum number of of devices to enumerate into arrayRETURNS:Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.REMARKS:Function to enumerate all available devices on the PCI bus into an arrayof configuration information blocks.****************************************************************************/static int PCI_enumerateMech1(	PCIDeviceInfo info[],	int maxDevices){	int				bus,device,function,i,numFound = 0;	ulong			*lp,tmp;	PCIslot			slot = {{0,0,0,0,0,0,1}};	PCIDeviceInfo	pci;	/* Try PCI access mechanism 1 */	PM_outpb(0xCFB,0x01);	tmp = PM_inpd(0xCF8);	PM_outpd(0xCF8,slot.i);	if ((PM_inpd(0xCF8) == slot.i) && (PM_inpd(0xCFC) != 0xFFFFFFFFUL)) {		/* PCI access mechanism 1 - the preferred mechanism */		for (bus = 0; bus < 8; bus++) {			slot.p.Bus = bus;			for (device = 0; device < 32; device++) {				slot.p.Device = device;				for (function = 0; function < 8; function++) {					slot.p.Function = function;					slot.p.Register = 0;					PM_outpd(0xCF8,slot.i);					if (PM_inpd(0xCFC) != 0xFFFFFFFFUL) {						memset(&pci,0,sizeof(pci));						pci.dwSize = sizeof(pci);						pci.mech1 = 1;						pci.slot = slot;						lp = (ulong*)&(pci.VendorID);						for (i = 0; i < NUM_PCI_REG; i++, lp++) {							slot.p.Register = i;							PM_outpd(0xCF8,slot.i);							*lp = PM_inpd(0xCFC);							}						COPY_STRUCTURE(&info[numFound],&pci);						if (!CheckDuplicate(info,numFound)) {							if (++numFound >= maxDevices)								break;							}						}					if (numFound >= maxDevices)						break;					}				if (numFound >= maxDevices)					break;				}			if (numFound >= maxDevices)				break;			}		/* Disable PCI config cycle on exit */		PM_outpd(0xCF8,0);		return numFound;		}	PM_outpd(0xCF8,tmp);	/* No hardware access mechanism 1 found */	return 0;}/****************************************************************************PARAMETERS:info		- Array of PCIDeviceInfo structures to fill inmaxDevices	- Maximum number of of devices to enumerate into arrayRETURNS:Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.REMARKS:Function to enumerate all available devices on the PCI bus into an arrayof configuration information blocks.****************************************************************************/static int PCI_enumerateMech2(	PCIDeviceInfo info[],	int maxDevices){	int				bus,device,function,i,numFound = 0;	ushort  		deviceIO;	ulong			*lp;	PCIslot			slot = {{0,0,0,0,0,0,1}};	PCIDeviceInfo	pci;	/* Try PCI access mechanism 2 */	PM_outpb(0xCFB,0x00);	PM_outpb(0xCF8,0x00);	PM_outpb(0xCFA,0x00);	if (PM_inpb(0xCF8) == 0x00 && PM_inpb(0xCFB) == 0x00) {		/* PCI access mechanism 2 - the older mechanism for legacy busses */		for (bus = 0; bus < 2; bus++) {			slot.p.Bus = bus;			PM_outpb(0xCFA,(uchar)bus);			for (device = 0; device < 16; device++) {				slot.p.Device = device;

⌨️ 快捷键说明

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