📄 pciext.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
/*
Copyright(c) 2001 Microsoft.
Module Name:
pciext.c
Revision History:
Oct 26th for Talisker #664 ( Del EDBGOutputDebugString )
*/
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <halether.h>
#include "shx.h"
#include "platform.h"
#include "oalintr.h"
#include "pciext.h"
#define IRQ_INTA SYSINTR_PCI_START
#define IRQ_INTB (SYSINTR_PCI_START+1)
#define IRQ_INTC (SYSINTR_PCI_START+2)
#define IRQ_INTD (SYSINTR_PCI_START+3)
#define MAX_PCI_IRQ (SYSINTR_PCI_START+4)
static DWORD IrqTable[4][4] = {
{IRQ_INTA, IRQ_INTB, IRQ_INTC, IRQ_INTD}, // Bus 0, Device 9, PCI-PCI bridge
{IRQ_INTB, IRQ_INTC, IRQ_INTD, IRQ_INTA}, // Bus 0, Device 10, slot 3
{IRQ_INTC, IRQ_INTD, IRQ_INTA, IRQ_INTB}, // Bus 0, Device 11, slot 2
{IRQ_INTD, IRQ_INTA, IRQ_INTB, IRQ_INTC} // Bus 0, Device 12, slot 1
};
ULONG Logic2SysIntr[MAX_PCI_IRQ + 1];
ULONG SysIntr2Logic[SYSINTR_MAXIMUM];
#if 0
void OEMInitInterrupts()
{
memset(Logic2SysIntr, 0xFF, sizeof(Logic2SysIntr));
memset(SysIntr2Logic, 0xFF, sizeof(SysIntr2Logic));
WRITE_REGISTER_ULONG(FPGA_IMASK,
(READ_REGISTER_ULONG(FPGA_IMASK) | FPGA_IMASK_IV3 ));
}
#endif
DWORD OEMTranslateIrq(
DWORD Irq
)
{
if (Irq < SYSINTR_PCI_START)
return Irq; // IF it is Built-in Interrupt. It is one-to-one map
else
if (Irq > MAX_PCI_IRQ ) {
ASSERT(FALSE);
return -1;
} else {
ASSERT( Logic2SysIntr[Irq]!=0xFF);
return Logic2SysIntr[Irq];
}
}
DWORD OEMTranslateSysIntr(
DWORD SysIntr
)
{
if (SysIntr >= SYSINTR_MAXIMUM) {
ASSERT(FALSE);
return -1;
} else {
ASSERT( Logic2SysIntr[SysIntr]!=0xFF);
return SysIntr2Logic[SysIntr];
}
}
DWORD OEMRequestSysIntr(
DWORD Irq
)
{
DWORD SysIntr;
if (Irq < SYSINTR_PCI_START)
return Irq; // IF it is Built-in Interrupt. It is one-to-one map
else
if (Irq > MAX_PCI_IRQ) {
ASSERT(FALSE);
return -1;
}
if ((Irq != IRQ_INTA) && (Irq != IRQ_INTB) && (Irq != IRQ_INTC) && (Irq != IRQ_INTD)) {
ASSERT(FALSE);
return -1;
}
// Look for next free SYSINTR
for (SysIntr = SYSINTR_PCI_START; SysIntr < SYSINTR_MAXIMUM; SysIntr++) {
if (SysIntr2Logic[SysIntr] == -1) break;
}
// No free SYSINTRs left
if (SysIntr >= SYSINTR_MAXIMUM) {
ASSERT(FALSE);
return -1;
}
// Make SYSINTR -> Irq association
SysIntr2Logic[SysIntr] = Irq;
// Make Irq -> SYSINTR association, only if not multiply-mapped
if (Logic2SysIntr[Irq] == -1) {
Logic2SysIntr[Irq] = SysIntr;
}
return SysIntr;
}
BOOL
OEMGetInterrupt(
PDEVICE_LOCATION pDevLoc,
PDWORD pIrq
)
{
BOOL RetVal = TRUE;
int Bus = pDevLoc->BusNumber;
int Device = (pDevLoc->LogicalLoc >> 8) & 0xFF;
*pIrq = 0xFF;
// Currently supporting only PCIbus
if (pDevLoc->IfcType != PCIBus) return FALSE;
// Make sure interrupt Pin is in range
if ((pDevLoc->Pin < 1) || (pDevLoc->Pin > 4)) return FALSE;
if (Bus == 0) {
// Bus 0 has devices 9 through 12 mapped
if ((Device < 12) || (Device > 16)) {
return FALSE;
}
*pIrq = IrqTable[Device - 13][pDevLoc->Pin - 1];
return TRUE;
} else {
// All other buses behind PCI-PCI bridge conform to PCI convention
Device = Device % 4;
*pIrq = IrqTable[Device][pDevLoc->Pin - 1];
}
return RetVal;
}
#define DEVICE_360 360
# define V3_DEVICE DEVICE_360
/* 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 PCI_MEM_SIZE MB_16
# define PCI_IO_SIZE MB_1 /* size of PCI IO Area. */
# define PCI_CONFIG_SIZE PCI_MEM_SIZE
# define V3_InternalRegBase PHYSICAL_V3_INTERNAL_REG_BASE
/* Interrupt for PCI_INT_CFG */
#define PCI_INTD_CFG 0x8000
#define PCI_INTC_CFG 0x0400
#define PCI_INTB_CFG 0x0020
#define PCI_INTA_CFG 0x8001
/* 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))
#define V360_PCI_BASE0 (*(volatile unsigned long*)(0x14+V3_InternalRegBase))
#define V360_PCI_BASE1 (*(volatile unsigned long*)(0x18+V3_InternalRegBase))
#define V360_PCI_MAP0 (*(volatile unsigned long*)(0x40+V3_InternalRegBase))
#define V360_PCI_MAP1 (*(volatile unsigned long*)(0x44+V3_InternalRegBase))
#define V360_PCI_INT_STAT (*(volatile unsigned long*)(0x48+V3_InternalRegBase))
#define V360_PCI_INT_CFG (*(volatile unsigned long*)(0x4c+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_LB_ISTAT (*(volatile unsigned short*)(0x76+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))
#define INIT_WAIT_TIME 0x6FFFF /* Need to fine tune */
#define INIT_WAIT { int i; for(i = 0; i < INIT_WAIT_TIME; i ++); }
#define CONFIG_WAIT_TIME 0x60000
#define CONFIG_WAIT { int i; for(i = 0; i < CONFIG_WAIT_TIME; i ++); }
DWORD PciConfigBase=0;
DWORD NKCallIntChainWrapped( BYTE bIRQ ) ;
#ifdef BSP_NOPCIBUS
int PCI_ISR()
{ // From PCI external board.
DWORD dwFpgaIStat;
DWORD old_val;
DWORD dwIrq=-1;
DWORD nSysIntr=SYSINTR_NOP;
dwFpgaIStat = READ_REGISTER_ULONG(FPGA_ISTAT);
if ((dwFpgaIStat & FPGA_IMASK_IV3)==0 && PciConfigBase==0) {
OEMWriteDebugString(TEXT("Wrong PCI Interrupt\r\n"));
return SYSINTR_NOP;
}
// Save OLD Value of LB_MAP1 so that you can restore it after the access
old_val = V360_LB_MAP1_RES;
V360_LB_MAP1_RES=0x00000000; // Intr Ack Cycle.
dwIrq=*(volatile DWORD *)PciConfigBase;
dwIrq +=SYSINTR_PCI_START;
V360_LB_MAP1_RES=old_val;
nSysIntr = NKCallIntChainWrapped((BYTE)dwIrq);
if (nSysIntr == SYSINTR_CHAIN) {
nSysIntr = OEMTranslateIrq(dwIrq);
OEMPciIntrDisable(dwIrq);
}
return (nSysIntr==-1? SYSINTR_NOP: nSysIntr);
};
BOOL OEMPciIntrEnable(DWORD dwIrq)
{
switch (dwIrq) {
case IRQ_INTA:
V360_PCI_INT_CFG |=PCI_INTA_CFG;
break;
case IRQ_INTB:
V360_PCI_INT_CFG |=PCI_INTB_CFG;
break;
case IRQ_INTC:
V360_PCI_INT_CFG |=PCI_INTC_CFG;
break;
case IRQ_INTD:
V360_PCI_INT_CFG |=PCI_INTD_CFG;
break;
default:
return FALSE;
}
return TRUE;
}
BOOL OEMPciIntrDisable(DWORD dwIrq)
{
switch (dwIrq) {
case IRQ_INTA:
V360_PCI_INT_CFG &=~PCI_INTA_CFG;
break;
case IRQ_INTB:
V360_PCI_INT_CFG &=~PCI_INTB_CFG;
break;
case IRQ_INTC:
V360_PCI_INT_CFG &=~PCI_INTC_CFG;
break;
case IRQ_INTD:
V360_PCI_INT_CFG &=~PCI_INTD_CFG;
break;
default:
return FALSE;
}
return TRUE;
}
BOOL OEMPciIntrDone(DWORD dwIrq)
{
return OEMPciIntrEnable(dwIrq);
}
#endif
/*
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI]
"Dll"="PCIbus.dll"
"Order"=dword:20
"Flags"=dword:1
"NoConfig"=dword:0
"MemBase"=dword:10000000
"MemLen"=dword:04000000
"IoBase"=dword:0
"IoLen"=dword:00040000
*/
#ifdef BSP_NOPCIBUS
/*****************************************************************************
* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -