oempci.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,258 行 · 第 1/4 页

C
1,258
字号
/******************************************************************************
 * File: OEMPCI.C
 * Modified by: Naresh Gupta (nkgupta@hotmail.com)
 * This file provides the low level PCI interface functions and would work
 * with both Windows CE and SDBTests.
 *****************************************************************************/

#include <windows.h>
#include "platform.h"
#include "pci.h"
#include "my_pci.h"
#include "common.h"
#include <stdio.h>
#include "oem.h"

#ifdef SDBTESTS
#include "standalone.h"
#endif SDBTESTS

// #define PUT_PCI_DELAY

/* Which V3 Device are you using. It can be one of the following 3 :-
       292: For V292 PBC (PCI Bus Controller) support.
	   360: For V360 EPC (Enahanced PCI Controller) support.
	   320: For V320 USC support.
 */
#define DEVICE_292						292
#define DEVICE_360						360
#define DEVICE_320						320

/* Messages to be printed in DEBUG version */
#define DEB_PCI_INIT						1	/* PCI Initialization Code */
#define DEB_PCI_CONFIG						1	/* PCI Config Read/Write */

extern int DbgPrintf(char *s, ...);
extern void ProcessCommands();
/************* End of User Programmable Parameters. *************/

/* For ASPEN the Platform is PLATFORM_ASPEN and V3 device is DEVICE_360 */
#if ( (SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_S1) )
#	define V3_DEVICE					DEVICE_360
#elif (SH_PLATFORM == PLATFORM_BIGSUR)
#	define V3_DEVICE					DEVICE_320
#else // Default for other platforms.
#	define V3_DEVICE					DEVICE_360		/* options: 292, 360, 320 */
#endif // (SH_PLATFORM == PLATFORM_ASPEN)

/* Notes:-
  USC = V320
  EPC = V360 EPC: Enhanced PCI Controller
  PBC = V292 PBC: Pci Bus Controller
 Initialization
 --------------

 V360EPC:
    1. LRESET# assert and deassert.
	2. After the reset, the EPC captures all writes on the local bus, till it
	3. Wait for 8 clock cycles.
	   sees a write to the offset 0x6E (LB_IO_BASE). It sets the LB_IO_BASE
	   register and after that all the registers are seen in the window starting
	   at the value programmed in LB_IO_BASE register.
	3. This strategy doesn't seem to work. Please see Errata A0-4 to see
	   whether the problem is the same of different.

 V320USC:
    The document does not mention how to set LB_IO_BASE from the local bus.


 The common registers are coded as V3... to use the same code for both
 V320 and V360. If the registers are different, then V320 registers would
 be named as V320..., and V360 registers would be named V360... (The register
 names for V292 and V360 are same though some of the registers have different
 bit definitions.

 */

/* Some defines for SH4, and ASPEN. These would later be moved to a separate
 * header file */
#define FRQCR							0xFFC00000		// Frequency Regoister
#define MExINT							0xA6000000		// Interrupt Register
#define ExINT							0xA6000002		// Interrupt Register

#define BCR1							0xFF800000
#define BCR2							0xFF800004
#define WCR1							0xFF800008
#define WCR2							0xFF80000C
#define WCR3							0xFF800010
#define MCR								0xFF800014

/* Some predefined Sizes in MB */
#define MB_1							0x00100000
#define MB_2							(2  * MB_1)
#define MB_4							(4  * MB_1)
#define MB_8							(8  * MB_1)
#define MB_16							(16 * MB_1)
#define MB_32							(32 * MB_1)
#define MB_64							(64 * MB_1)

/* Type of cycles that can be generated on PCI bus. Value to be written to LB_MAP registers. */
#define TYPE_INT						0x0		/* Interrupt acknowledge (read) */
#define TYPE_IO							0x2		/* IO Read/Write */
#define TYPE_MEM						0x6		/* Memory Read/Write */
#define TYPE_CONFIG						0xA		/* Config Read/Write */
#define TYPE_MEM_MULTIPLE				0xC		/* Memory Read Multiple/ Memory Write */

				

/* Define the PCI Address spaces, FPGA registers, and V3 Memory Area. for
 * each of the platforms. */

/* S1 */
#if (SH_PLATFORM == PLATFORM_S1)
#	define PHYSICAL_FPGA_BASE			 		0xA6000000

// FPGA Registers related to PCI
#	define FPGA_INT_CSR	 		*(volatile unsigned long *)(0x00 + FPGA_Base)
#	define FPGA_PCI_CNT		 	*(volatile unsigned short *)(0x04 +FPGA_Base)

/* Definitions of the FPGA registers for S1 are as follows :-

      FPGA_INT_CSR: Lower 16 bits: FPGA PCI Interrupt Control

       15                         9  8                                 0 
      ------------------------------------------------------------------
      | - | - | -                   |     csr(8) --- csr(0)             |
      ------------------------------------------------------------------



      FPGA_INT_CSR: Upper 16 bits: FPGA PCI Interrupt Status

       15                                                              0 
      ------------------------------------------------------------------
      |                 Interrupt Status                                |
      ------------------------------------------------------------------



       FPGA_PCI_CNT: FPGA PCI Control register.

         15       14     13    12     11    10     9    8    7               0 
      ------------------------------------------------------------------------
      | xRST | idsel2 | id1 | id0 | vbWE3 | vb2 | vb1 | vb0 |    b7 - b0      |
      ------------------------------------------------------------------------

 */

/* Various PCI Areas that you want. */
#	define PHYSICAL_PCI_MEM_BASE			0xA4000000
#	define PHYSICAL_PCI_CONFIG_BASE			0xA4000000
#	define PHYSICAL_PCI_IO_BASE				0xA5000000
#	define PCI_MEM_SIZE						MB_16	/* size of PCI Memory Area. */
#	define PCI_IO_SIZE						MB_1	/* size of PCI IO Area. */
#	define PCI_CONFIG_SIZE					PCI_MEM_SIZE

/* Area where the V3 registers are present */
#	define PHYSICAL_V3_MEM_BASE				0xA4000000 // V3 is present in area 1.
#	define PHYSICAL_V3_INTERNAL_REG_BASE	0xA5800000
#endif //(SH_PLATFORM == PLATFORM_S1)


/* Aspen */
#if (SH_PLATFORM == PLATFORM_ASPEN)
#	define PCI_MEM_SIZE						MB_16
#	define PCI_IO_SIZE						MB_1	/* size of PCI IO Area. */
#	define PCI_CONFIG_SIZE					PCI_MEM_SIZE
#endif // (SH_PLATFORM == PLATFORM_ASPEN)

/* BigSur */
#if (SH_PLATFORM == PLATFORM_BIGSUR)
#	define PCI_MEM_SIZE						MB_16
#	define PCI_IO_SIZE						MB_1	/* size of PCI IO Area. */
#	define PCI_CONFIG_SIZE					PCI_MEM_SIZE
#endif // (SH_PLATFORM == PLATFORM_BIGSUR)

/* Register common to all V3 devices supported. */
#define V3_PCI_DEV_VEN	 	(*(volatile unsigned long*)(0x00+V3_InternalRegBase))
#define V3_PCI_STAT_CMD	 	(*(volatile unsigned long*)(0x04+V3_InternalRegBase))
#define V3_PCI_CC_REV		(*(volatile unsigned long*)(0x08+V3_InternalRegBase))
#define V3_PCI_HDR_CFG	 	(*(volatile unsigned long*)(0x0C+V3_InternalRegBase))


/* Register common between 292 and 360 are named as V360... */
#define V360_LB_BASE0	 	(*(volatile unsigned long*)(0x54+V3_InternalRegBase))
#define V360_LB_BASE1	 	(*(volatile unsigned long*)(0x58+V3_InternalRegBase))
#define V360_LB_MAP0_RES 	(*(volatile unsigned long*)(0x5c+V3_InternalRegBase))
#define V360_LB_MAP1_RES 	(*(volatile unsigned long*)(0x60+V3_InternalRegBase))
#define V360_LB_IO_BASE_RES	(*(volatile unsigned long*)(0x6c+V3_InternalRegBase))
#define V360_LB_CFG_SYSTEM	(*(volatile unsigned long*)(0x78+V3_InternalRegBase))
#define V360_FIFO_PRIOR_CFG	(*(volatile unsigned long*)(0x70+V3_InternalRegBase))
#define V360_PCI_CFG		(*(volatile unsigned long*)(0x7C+V3_InternalRegBase))

#define V360_INITIAL_LB_IO_BASE_RES	(*(volatile unsigned long*)(0x6c+PHYSICAL_V3_INTERNAL_REG_BASE))

/* Register specific to V320 */
#define V320_LB_PCI_BASE0 	(*(volatile unsigned long*)(0x54+V3_InternalRegBase))
#define V320_LB_PCI_BASE1 	(*(volatile unsigned long*)(0x58+V3_InternalRegBase))
#define V320_LB_BUS_CFG		(*(volatile unsigned long*)(0x78+V3_InternalRegBase))
#define V320_SYSTEM_LB_REG_BASE		(*(volatile unsigned long*)(0x70+V3_InternalRegBase))

#define V320_INITIAL_SYSTEM_LB_REG_BASE		(*(volatile unsigned long*)(0x70+V3_InternalRegBase))

/* Function prototypes */
extern void Command_Scan(void);
void OEM_EncodeConfigAddress( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD *pdwAddress );
void OEM_ReadConfigDword( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD *pdwData );
void OEM_WriteConfigDword( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD dwData );
int MapRegisters(void);
unsigned VirtualAddress(unsigned StartAddress, unsigned Length);


#ifndef SDBTESTS
extern struct PciBaseAddresses_Type PciBaseAddresses;
#endif SDBTESTS

/* Virtual Address of Various Base Addresses. Same as physical address for SDBTESTS */
static unsigned V3_InternalRegBase,		/* Base Address of V3 registers. */
				PciIoBase,				/* I/O Base Address. */
				PciMemBase,
				PciConfigBase;

/* For the benefit of other files in the PCI driver, these two varibles give
 * the physical io and memory addresses of PCI address space.
 */
unsigned PhysicalPciIoBase,
		 PhysicalPciMemBase;

int pci_wait, 
	config_wait; // Wait time period before configuration area read/write

/* Junk global variable to make sure it does not get removed while optimization */
int my_wait;

/* Time periods for various waits. Need to fine tune later. */
// #define INIT_WAIT_TIME			0x4FFFF	 /* Need to fine tune */
// #define CONFIG_WAIT_TIME 		0x40000

#define INIT_WAIT_TIME			0x6FFFF	 /* Need to fine tune */
#define CONFIG_WAIT_TIME 		0x60000

/* INIT_WAIT is the time that you need to wait while resetting the V3 device */
#define INIT_WAIT   { int i; for(i = 0; i < INIT_WAIT_TIME; i ++); }

#ifdef PUT_PCI_DELAY
#define CONFIG_WAIT { int i; for(i = 0; i < CONFIG_WAIT_TIME; i ++); }
#else PUT_PCI_DELAY
#define CONFIG_WAIT
#endif PUT_PCI_DELAY


#ifndef SDBTESTS
/******************************************************************************
 * Function:	VirtualAddress
 * Input:       unsigned StartAddress
 *				unsigned Length
 * Output:      Success: Pointer to start of Virtual Address Space allocated.
 *				Failure: NULL
 * Synopsis:	This routine maps "Length" bytes of physical memory starting
 *				at "StartAddress" into the Virtual Address Space and returns
 *				a pointer to the start of this Virtual Address Space.
******************************************************************************/
unsigned VirtualAddress(unsigned StartAddress, unsigned Length) 
{
	
	unsigned *VirtAddr;

	DEBUGMSG(DEB_PCI_INIT, (TEXT("+VirtualAddress(0x%x, 0x%x): "), StartAddress, Length));

  	VirtAddr = VirtualAlloc(0, Length, MEM_RESERVE, PAGE_NOACCESS);

	DEBUGMSG(DEB_PCI_INIT, (TEXT("Got VirtAddr = 0x%x\r\n"), VirtAddr));
  	if ( VirtAddr == NULL ) {
    	ERRORMSG(1,	(TEXT("DD2: MapAddress: VirtualAlloc failed for %d bytes!\r\n"), Length));
		return FALSE;
  	}
  	else {
  		if ( !VirtualCopy((PVOID)VirtAddr, (PVOID)StartAddress, 
  				Length, PAGE_READWRITE|PAGE_NOCACHE) ) {
    		ERRORMSG(1,	(TEXT("DD2: MapAddress: VirtualCopy failed for Physical Address 0x%08x!\r\n"), StartAddress));
			return FALSE;
		}
  	}

	return (unsigned)VirtAddr;
}
#endif SDBTESTS

/*****************************************************************************
 * Function: MapRegisters
 * Input:    None
 * Output:   Sets the members of the PciBaseAddresses structure.
 * Synopsis: 1. This function is used to Map the virtual address space of PCI
 *              registers to the address space of the PCI driver.
 *           2. If you are using this routine as a part of SDBTESTS, it does
 *              nothing, but returning the actual PCI addresses.
 ****************************************************************************/
int MapRegisters(void)
{
	static int RegistersMapped = 0;
	int retval = TRUE;

  	DEBUGMSG(DEB_PCI_INIT, (TEXT("+PCI: MapRegisters\r\n")));

	// If the registers have already been mapped, just return.
	if(RegistersMapped) {
		return TRUE;
	}
	RegistersMapped = TRUE;

#ifdef SDBTESTS
	PciIoBase 			= PHYSICAL_PCI_IO_BASE;
	PciMemBase 			= PHYSICAL_PCI_MEM_BASE;
	PciConfigBase	 	= PHYSICAL_PCI_CONFIG_BASE;
	V3_InternalRegBase 	= PHYSICAL_V3_INTERNAL_REG_BASE;
#else

⌨️ 快捷键说明

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