📄 pci_serv.c
字号:
//=============================================================================
//
// pci_serv.c - Cyclone Diagnostics
//
//=============================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (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.redhat.com/
//
// 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 eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
// Contributors:
// Date: 2001-01-25
// Purpose:
// Description:
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
/********************************************************************************/
/* PCI_SERV.C - PCI driver for IQ80310 */
/* */
/* History: */
/* 15sep00 ejb Ported to Cygmon on IQ80310 */
/* 18dec00 snc */
/********************************************************************************/
#include "iq80310.h"
#include "pci_bios.h"
#undef DEBUG_PCI
#define IB_MA_ERROR 0x2000
/*==========================================================================*/
/* Globals */
/*==========================================================================*/
ULONG memspace_ptr[NUM_PCI_BUSES];
ULONG iospace_ptr[NUM_PCI_BUSES];
ULONG memspace_limit[NUM_PCI_BUSES];
ULONG iospace_limit[NUM_PCI_BUSES];
UINT nextbus;
UINT secondary_busno = SECONDARY_BUS_NUM;
UINT primary_busno = PRIMARY_BUS_NUM;
UINT lastbus;
unsigned long dram_size; /* global storing the size of DRAM */
int bus0_lastbus; /* last secondary bus number behind bus 0 */
int bus1_lastbus; /* last secondary bus number behind bus 1 */
int nmi_verbose; /* global flag to indicate whether or not PCI Error messages should be
printed. This flag is used to prevent a painful deluge of messages
when performing PCI configuration reads/writes to possibly non-existant
devices. */
int pci_config_error = FALSE; /* becomes TRUE if an NMI interrupt occurs due to a PCI config cycle */
#define PRINT_ON() nmi_verbose = TRUE
#define PRINT_OFF() nmi_verbose = FALSE
/*==========================================================================*/
/* Function prototypes */
/*==========================================================================*/
static void sys_pci_bus_init (UINT bus, UINT root_bus, PCI_DATA* pci_data);
void print_config_space (int bus, int device, int function);
void show_pci(void);
void show_bus(int);
void init_312_pci(void);
typedef int (*FUNCPTR) (); /* ptr to function returning int */
typedef struct
{
FUNCPTR handler;
int arg;
int bus;
int device;
} INT_HANDLER;
#define NUM_PCI_XINTS 4 /* XINT0 - XINT3 */
#define MAX_PCI_HANDLERS 8 /* maximum handlers per PCI Xint */
/* Table where the interrupt handler addresses are stored. */
INT_HANDLER pci_int_handlers[4][MAX_PCI_HANDLERS];
extern void printf();
extern void hexIn();
extern int pci_config_cycle;
extern void _enableFiqIrq();
extern void config_ints(void); /* configure interrupts */
/*********************************************************************************
* pci_to_xint - convert a PCI device number and Interrupt line to an 80312 XINT
*
* This function converts a PCI slot number (0 - 7) and an Interrupt line
* (INTA - INTD) to a i960 processor XINT number (0 - 3)
*
* RETURNS: OK or ERROR if arguments are invalid
*
*/
STATUS pci_to_xint(int device, int intpin, int *xint)
{
int device_base; /* all devices mod 4 follow same interrupt mapping scheme */
/* check validity of arguments */
if ((intpin < INTA) || (intpin > INTD) || (device > 31))
return (ERROR);
device_base = device % 4;
/* interrupt mapping scheme as per PCI-to-PCI Bridge Specification */
switch (device_base)
{
case 0:
switch (intpin)
{
case INTA:
*xint = XINT0;
break;
case INTB:
*xint = XINT1;
break;
case INTC:
*xint = XINT2;
break;
case INTD:
*xint = XINT3;
break;
}
break;
case 1:
switch (intpin)
{
case INTA:
*xint = XINT1;
break;
case INTB:
*xint = XINT2;
break;
case INTC:
*xint = XINT3;
break;
case INTD:
*xint = XINT0;
break;
}
break;
case 2:
switch (intpin)
{
case INTA:
*xint = XINT2;
break;
case INTB:
*xint = XINT3;
break;
case INTC:
*xint = XINT0;
break;
case INTD:
*xint = XINT1;
break;
}
break;
case 3:
switch (intpin)
{
case INTA:
*xint = XINT3;
break;
case INTB:
*xint = XINT0;
break;
case INTC:
*xint = XINT1;
break;
case INTD:
*xint = XINT2;
break;
}
break;
}
return (OK);
}
/******************************************************************************
*
* Checks to see if the "bus" argument identifies a PCI bus which is located
* off of the Primary PCI bus of the board.
*/
int off_ppci_bus (int busno)
{
if (busno == primary_busno)
return (TRUE);
else if (busno == secondary_busno)
return (FALSE);
else if (busno <= bus0_lastbus)
return (TRUE);
else
return (FALSE);
}
static unsigned old_abort_vec;
/*************************************************************************
* pci_cycle_cleanup - cleanup after a PCI configuration cycle
*
* This function will clear the various PCI abort bits if a configuration
* cycle to a non-existant device is attempted. Covers both ATU and
* bridge functions.
*
* RETURNS: OK if no PCI abort bits were set or ERROR if abort bits were
* detected.
*/
static int pci_cycle_cleanup (ULONG busno)
{
UINT16 *pci_status_reg16;
UINT16 pci_status16;
UINT32 *pci_status_reg;
UINT32 pci_status;
UINT8 status;
UINT8 bus_select = 0; /* quiet the compiler warning */
pci_status16 = 0;
pci_status = 0;
status = 0;
/* this if-else structure must be done in the correct order to
ensure that the correct ATU is chosen */
if (busno == primary_busno)
bus_select = PRIMARY_BUS_NUM;
else if (busno == secondary_busno)
bus_select = SECONDARY_BUS_NUM;
else if (busno <= bus0_lastbus)
bus_select = PRIMARY_BUS_NUM;
else if (busno <= bus1_lastbus)
bus_select = SECONDARY_BUS_NUM;
else return (ERROR);
/* Read/clear bus status and bus interrupt status registers */
switch (bus_select)
{
case 0: /* Primary Bus */
pci_status_reg16 = (UINT16 *) PATUSR_ADDR;
pci_status16 = *pci_status_reg16;
if ((pci_status16 & 0xF900) == 0) goto skip1;
#ifdef DEBUG_PCI
if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Primary Bus - ATU\n");
if (pci_status16 & SERR_ERROR) printf("P_SERR# Asserted - Primary Bus - ATU\n");
if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Primary Bus - ATU\n");
if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Primary Bus - ATU is master\n");
if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Primary Bus - ATU is target\n");
if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Primary Bus - ATU\n");
#endif
status = 1;
pci_status16 &= 0xF980;
*pci_status_reg16 = pci_status16;
skip1:
pci_status_reg16 = (UINT16 *) PSR_ADDR;
pci_status16 = *pci_status_reg16;
if ((pci_status16 & 0xF900) == 0) goto skip2;
#ifdef DEBUG_PCI
if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Primary Bus - Bridge\n");
if (pci_status16 & SERR_ERROR) printf("P_SERR# Asserted - Primary Bus - Bridge\n");
if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Primary Bus - Bridge\n");
if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Primary Bus - Bridge is master\n");
if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Primary Bus - Bridge is target\n");
if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Primary Bus - Bridge\n");
#endif
status = 1;
pci_status16 &= 0xF980;
*pci_status_reg16 = pci_status16;
skip2:
pci_status_reg = (UINT32 *) PATUISR_ADDR;
pci_status = *pci_status_reg;
if ((pci_status & 0x0000079F) == 0) goto skip3;
#ifdef DEBUG_PCI
if (pci_status & ATU_BIST_ERR) printf("ATU BIST Error - Primary Bus\n");
if (pci_status & IB_MA_ERROR) printf("Internal Bus Master Abort - Primary Bus - ATU\n");
#endif
status = 1;
pci_status &= 0x0000079f;
*pci_status_reg = pci_status;
skip3:
pci_status_reg = (UINT32 *) PBISR_ADDR;
pci_status = *pci_status_reg;
if ((pci_status & 0x0000003F) == 0) goto skip4;
#ifdef DEBUG_PCI
if (pci_status16 & BRIDGE_PERR) printf("Parity Error Detected - Primary Bus - Bridge\n");
if (pci_status16 & SERR_ERROR) printf("P_SERR# Asserted - Primary Bus - Bridge\n");
if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Primary Bus - Bridge\n");
if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Primary Bus - Bridge is master\n");
if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Primary Bus - Bridge is target\n");
if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Primary Bus - Bridge\n");
#endif
status = 1;
pci_status &= 0x0000003F;
*pci_status_reg = pci_status;
skip4:
break;
case 1: /* Secondary Bus */
pci_status_reg16 = (UINT16 *) SATUSR_ADDR;
pci_status16 = *pci_status_reg16;
if ((pci_status16 & 0xF900) == 0) goto skip5;
#ifdef DEBUG_PCI
if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Secondary Bus - ATU\n");
if (pci_status16 & SERR_ERROR) printf("S_SERR# Asserted - Secondary Bus - ATU\n");
if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Secondary Bus - ATU\n");
if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Secondary Bus - ATU is master\n");
if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Secondary Bus - ATU is target\n");
if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Secondary Bus - ATU\n");
#endif
status = 1;
pci_status16 &= 0xF900;
*pci_status_reg16 = pci_status16;
skip5:
pci_status_reg16 = (UINT16 *) SSR_ADDR;
pci_status16 = *pci_status_reg16;
if ((pci_status16 & 0xF900) == 0) goto skip6;
#ifdef DEBUG_PCI
if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Secondary Bus - Bridge\n");
if (pci_status16 & SERR_ERROR) printf("S_SERR# Asserted - Secondary Bus - Bridge\n");
if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Secondary Bus - Bridge\n");
if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Secondary Bus - Bridge is master\n");
if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Secondary Bus - Bridge is target\n");
if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Secondary Bus - Bridge\n");
#endif
status = 1;
pci_status16 &= 0xF980;
*pci_status_reg16 = pci_status16;
skip6:
pci_status_reg = (UINT32 *) SATUISR_ADDR;
pci_status = *pci_status_reg;
if ((pci_status & 0x0000069F) == 0) goto skip7;
#ifdef DEBUG_PCI
if (pci_status & IB_MA_ERROR) printf("Internal Bus Master Abort - Secondary Bus - ATU\n");
#endif
status = 1;
pci_status &= 0x0000069F;
*pci_status_reg = pci_status;
skip7:
break;
default: return (ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -