📄 pciext.c
字号:
* nothing, but returning the actual PCI addresses.
****************************************************************************/
int MapRegisters(void)
{
static int RegistersMapped = 0;
int retval = TRUE;
DEBUGMSG(1, (TEXT("+PCI: MapRegisters\r\n")));
// If the registers have already been mapped, just return.
if(RegistersMapped) {
return TRUE;
}
RegistersMapped = TRUE;
PciConfigBase = (DWORD)(PHYSICAL_PCI_CONFIG_BASE|UNCACHED_BASE);
// V3_InternalRegBase = PHYSICAL_V3_INTERNAL_REG_BASE;
DEBUGMSG(1, (TEXT("PCI: -MapRegisters returning %d\r\n"), retval));
return retval;
}
// PCI Bridge
int OEM_InitPCIHostBridge( void )
{
unsigned tmp, i;
RETAILMSG(1, (TEXT("\r\n+InitPCIHostBridge\r\n")));
/* Map Registers into your virtual address space. */
MapRegisters();
INIT_WAIT;
RETAILMSG(1, (TEXT("PCI_INIT: Writing 0x%x to 0x%x\r\n"), (PHYSICAL_V3_INTERNAL_REG_BASE + 0x6c), &V360_LB_IO_BASE_RES));
V360_LB_IO_BASE_RES = (0x6c+PHYSICAL_V3_INTERNAL_REG_BASE);
INIT_WAIT;
#if 0
DbgPrintf("Set io base register. \r\n");
{
unsigned tmp;
DbgPrintf("BCR1 = 0x%x\r\n", *(unsigned long *)0xFF800000);
tmp = V3_PCI_DEV_VEN;
DbgPrintf("tmp = %x\r\n", tmp);
}
#endif 0
RETAILMSG(1, (TEXT("PCI_INIT: V3 device reads Vendor ID = %x, Device ID = %x\r\n"),
(V3_PCI_DEV_VEN & 0xFFFF), ((V3_PCI_DEV_VEN >> 16) & 0xFFFF)) );
// Flush ALL FIFOs
V360_LB_CFG_SYSTEM = 0x00008077; // 0x8000; // 0x00008077; // 0x63008077;
V360_LB_CFG_SYSTEM = 0x00000000; // 0x63008077;
V360_LB_CFG_SYSTEM = 0x63c08000; // 0x8000; // 0x63c08000; //
INIT_WAIT;
V3_PCI_STAT_CMD = 0x00000246; // 0x00000246;
V3_PCI_HDR_CFG = 0x0000F800; // 0x00000800;
// Find out what to write in the BASE1 registers, Size bits.
// The size bits contain the encoded value of the bits that is 1 above 1 Mb.
i = 0;
tmp = MB_1;
// Possible values of ADR_SIZE are from 0 (1Mb) to 11 (2 Gb). Though SH4 will not support such big value
// I still check for it.
for(i = 0; i <= 11; i++) {
if(tmp == PCI_MEM_SIZE)
break;
tmp <<= 1;
}
// At present i support only slots up to 64 Mb.
if( i > 6) {
ERRORMSG(1, (TEXT("Error: Got invalid size of PCI Memory Space (0x%x). Check PCI_MEM_SIZE in oempci.c\n"), PCI_MEM_SIZE));
return -1;
}
tmp = PHYSICAL_PCI_MEM_BASE |UNCACHED_BASE | (i << 4) | 0x1;
// DbgPrintf("Writing 0x%x to LB_BASE1\n", tmp);
V360_LB_BASE0 = PHYSICAL_PCI_IO_BASE |UNCACHED_BASE| 0x01; // Enable.
V360_LB_BASE1 = tmp;
V360_LB_MAP0_RES = 0x00020000; // Map PHYSICAL_PCI_IO_BASE to -> 0
V360_LB_MAP1_RES = 0x00060000 | (tmp&0xfff00000L) ; // It is One to one MAP
DEBUGMSG(1, (TEXT("LB_BASE0=0x%x, 1=0x%x, MAP0=0x%x, 1=0x%x, tmp=0x%x\r\n"), V360_LB_BASE0, V360_LB_BASE1,
V360_LB_MAP0_RES, V360_LB_MAP1_RES, tmp));
// PCI to LOCAL map
V360_PCI_BASE0 = ((DRAM_BASE | UNCACHED_BASE) & 0xfff00000);
V360_PCI_MAP0 = ((DRAM_BASE | UNCACHED_BASE ) & 0xfff00000) | 3 | (5<4); // 64 M uncached memory
// PCI to LOCAL map
V360_PCI_BASE1 = ((DRAM_BASE ) & 0xfff00000);
V360_PCI_MAP1 = ((DRAM_BASE ) & 0xfff00000) | 3 | (5<4); // 64 M cached memory
V360_FIFO_PRIOR_CFG = 0x0f0f0000;
// PCI Interrupt
V360_PCI_INT_CFG = 0x8421;
V360_LB_ISTAT = 0x1010;
#if 0
WRITE_REGISTER_USHORT(V3_LB_MAP0, 0x000a);
WRITE_REGISTER_USHORT(FPGA_PCI_CNT, 0xa0FF);
#endif
CONFIG_WAIT;
RETAILMSG(1, (TEXT("-InitPCIHostBridge\r\n")));
// Command_Scan();
return 0;
#if 0
/* Enable Bus Mastering on the primary PCI segment for the ATU through the */
/* Primary ATU Command Register */
*(volatile WORD *)0x00001204 = 0x0157;
/* Set PCI Interrupt Routing Control so that it does not route CPU board */
/* secondary interrupts to primary PCI segment */
*(volatile DWORD *)0x00001050 = 0x0000000F;
/* Make sure that the internal bridge does not accept any accesses */
*(volatile WORD *)0x00001004 = 0;
#endif
return 0;
}
/* This function will encode a Type 0 or Type 1 configuration address based on */
/* the parameters passed in. */
void OEM_EncodeConfigAddress( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD *pdwAddress ) {
/* Assume that we need to generate Type 0 bus cycles for Bus 0, based on */
/* the assumption that bus 0 is the one connected to the PCI host bridge. */
if (dwBusNo == 0) {
*pdwAddress = (0x00000800 << dwDevNo) | (dwFuncNo << 8) | (dwOffset & 0xFC);
}
else {
/* Generate a Type 1 address for everything not on Bus 0. */
*pdwAddress = (dwBusNo << 16) | (dwDevNo << 11) | (dwFuncNo << 8) | (dwOffset & 0xFC) | 1;
}
} /* OEM_EncodeConfigAddress */
DWORD OEM_ReadConfigDword(IN ULONG BusNumber, IN ULONG DeviceNumber, IN ULONG FunctionNumber,
IN ULONG Offset)
{
// This routine would check out the entire range of idsels by asserting
// bits 11 - 31, one bit at a time.
// If some of the bits are don't care, it would not make any difference.
// So the configuration addresses generated would be of the form :-
// dwDevNo == 0, idSel = 0x00000800
// dwDevNo == 1, idSel = 0x00001000
// dwDevNo == 21, idSel = 0x8000000
// This way a max. of 21 devices are supported.
DWORD dwConfigAddress;
DWORD dwReturn;
unsigned addr;
unsigned old_val;
// DEBUGMSG(0, (TEXT("RCD: dwBusNo = 0x%x, dwDevNo = 0x%x, dwFuncNo = 0x%x, dwOffset = 0x%x\r\n"), BusNumber, DeviceNumber, FunctionNumber,Offset));
// CONFIG_WAIT;
// Get the address in the PCI configuration space for the requested register
OEM_EncodeConfigAddress( BusNumber, DeviceNumber, FunctionNumber, Offset, &dwConfigAddress );
// Save OLD Value of LB_MAP1 so that you can restore it after the access
old_val = V360_LB_MAP1_RES;
// DEBUGMSG(0, (TEXT("Encoded Address = 0x%x\r\n"), dwConfigAddress));
// Now is the address bigger than PCI memory size that you mapped ?
if(dwConfigAddress >= PCI_CONFIG_SIZE) {
// DEBUGMSG(1, (TEXT("Writing to LB_MAP1_RES1 0x%x\n"), ((dwConfigAddress & 0xFFF00000) | (TYPE_CONFIG << 16)) ));
// Split dwConfigAddress into two parts. The upper part gets written
// to MAP1 register and the lower part is the address that gets accessed.
V360_LB_MAP1_RES = ((dwConfigAddress & 0xFFF00000) | (TYPE_CONFIG << 16));
}
else {
// DEBUGMSG(0, (TEXT("Writing to LB_MAP1_RES2 0x%x\r\n"), (TYPE_CONFIG) << 16) );
V360_LB_MAP1_RES = (TYPE_CONFIG) << 16 ;
}
addr = PciConfigBase + (dwConfigAddress & (PCI_CONFIG_SIZE - 1));
// DEBUGMSG(1, (TEXT("addr = 0x%x\r\n"), addr));
// If type is 1, that is address bits 0,1 are 01, Then you need to
// program AD_LOW_ENABLE in LB_MAP1_RES and AD_LOW=01 in PCI_CFG
if(addr & 3) {
volatile unsigned long *tmp_addr = (unsigned *) (addr & 0xFFFFFFFC);
// CONFIG_WAIT;
// Set bits 8,9 of PCI_CFG register to the override value of address.
V360_PCI_CFG = ( V360_PCI_CFG & ~(0x300) ) | ( (addr & 3) << 8);
V360_LB_MAP1_RES = (V360_LB_MAP1_RES | 0x10000);
// DEBUGMSG(1, (TEXT("RCD: addr = 0x%x, V360_PCI_CFG = 0x%x, V360_LB_MAP1_RES = 0x%x\n"), tmp_addr, V360_PCI_CFG, V360_LB_MAP1_RES));
dwReturn = *tmp_addr;
}
else {
// CONFIG_WAIT;
// DEBUGMSG(1, (TEXT("About to read location 0x%x, \r\n"), addr));
dwReturn = *(volatile unsigned long *)(addr);
// DEBUGMSG(1, (TEXT("read data %x\r\n"), dwReturn));
}
// DEBUGMSG(1, (TEXT("RCD(BDFO)=(%d:%d:%d:0x%x),A=%x,*D=%x,M1=%x,CA=%x\r\n"), BusNumber, DeviceNumber, FunctionNumber, Offset, addr, dwReturn, V360_LB_MAP1_RES, dwConfigAddress));
// Switch back the area to old mode
V360_LB_MAP1_RES = old_val;
// No need to reset PCI_CFG AD_LOW bits since they would not be used.
return dwReturn;
}
int glbl_wait = 1000;
/* Junk global variable to make sure it does not get removed while optimization */
int my_wait=0;
void OEM_WriteConfigDword(IN ULONG BusNumber, IN ULONG DeviceNumber, IN ULONG FunctionNumber,
IN ULONG Offset, IN ULONG dwData)
{
DWORD dwConfigAddress;
unsigned addr;
unsigned old_val;
// CONFIG_WAIT;
// Get the address in the PCI configuration space for the requested register
OEM_EncodeConfigAddress( BusNumber, DeviceNumber, FunctionNumber, Offset, &dwConfigAddress );
// Save OLD Value of LB_MAP1 so that you can restore it after the access
old_val = V360_LB_MAP1_RES;
// Now is the address is bigger than PCI memory size that you mapped,
if(dwConfigAddress >= PCI_CONFIG_SIZE) {
// Split dwConfigAddress into two parts. The upper part gets written
// to MAP1 register and the lower part is the address that gets accessed.
V360_LB_MAP1_RES = ((dwConfigAddress & 0xFFF00000) | (TYPE_CONFIG << 16));
}
else {
V360_LB_MAP1_RES = (TYPE_CONFIG) << 16 ;
}
addr = PciConfigBase + (dwConfigAddress & (PCI_CONFIG_SIZE - 1));
// DEBUGMSG(1, (TEXT("WCD: (B:D:F:O) = (%d:%d:%d:0x%x), *Data=%x, addr=%x, MAP1=%x\r\n"), BusNumber, DeviceNumber, FunctionNumber,Offset, dwData, addr, V360_LB_MAP1_RES));
// If type is 1, that is address bits 0,1 are 01, Then you need to
// program AD_LOW_ENABLE in LB_MAP1_RES and AD_LOW=01 in PCI_CFG
if(addr & 3) {
volatile unsigned long *tmp_addr = (unsigned long *)(addr & 0xFFFFFFFC);
// Set bits 8,9 of PCI_CFG register to the override value of address.
V360_PCI_CFG = ( V360_PCI_CFG & ~(0x300) ) | ( (addr & 3) << 8);
V360_LB_MAP1_RES = (V360_LB_MAP1_RES | 0x10000);
// DEBUGMSG(1, (TEXT("WCD: addr = 0x%x, V360_PCI_CFG = 0x%x, V360_LB_MAP1_RES = 0x%x "), tmp_addr, V360_PCI_CFG, V360_LB_MAP1_RES));
// Presently i need to write to this register many times, since if i
// write only once, it does not reliably get written to the register.
// Either some timing problem or some wrongly set paramter.
*tmp_addr = dwData; // Write code
#if 1 // def PUT_PCI_DELAY
{
int i;
for(i = 0; i < 1; i++)
for(glbl_wait = 0; glbl_wait < my_wait; glbl_wait ++);
*tmp_addr = dwData; // Write code
}
// DEBUGMSG(1, (TEXT("RB: 0x%x\n"), *(volatile unsigned long *)(tmp_addr)));
#endif PUT_PCI_DELAY
}
else {
*(volatile unsigned long *)(addr) = dwData; // Write code
// DEBUGMSG(1, (TEXT("RB: 0x%x\n"), *(volatile unsigned long *)(addr)));
}
// DEBUGMSG(1, (TEXT("WCD: (B:D:F:O) = (%d:%d:%d:0x%x), *Data=%x, addr=%x, MAP1=%x, dwConfigAddress=%x\r\n"), BusNumber, DeviceNumber, FunctionNumber,Offset, dwData, addr, V360_LB_MAP1_RES, dwConfigAddress));
// Switch back the area to old mode
V360_LB_MAP1_RES = old_val;
// No need to reset PCI_CFG AD_LOW bits since they would not be used.
return;
} /* OEM_WriteConfigDword() */
ULONG PCI_Type1_Configuration(ULONG BusNumber, ULONG SlotNumber, PVOID Buffer,
ULONG Offset, ULONG Length, BOOL fSet)
{
PULONG pBuffer;
int registerOffset, endOffset;
ULONG DeviceNumber, FunctionNumber;
if (BusNumber >= PCI_MAX_BUS)
return (0);
DeviceNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.DeviceNumber;
FunctionNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.FunctionNumber;
if (DeviceNumber >= PCI_MAX_DEVICES)
return (0);
registerOffset = Offset / sizeof(ULONG);
endOffset = registerOffset + (Length + sizeof(ULONG) - 1) / sizeof(ULONG);
pBuffer = Buffer;
for ( ; registerOffset < endOffset; ++registerOffset)
{
if (fSet)
OEM_WriteConfigDword(BusNumber, DeviceNumber, FunctionNumber,
registerOffset * 4, *pBuffer++);
else
*(pBuffer++) = OEM_ReadConfigDword(BusNumber, DeviceNumber,
FunctionNumber,
registerOffset * 4);
}
return (Length);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -