www.pudn.com > MPC8241BSP.rar > sysLib.c
/* sysLib.c - Motorola PrPMC600 board series system-dependent library */
/* Copyright 1984-2000 Wind River Systems, Inc. */
/* Copyright 1996-2000 Motorola, Inc. All Rights Reserved */
/*
modification history
--------------------
01a,28feb00,rhk created from version 01s, MV2100 BSP.
*/
/*
DESCRIPTION
This library provides board-specific routines. The chip drivers included are:
i8250Sio.c - Intel 8250 UART driver
ppcDecTimer.c - PowerPC decrementer timer library (system clock)
byteNvRam.c - byte-oriented generic non-volatile RAM library
pciConfigLib.c - PCI configuration library
dec2155xCpci.c - Dec/Intel non-transparent PCI-to-PCI bridge library
mpc8240Epic.c - Mpc8240 Interrupt Controller
sysMotI2c.c - Mpc8240 I2C interface driver
INCLUDE FILES: sysLib.h
SEE ALSO:
.pG "Configuration"
*/
/* includes */
#include "vxWorks.h"
#include "pci.h"
#include "memLib.h"
#include "cacheLib.h"
#include "sysLib.h"
#include "config.h"
#include "string.h"
#include "intLib.h"
#include "esf.h"
#include "excLib.h"
#include "logLib.h"
#include "taskLib.h"
#include "vxLib.h"
#include "tyLib.h"
#include "arch/ppc/archPpc.h"
#include "arch/ppc/mmu603Lib.h"
#include "arch/ppc/vxPpcLib.h"
#include "arch/ppc/excPpcLib.h"
#include "private/vmLibP.h"
#include "drv/pci/pciConfigLib.h"
#if 0
# include "pci/pciAutoConfigLib.h"
#else
# include "./pci/pciAutoConfigLib.h"
#endif
void sysMicroDelay(int iDelayUnit);
extern void useI2O(void);
/* defines */
extern int sysStartType;
#define ZERO 0
#define DEFAULT_TAS_CHECKS 10 /* rechecks for soft tas */
#define TAS_CONST 0x80
int pci1200=0;
char mac[6]={0x00,0x11,0x22,0x33,0x44,0x55};
IMPORT void * cookieArray[32];
/* structures */
typedef struct mailboxInfo
{
BOOL connected;
FUNCPTR routine;
int arg;
} MAILBOX_INFO;
typedef struct mpc8240WinStruct
{
UINT32 winType; /* mem or i/o */
UINT32 winBase; /* start of window */
UINT32 winLimit; /* end of window */
} MPC8240_WIN_STRUCT;
/* The following structure is used in the support of distributed shared
* memory interrupt sources. The structure is used to create a linked list
* which contains an entry for each PCI device capable of generating shared
* memory interrupts. When sysIntDisable is called with the shared memory
* interrupt vector, the list of shared memory devices is traversed and
* each device's intDisable routine is called to disable shared memory
* interrupts from that device. Interrupt enable requests are handled in a
* similar manner. The pInfo field is used to save a device-specific
* pointer which could be used to specify the hardware's base address or
* other similar information.
*/
typedef struct sysSmIntDevListEntry
{
struct sysSmIntDevListEntry * next;
void * pInfo;
void (* intEnable) (
void * pInfo,
UINT32 level
);
void (* intDisable) (
void * pInfo,
UINT32 level
);
} SYS_SM_INT_DEV_LIST_ENTRY;
/* globals */
/*
* sysBatDesc[] is used to initialize the block address translation (BAT)
* registers within the PowerPC 603/604 MMU. BAT hits take precedence
* over Page Table Entry (PTE) hits and are faster. Overlap of memory
* coverage by BATs and PTEs is permitted in cases where either the IBATs
* or the DBATs do not provide the necessary mapping (PTEs apply to both
* instruction AND data space, without distinction).
*
* The primary means of memory control for VxWorks is the MMU PTE support
* provided by vmLib and cacheLib. Use of BAT registers will conflict
* with vmLib support. User's may use BAT registers for i/o mapping and
* other purposes but are cautioned that conflicts with cacheing and mapping
* through vmLib may arise. Be aware that memory spaces mapped through a BAT
* are not mapped by a PTE and any vmLib() or cacheLib() operations on such
* areas will not be effective, nor will they report any error conditions.
*
* Note: BAT registers CANNOT be disabled - they are always active.
* For example, setting them all to zero will yield four identical data
* and instruction memory spaces starting at local address zero, each 128KB
* in size, and each set as write-back and cache-enabled. Hence, the BAT regs
* MUST be configured carefully.
*
* With this in mind, it is recommended that the BAT registers be used
* to map LARGE memory areas external to the processor if possible.
* If not possible, map sections of high RAM and/or PROM space where
* fine grained control of memory access is not needed. This has the
* beneficial effects of reducing PTE table size (8 bytes per 4k page)
* and increasing the speed of access to the largest possible memory space.
* Use the PTE table only for memory which needs fine grained (4KB pages)
* control or which is too small to be mapped by the BAT regs.
*
* The BAT configuration for 4xx/6xx-based PPC boards is as follows:
* All BATs point to PROM/FLASH memory so that end customer may configure
* them as required.
*
* [Ref: chapter 7, PowerPC Microprocessor Family: The Programming Environments]
*/
UINT32 sysBatDesc [2 * (_MMU_NUM_IBAT + _MMU_NUM_DBAT)] =
{
/* I BAT 0 */
((ROM_BASE_ADRS & _MMU_UBAT_BEPI_MASK) | (_MMU_UBAT_BL_1M &
~(_MMU_UBAT_VS & _MMU_UBAT_VP))),
((ROM_BASE_ADRS & _MMU_LBAT_BRPN_MASK) | _MMU_LBAT_PP_RW |
_MMU_LBAT_CACHE_INHIBIT),
/* I BAT 1 */
0, 0,
/* I BAT 2 */
0, 0,
/* I BAT 3 */
0, 0,
/* D BAT 0 */
0, 0,
/* D BAT 1 */
0, 0,
/* D BAT 2 */
0, 0,
/* D BAT 3 */
0, 0
};
/*
* sysPhysMemDesc[] is used to initialize the Page Table Entry (PTE) array
* used by the MMU to translate addresses with single page (4k) granularity.
* PTE memory space should not, in general, overlap BAT memory space but
* may be allowed if only Data or Instruction access is mapped via BAT.
*
* Address translations for local RAM, memory mapped PCI bus
* and local PROM/FLASH are set here.
*
* PTEs are held, strangely enough, in a Page Table. Page Table sizes are
* integer powers of two based on amount of memory to be mapped and a
* minimum size of 64 kbytes. The MINIMUM recommended Page Table sizes
* for 32-bit PowerPCs are:
*
* Total mapped memory Page Table size
* ------------------- ---------------
* 8 Meg 64 K
* 16 Meg 128 K
* 32 Meg 256 K
* 64 Meg 512 K
* 128 Meg 1 Meg
* . .
* . .
* . .
*
* [Ref: chapter 7, PowerPC Microprocessor Family: The Programming Environments]
*
*/
PHYS_MEM_DESC sysPhysMemDesc [] =
{
{
/* Vector Table and Interrupt Stack */
(void *) LOCAL_MEM_LOCAL_ADRS,
(void *) LOCAL_MEM_LOCAL_ADRS,
RAM_LOW_ADRS,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE |
VM_STATE_MASK_MEM_COHERENCY,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE |
VM_STATE_MEM_COHERENCY
},
{
/* Local DRAM */
(void *) RAM_LOW_ADRS,
(void *) RAM_LOW_ADRS,
LOCAL_MEM_SIZE - RAM_LOW_ADRS,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE |
VM_STATE_MASK_MEM_COHERENCY,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE |
VM_STATE_MEM_COHERENCY
},
/* Access to PCI ISA I/O space */
{
(void *) ISA_MSTR_IO_LOCAL,
(void *) ISA_MSTR_IO_LOCAL,
ISA_MSTR_IO_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
/* Access to PCI I/O space */
{
(void *) PCI_MSTR_IO_LOCAL,
(void *) PCI_MSTR_IO_LOCAL,
PCI_MSTR_IO_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#ifdef ISA_MEM_SPACE
/* Access to PCI ISA memory space */
{
(void *) ISA_MSTR_MEM_LOCAL,
(void *) ISA_MSTR_MEM_LOCAL,
ISA_MSTR_MEM_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#endif
/* Access to PCI non-prefetchable memory space */
{
(void *) PCI_MSTR_MEMIO_LOCAL,
(void *) PCI_MSTR_MEMIO_LOCAL,
PCI_MSTR_MEMIO_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
/* Access to PCI memory space */
{
(void *) PCI_MSTR_MEM_LOCAL,
(void *) PCI_MSTR_MEM_LOCAL,
PCI_MSTR_MEM_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
/*{
(void *) 0x88000000,
(void *) 0x88000000,
(0x8000000),
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},*/
/* Access to GALNET space */
#ifdef INCLUDE_DEVGALNET
{
(void *) GALNETPCIMEM,
(void *) GALNETPCIMEM,
GALNETMEMSIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#endif
#ifdef INCLUDE_PCI9030
{
(void *) PCI9030EXTFLASHMEM,
(void *) PCI9030EXTFLASHMEM,
PCI9030EXTFLASHSIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#endif
{
/* Mpc8240 registers */
(void *) MPC8240_EUMB_BASE,
(void *) MPC8240_EUMB_BASE,
MPC8240_EUMB_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
/* {*/
/* Mpc8240 registers */
/* (void *) MPC8240_PCSR_BASE,
(void *) MPC8240_PCSR_BASE,
4*1024,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},*/
{
/* PCI interrupt acknowledge */
(void *) PCI_MSTR_IACK_WNDW_ADRS,
(void *) PCI_MSTR_IACK_WNDW_ADRS,
PCI_MSTR_IACK_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#ifdef CHRP_ADRS_MAP
{
/* PCI Configuration Address Register */
(void *) PCI_MSTR_PRIMARY_CAR,
(void *) PCI_MSTR_PRIMARY_CAR,
PCI_MSTR_PRIMARY_CAR_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
{
/* PCI Configuration Data Register */
(void *) PCI_MSTR_PRIMARY_CDR,
(void *) PCI_MSTR_PRIMARY_CDR,
PCI_MSTR_PRIMARY_CDR_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#endif
#ifndef CHRP_ADRS_MAP /* if PReP address map */
{
/* map in direct access of PCI configuration space */
(void *) PCI_MSTR_DIRECT_MAP_ADRS,
(void *) PCI_MSTR_DIRECT_MAP_ADRS,
PCI_MSTR_DIRECT_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
#endif
{
(void *) FLASH_BASE_ADRS,
(void *) FLASH_BASE_ADRS,
FLASH_MEM_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
{
(void *) ROM_BASE_ADRS,
(void *) ROM_BASE_ADRS,
ROM_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},
{
(void *) 0xff000000,
(void *) 0xff000000,
0x1000,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
}
};
UINT wbVectorIRQ0=WBPIC_INTERRUPT_BASE; /*added by xdg*/
int sysPhysMemDescNumEnt = NELEMENTS (sysPhysMemDesc);
int sysBus = BUS_TYPE_PCI; /* system bus type */
int sysCpu = CPU; /* system CPU type (MC680x0) */
char * sysBootLine = BOOT_LINE_ADRS; /* address of boot line */
char * sysExcMsg = EXC_MSG_ADRS; /* catastrophic message area */
int sysProcNum; /* processor number of this CPU */
int sysFlags; /* boot flags */
char sysBootHost [BOOT_FIELD_LEN]; /* name of host from which we booted */
char sysBootFile [BOOT_FIELD_LEN]; /* name of file from which we booted */
UINT sysVectorIRQ0 = INT_VEC_IRQ0; /* vector for IRQ0 */
int smIntArg1 = -1; /* Shared memory SM_INT_ARG1 */
int smIntArg2 = -1; /* Shared memory SM_INT_ARG2 */
MPC8240_WIN_STRUCT sysMpc8240CpuToPciWin[MPC8240_WIN_CNT-1] = { { 0 } };
MPC8240_WIN_STRUCT sysMpc8240PciToCpuWin[MPC8240_WIN_CNT-1] = { { 0 } };
#ifdef INCLUDE_SM_NET
MAILBOX_INFO sysMailbox = {FALSE, NULL, 0};
SYS_SM_INT_DEV_LIST_ENTRY * pSmIntListHead = 0;
#endif
#if defined(SYS_SM_ANCHOR_POLL_LIST) && defined(INCLUDE_DEC2155X)
LOCAL SYS_SM_ANCHOR_POLLING_LIST sysSmAnchorPollList[] =
{
SYS_SM_ANCHOR_POLL_LIST
{ 0xffffffff, 0xffffffff } /* Required entry: marks end of list */
};
#endif
LOCAL int sysSmUtilTasValue = 0; /* special soft tas value */
/* last 5 nibbles are board specific, initialized in sysHwInit */
unsigned char lnEnetAddr [6] = { 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00 };
unsigned char clearWd [1] = { 0x00 };
/* locals */
LOCAL char sysModelStr[80];
LOCAL char wrongCpuMsg[] = WRONG_CPU_MSG;
/* forward declarations */
void sysSpuriousIntHandler(void);
void sysCpuCheck (void);
char * sysPhysMemTop (void);
void sysBusTasClear (volatile char *);
STATUS sysBusProbe (char *, int, int, char *);
IMPORT UINT sysHid1Get(void);
void sysFpSet(ULONG tmp);
void sysDebugMsg(char * str, UINT32 recovery);
UINT sysGetBusSpd(void); /* system bus speed (in megahertz) */
UINT sysGetBusSpdHertz(void); /* system bus speed (in hertz) */
UINT sysGetMpuSpd(void); /* processor speed (in megahertz) */
UINT sysGetMpuSpdHertz(void); /* processor speed (in hertz) */
UINT sysGetPciSpd(void); /* pci bus speed (in megahertz) */
UINT sysGetPciSpdHertz(void); /* pci bus speed (in hertz) */
void led12(unsigned short );
void led11(unsigned short );
void flashled(unsigned short ,unsigned short );
void sysPciInsertLong (UINT32, UINT32, UINT32);
void sysPciInsertWord (UINT32, UINT16, UINT16);
void sysPciInsertByte (UINT32, UINT8, UINT8);
void sysPciOutLongConfirm (UINT32, UINT32);
void sysPciOutWordConfirm (UINT32, UINT16);
void sysPciOutByteConfirm (UINT32, UINT8);
void sysDelay (void);
/* add by zoutl for test 2003-3-28 9:42 */
void testConfigReg(void);
void AddMyexcHandler( void );
/* add by zoutl for test 2003-3-28 9:42 */
#ifdef INCLUDE_PCI9030
void pci9030Init(void);
#endif
#ifdef INCLUDE_SM_NET
LOCAL STATUS sysPciConfig21554InLong (int, int, int, int, UINT32 *);
LOCAL int sysPciConfigPack21554 ( int, int, int, int);
LOCAL void sysSmParamsCompute (void);
int sysSmArg2Compute (void);
# if (SM_OFF_BOARD == TRUE)
# ifdef SYS_SM_ANCHOR_POLL_LIST
LOCAL UINT sysSmAnchorCandidate ( UINT, UINT, UINT);
# endif
LOCAL STATUS sysSmAnchorFind ( int, char **);
LOCAL char *sysSmAnchorPoll (void);
char * sysSmAnchorAdrs (); /* Anchor address (dynamic) */
# endif
#endif /* INCLUDE_SM_NET */
/* externals */
IMPORT UCHAR sysInByte (ULONG);
IMPORT void sysOutByte (ULONG, UCHAR);
IMPORT USHORT sysInWord (ULONG);
IMPORT void sysOutWord (ULONG, USHORT);
IMPORT ULONG sysInLong (ULONG);
IMPORT void sysOutLong (ULONG, ULONG);
IMPORT UINT32 sysPciInLong (UINT32);
IMPORT void sysPciOutLong (UINT32, UINT32);
IMPORT UINT8 sysPciConfigInByte (UINT8 * dataPtr);
IMPORT UINT32 sysPciConfigInLong (UINT32 *);
IMPORT void sysPciConfigOutLong (UINT32 *, UINT32);
IMPORT UINT16 sysPciConfigInWord (UINT16 *);
IMPORT void sysPciConfigOutWord (UINT16 *, UINT16);
IMPORT void sysClkIntCIO (void);
IMPORT STATUS sysMemProbeSup (int length, char * src, char * dest);
IMPORT int sysProbeExc();
IMPORT VOIDFUNCPTR smUtilTasClearRtn;
IMPORT void sysBusRmwEnable(UINT, UINT, UINT, char *);
IMPORT void sysBusRmwDisable(void);
IMPORT UINT32 sysTimeBaseLGet (void);
IMPORT UCHAR sysProductStr[];
IMPORT UINT32 sysInLongRev ( UINT32);
IMPORT void sysOutLongRev (UINT32, UINT32);
IMPORT UINT16 sysInWordRev (UINT32);
IMPORT void sysOutWordRev (UINT32, UINT16);
/* BSP DRIVERS */
#include "pci/pciConfigLib.c"
#include "sysSerial.c"
#include "mem/nullNvRam.c"
#include "timer/ppcDecTimer.c" /* PPC603 has on chip timers */
/* add by zoutl for NVRam & double boot 2003-4-21 19:01 */
/* delete by wanggeng 20050729
#include "../../Modules/DoubleBoot/xpbConI2c.c"
#include "../../Modules/DoubleBoot/xpbConEeprom.c"
#include "../../Modules/DoubleBoot/BootRomDrv.c"
*/
#ifdef INCLUDE_NETWORK
# include "sysNet.c"
# ifdef INCLUDE_END
# ifdef INCLUDE_RTL_81X9_END
# include "sysRtl81x9End.c"
# include "rtl81x9.c"
# endif /* INCLUDE_RTL_81X9_END */ /*INCLUDE_RTL_81X9_END is added by mashuyu*/
# ifdef INCLUDE_RTL_CP_END
# include "rtlcpp.c"
# include "sysRtlcpEnd.c"
# include "rtl8139Config.c"
# endif
# endif /* INCLUDE_END */
#endif /* INCLUDE_NETWORK */
#ifdef INCLUDE_SHOW_ROUTINES
#include "pci/pciConfigShow.c" /* display of PCI config space */
#endif
#ifdef INCLUDE_SCSI
# include "sysScsi.c" /* sysScsiInit routine */
#endif /* INCLUDE_SCSI */
#ifdef INCLUDE_TFFS
# include "i28f640.c"
# include "p755-sysTffs.c"
# include "trueFFS.c" /* tffs routine */
#endif /* INCLUDE_TFFS */
#include "mpc8240Epic.c"
#ifdef INCLUDE_AUXCLK
# include "mpc8240AuxClk.c"
#endif
/* add by zoutl for test BSP 2003-5-30 14:31 */
#ifdef BSP_TEST
# include "./test/mpc8240AuxClk1.c"
# include "./test/NetTest.c"
#endif
#if 0
# include "pci/pciAutoConfigLib.c"
#else
# include "./pci/pciAutoConfigLib.c"
#endif
# include "./sysBusPci.c"
#include "i2o.c"
#include "i2c.c"
#include "flash.c"
#include "pciAddrAlloc.c"
/* delete by wanggeng 20050729
#include "BspCpusApi.c"
*/
/*#include "rtc.c"*/
/*#include "dma.c"*/
/*#include "testfile.c"*/
/* defines for sysBusTas() and sysBusTasClear() */
#define CPU_CLOCKS_PER_LOOP 10
#define LOCK_TIMEOUT 10
#define UNLOCK_TIMEOUT 10000
/******************************************************************************
*
* sysModel - return the model name of the CPU board
*
* This routine returns the model name of the CPU board. The returned string
* depends on the board model and CPU version being used, for example,
* "Motorola MVME2600 - MPC 604e".
*
* RETURNS: A pointer to the string.
*/
char * sysModel (void)
{
int cpu;
char cpuStr[80];
/* Determine CPU type and build display string */
cpu = CPU_TYPE;
switch (cpu)
{
case CPU_TYPE_603EK:
sprintf(cpuStr, "8240");
break;
default:
sprintf (cpuStr, "60%d", cpu);
break;
}
sprintf (sysModelStr, "ZTE CDMA LPB %s", cpuStr);
return (sysModelStr);
}
/*******************************************************************************
*
* sysBspRev - return the BSP version and revision number
*
* This routine returns a pointer to a BSP version and revision number, for
* example, 1.1/0. BSP_REV is concatenated to BSP_VERSION and returned.
*
* RETURNS: A pointer to the BSP version/revision string.
*/
char * sysBspRev (void)
{
return (BSP_VERSION BSP_REV);
}
/*******************************************************************************
* sysDecDelay - decrementer delay
*
* This function's purpose is delay for the specified number
* micro-seconds.
*
* RETURNS: none
*/
void sysDecDelay
(
UINT usDelay
)
{
UINT oneUsDelta;
UINT valueCurrent, valuePrevious, valueDelta;
/* if no delay count, exit */
if (!usDelay)
return;
/*
* calculate delta of decrementer ticks for 1ms of elapsed time,
* the bus clock (in megahertz) is used for 603/604 versions, the
* decrementer counts down once every four bus clocks for the
* 603/604 versions, and once every RTC tick for the 601, the RTC
* tick for 601 is the period of 1ns
*/
oneUsDelta = ((DEC_CLOCK_FREQ / 4) / 1000000);
/*
* snapshot current decrementer count, this count is used
* as the starting point
*
* check for rollover, the decrementer counts down from
* the maximum count (0xffffffff) to zero
*
* calculate delta of the decrementer counts and divide
* down by the one MS divider, exit if count has been
* met or exceeded
*/
for (valuePrevious = vxDecGet();;)
{
valueCurrent = vxDecGet();
valueDelta = 0;
if (valueCurrent > valuePrevious)
{
valueDelta = (0xFFFFFFFF - valueCurrent) + valuePrevious;
}
else
{
if (valueCurrent < valuePrevious)
{
valueDelta = valuePrevious - valueCurrent;
}
}
if ((valueDelta / oneUsDelta) >= usDelay)
break;
}
}
/******************************************************************************
*
* sysHwInit - initialize the system hardware
*
* This routine initializes various features of the CPU board. It is called
* by usrInit() in usrConfig.c. This routine sets up the control registers
* and initializes various devices if they are present.
*
* NOTE: This routine should not be called directly by the user application. It
* cannot be used to initialize interrupt vectors.
*
* RETURNS: N/A
*/
void sysHwInit (void)
{
/* Validate CPU type */
sysCpuCheck();
/*12.30 for 64bit opt*/
#if(1)
sysFpSet(0);
#endif
/* 写EUMB寄存器 Added by xdg*/
/* 参数中前者是需要写到PCI配置地址寄存器的值,后者是需要写到PCI配置数据寄存器的值*/
sysPciConfigOutLong ( (UINT32*)(CNFG_PCI_HOST_BRDG+MPC8240_CFG_EUMBBAR), \
(UINT32)MPC8240_EUMB_BASE );
sysPciConfigOutLong ( (UINT32*)(CNFG_PCI_HOST_BRDG+0xD0), \
(UINT32)0x85080000 );
sysPciConfigOutLong ( (UINT32*)(CNFG_PCI_HOST_BRDG+0xD8), \
(UINT32)0x0000000B );
/*
* If mmu tables are used, this is where we would dynamically
* update the entry describing main memory, using sysPhysMemTop().
* We must call sysPhysMemTop () at sysHwInit() time to do
* the memory autosizing if available.
*/
sysPhysMemTop ();
/* add by zoutl 2003-5-24 10:32 */
#ifdef BOOT_DEBUG_MSG
sysDebugMsg("sysPhysMemTop succeed!\n\r",0);
#endif
/* Initialize PCI driver library. */
if (pciConfigLibInit (PCI_MECHANISM_1, PCI_MSTR_PRIMARY_CAR,
PCI_MSTR_PRIMARY_CDR, 0) != OK)
{
sysToMonitor (BOOT_NO_AUTOBOOT);
}
/* Auto-Configure the PCI busses/devices. */
/*
* Test to determine if we need to configure the PCI busses with
* sysPciAutoConfig(). If we are coming up from a ROM-based image
* then we need to reconfigure. If we have been booted from a ROM
* image then we don't need to reconfigure since the bootrom will
* already have reconfigured the PCI busses. We must avoid
* configuring the PCI busses twice on startup.
*/
if ( !PCI_AUTOCONFIG_DONE )
{pci1200=1;
}
if(1)
{
/* in ROM boot phase, OK to continue and configure PCI busses.*/
sysPciAutoConfig ();
PCI_AUTOCONFIG_FLAG++; /* Remember that PCI is configured */
}
/* add by zoutl 2003-5-24 10:32 */
#ifdef BOOT_DEBUG_MSG
sysDebugMsg("sysPciAutoConfig succeed!\n\r",0);
#endif
/* Initialize the EPIC. */
sysEpicInit();
/* add by zoutl 2003-5-24 10:32 */
#ifdef BOOT_DEBUG_MSG
sysDebugMsg("sysEpicInit succeed!\n\r",0);
#endif
/* set pointer to bus probing hook */
_func_vxMemProbeHook = (FUNCPTR)sysBusProbe;
/* Initialize COM1 and COM2 serial channels */
/*pciConfigOutLong (0, 21, 0, 0x18, 0x88000000); */
sysSerialHwInit();
/* add by zoutl 2003-5-24 10:32 */
#ifdef BOOT_DEBUG_MSG
sysDebugMsg("sysSerialHwInit succeed!\n\r",0);
#endif
#ifdef INCLUDE_NETWORK
/* Initialize the network */
sysNetHwInit();
/* add by zoutl 2003-5-24 10:32 */
#ifdef BOOT_DEBUG_MSG
sysDebugMsg("sysNetHwInit succeed!\n\r",0);
#endif
#endif
/*#ifdef INCLUDE_PCI9030
pci9030Init();
#endif*/
}
/*******************************************************************************
*
* sysPhysMemTop - get the address of the top of physical memory
*
* This routine returns the address of the first missing byte of memory,
* which indicates the top of memory.
*
* Normally, the user specifies the amount of physical memory with the
* macro LOCAL_MEM_SIZE in config.h. BSPs that support run-time
* memory sizing do so only if the macro LOCAL_MEM_AUTOSIZE is defined.
* If not defined, then LOCAL_MEM_SIZE is assumed to be, and must be, the
* true size of physical memory.
*
* NOTE: Do no adjust LOCAL_MEM_SIZE to reserve memory for application
* use. See sysMemTop() for more information on reserving memory.
*
* RETURNS: The address of the top of physical memory.
*
* SEE ALSO: sysMemTop()
*/
char * sysPhysMemTop (void)
{
static char * sysPhysMemSize = NULL; /* ptr to top of mem + 1 */
if (sysPhysMemSize == NULL)
{
/* Don't do auto-sizing, use defined constants. */
sysPhysMemSize = (char *)(LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE);
}
return sysPhysMemSize;
}
/*******************************************************************************
*
* sysMemTop - get the address of the top of VxWorks memory
*
* This routine returns a pointer to the first byte of memory not
* controlled or used by VxWorks.
*
* The user can reserve memory space by defining the macro USER_RESERVED_MEM
* in config.h. This routine returns the address of the reserved memory
* area. The value of USER_RESERVED_MEM is in bytes.
*
* RETURNS: The address of the top of VxWorks memory.
*/
char * sysMemTop (void)
{
static char * memTop = NULL;
if (memTop == NULL)
{
memTop = sysPhysMemTop () - USER_RESERVED_MEM;
}
return memTop;
}
/******************************************************************************
*
* sysToMonitor - transfer control to the ROM monitor
*
* This routine transfers control to the ROM monitor. Normally, it is called
* only by reboot()--which services ^X--and by bus errors at interrupt level.
* However, in some circumstances, the user may wish to introduce a
* to enable special boot ROM facilities.
*
* RETURNS: Does not return.
*/
STATUS sysToMonitor
(
int startType /* parameter passed to ROM to tell it how to boot */
)
{
FUNCPTR pRom = (FUNCPTR) (ROM_TEXT_ADRS + 4); /* Warm reboot */
cacheDisable (0); /* Disable the Instruction Cache */
cacheDisable (1); /* Disable the Data Cache */
#if (CPU == PPC604)
vxHid0Set (vxHid0Get () & ~_PPC_HID0_SIED); /* Enable Serial Instr Exec */
#endif /* (CPU == PPC604) */
sysSerialReset (); /* reset serial devices */
/* Clear the MSR */
vxMsrSet (0);
/* Reset the EPIC */
sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, EPIC_GC_RESET);
/*7.28*/
#if(0)
/* set the Board Fail LED */
*(UINT8 *)PRPMC600_SYS_STAT_REG2 |= PRPMC600_BD_FAIL;
#endif
(*pRom) (startType);
return (OK); /* in case we ever continue from ROM monitor */
}
/******************************************************************************
*
* sysHwInit2 - initialize additional system hardware
*
* This routine connects system interrupt vectors and configures any
* required features not configured by sysHwInit().
*
* RETURNS: N/A
*/
void sysHwInit2 (void)
{
static BOOL configured = FALSE;
/* Int connects for various devices */
if (!configured)
{
#ifdef INCLUDE_AUXCLK
sysAuxClkInit ();
intConnect (INUM_TO_IVEC(TIMER0_INT_VEC), sysAuxClkInt, 0);
intEnable (TIMER0_INT_LVL);
#endif /* INCLUDE_AUXCLK */
/* add by zoutl for BSP test 2003-5-30 14:31 */
#ifdef BSP_TEST
sysAuxClk1Init();
/* add by zoutl for really enable interrupt */
intConnect (INUM_TO_IVEC((int)TIMER1_INT_LVL),sysAuxClk1Int, (int) 0);
intEnable (TIMER1_INT_LVL);
#endif
/* initialize serial interrupts */
sysSerialHwInit2();
/*in sysnet.c*/
#ifdef INCLUDE_NETWORK
/* configure the interrupts for the network hardware. */
sysNetHwInit2 ();
#endif
#ifdef INCLUDE_SM_NET
sysSmParamsCompute ();
#endif
configured = TRUE;
}
}
/******************************************************************************
*
* sysProcNumGet - get the processor number
*
* This routine returns the processor number for the CPU board, which is
* set with sysProcNumSet().
*
* RETURNS: The processor number for the CPU board.
*
* SEE ALSO: sysProcNumSet()
*/
int sysProcNumGet (void)
{
return (sysProcNum);
}
/******************************************************************************
*
* sysProcNumSet - set the processor number
*
* This routine sets the processor number for the CPU board. Processor numbers
* should be unique on a single backplane. It also maps local resources onto
* the VMEbus.
*
* RETURNS: N/A
*
* SEE ALSO: sysProcNumGet()
*
*/
void sysProcNumSet
(
int procNum /* processor number */
)
{
/* Init the global variable */
sysProcNum = procNum;
}
/* miscellaneous support routines */
/******************************************************************************
*
* sysMpc8240TransAdrs - translate an address that passes through the mpc8240.
*
* This routine converts an address from a cpu to pci address or vice versa. It
* uses a pair of window arrays built during hardware init2 to guide the
* translation. The adrs parameter is the address to convert.
*
* RETURNS: OK, or ERROR if the address space is unknown or the mapping is not
* possible.
*
* SEE ALSO: sysMpc8240Capt()
*
*/
LOCAL STATUS sysMpc8240TransAdrs
(
UINT32 adrsSpace, /* address space (memory or i/o ) */
UINT32 adrs, /* known address */
UINT32 * pTransAdrs, /* pointer to the translated address */
UINT32 winCnt, /* number of open windows */
MPC8240_WIN_STRUCT * pSrc, /* pointer to the source windows */
MPC8240_WIN_STRUCT * pDest /* pointer to the destination windows */
)
{
while (winCnt--)
{
/* check for a match on window type and in bounds */
if ( (pSrc->winType == adrsSpace) &&
(adrs >= pSrc->winBase) &&
(adrs <= pSrc->winLimit) )
{
*pTransAdrs = ( adrs - pSrc->winBase + pDest->winBase );
return (OK);
};
/* advance to next window */
pSrc++;
pDest++;
}
/*
* no window was found to contain adrs. indicate that translation was
* not possible.
*/
return (ERROR);
}
/******************************************************************************
*
* sysCpuToPciAdrs - translate a cpu address to a pci bus address
*
* This routine converts an address as seen from the cpu to the equivalent pci
* address, if it exists. The input address is the address as seen by the cpu.
*
* RETURNS: OK, or ERROR if the address space is unknown or the mapping is not
* possible.
*
* SEE ALSO: sysPciToCpuAdrs()
*/
LOCAL STATUS sysCpuToPciAdrs
(
int adrsSpace, /* bus address space where busAdrs resides */
char * localAdrs, /* local address to convert */
char ** pBusAdrs /* where to return bus address */
)
{
return (sysMpc8240TransAdrs (adrsSpace, (UINT32)localAdrs,
(UINT32 *)pBusAdrs, MPC8240_WIN_CNT,
&sysMpc8240CpuToPciWin[0],
&sysMpc8240PciToCpuWin[0]) );
}
/******************************************************************************
*
* sysPciToCpuAdrs - translate a pci bus address to a cpu address
*
* This routine converts an address as seen from the pci bus to the equivalent
* cpu address, if it exists. The input address is the address as seen by the
* pci bus.
*
* RETURNS: OK, or ERROR if the address space is unknown or the mapping is not
* possible.
*
* SEE ALSO: sysCpuToPciAdrs()
*/
LOCAL STATUS sysPciToCpuAdrs
(
int adrsSpace, /* bus address space where busAdrs resides */
char * localAdrs, /* local address to convert */
char ** pBusAdrs /* where to return bus address */
)
{
return (sysMpc8240TransAdrs (adrsSpace, (UINT32)localAdrs,
(UINT32 *)pBusAdrs, MPC8240_WIN_CNT,
&sysMpc8240PciToCpuWin[0],
&sysMpc8240CpuToPciWin[0]) );
}
/******************************************************************************
*
* sysLocalToBusAdrs - convert a local CPU address to a PCI bus address
*
* Given a CPU address, this routine returns a corresponding local PCI bus
* or Compact (backpanel) PCI bus address provided that such an address exists.
* The target PCI bus (local or backpanel) is selected by the adrsSpace
* parameter. Legal values for this parameter are found in "pci.h". If a
* transparent bridge is used to access the Compact PCI bus, the local PCI bus
* and the backpanel PCI bus share the same address space. In this case, the
* local and backpanel address space designators are synonomous.
*
* RETURNS: OK, or ERROR if the address space is unknown or the mapping is not
* possible.
*
* SEE ALSO: sysBusToLocalAdrs()
*/
STATUS sysLocalToBusAdrs
(
int adrsSpace, /* bus address space where busAdrs resides */
char * localAdrs, /* local address to convert */
char ** pBusAdrs /* where to return bus address */
)
{
switch (adrsSpace)
{
case PCI_SPACE_IO_PRI:
case PCI_SPACE_IO_SEC:
/* convert from cpu address space to local pci space */
if ( sysCpuToPciAdrs (PCI_BAR_SPACE_IO, localAdrs, pBusAdrs) != OK )
return (ERROR);
#ifdef INCLUDE_DEC2155X
/*
* if continuing on to the backpanel using the dec2155x, translate
* from local pci space to compact pci space.
*/
if ( PCI_SPACE_IS_CPCI(adrsSpace) )
return ( sysPciToCpciAdrs (PCI_BAR_SPACE_IO, *pBusAdrs,
pBusAdrs) );
#endif /* INCLUDE_DEC2155X */
break;
case PCI_SPACE_MEMIO_PRI:
case PCI_SPACE_MEM_PRI:
case PCI_SPACE_MEMIO_SEC:
case PCI_SPACE_MEM_SEC:
/* convert from cpu address space to local pci address space */
if (sysCpuToPciAdrs (PCI_BAR_SPACE_MEM, localAdrs, pBusAdrs) != OK )
return (ERROR);
#ifdef INCLUDE_DEC2155X
/*
* if continuing on to the backpanel using the dec2155x, translate
* from local pci space to compact pci space.
*/
if ( PCI_SPACE_IS_CPCI(adrsSpace) )
return ( sysPciToCpciAdrs(PCI_BAR_SPACE_MEM, *pBusAdrs,
pBusAdrs) );
#endif /* INCLUDE_DEC2155X */
break;
default:
return (ERROR);
break;
}
return (OK);
}
/******************************************************************************
*
* sysBusToLocalAdrs - convert a PCI bus address to a local CPU address
*
* Given a local or Compact (backpanel) PCI address, this routine returns a
* corresponding local CPU bus address provided such an address exists. The
* originating PCI bus (local or backpanel) is selected by the adrsSpace
* parameter. Legal values for this parameter are found in "pci.h". If a
* transparent bridge is used to access the Compact PCI bus, the local PCI bus
* and the Compact PCI bus share the same address space. In this case, the
* local and backpanel address space designators are synonomous.
*
* RETURNS: OK, or ERROR if the address space is unknown or the mapping is not
* possible.
*
* SEE ALSO: sysLocalToBusAdrs()
*/
STATUS sysBusToLocalAdrs
(
int adrsSpace, /* bus address space where busAdrs resides */
char * busAdrs, /* bus address to convert */
char ** pLocalAdrs /* where to return local address */
)
{
switch (adrsSpace)
{
case PCI_SPACE_IO_SEC:
#ifdef INCLUDE_DEC2155X
/*
* translate from compact PCI address space to local PCI address
* space.
*/
if ( sysCpciToPciAdrs (PCI_BAR_SPACE_IO, busAdrs, &busAdrs) != OK )
return (ERROR);
/* fall through */
#endif /* INCLUDE_DEC2155X */
case PCI_SPACE_IO_PRI:
/*
* translate from local PCI address space to CPU address
* space.
*/
return ( sysPciToCpuAdrs (PCI_BAR_SPACE_IO, busAdrs, pLocalAdrs) );
break;
case PCI_SPACE_MEMIO_SEC:
case PCI_SPACE_MEM_SEC:
#ifdef INCLUDE_DEC2155X
/*
* translate from compact PCI address space to local PCI address
* space.
*/
if ( sysCpciToPciAdrs (PCI_BAR_SPACE_MEM, busAdrs, &busAdrs) != OK)
return (ERROR);
/* fall through */
#endif /* INCLUDE_DEC2155X */
case PCI_SPACE_MEMIO_PRI:
case PCI_SPACE_MEM_PRI:
/*
* translate from local PCI address space to CPU address
* space.
*/
return (sysPciToCpuAdrs (PCI_BAR_SPACE_MEM, busAdrs, pLocalAdrs) );
break;
default:
return (ERROR);
break;
}
}
/*******************************************************************************
*
* sysBusTas - test and set a location across the bus
*
* The cPCI bridge chips do not support PCI target locking, therefore there is
* no atomic RMW operation. This routine performs a software-based mutual
* exclusion algorithm in place of a true test and set.
*
* NOTE: This algorithm is performed through a PCI-to-PCI bridge to a shared
* location that is subject to unprotected access by multiple simultaneous
* processors. There is the possibility that the bridge will deliver a delayed
* read completion to a PCI bus master which was not the original initiator of
* the delayed read. The bridge delivers the delayed read completion to the new
* requestor because it believes that the new delayed read request is actually
* the original master performing a delayed read retry as required by the PCI
* spec. When the original master comes back with the genuine retry, the bridge
* treats it as a new request. When this "aliasing" occurs, a read performed
* after a write can appear to complete ahead of the write, which is in violation
* of PCI transaction ordering rules. Since this algorithm depends on a strict
* time-ordered sequence of operations, it can deadlock under this condition.
* To prevent the deadlock, a throw-away read must be performed after the initial
* write. Since the bridge only remembers once instance of a queued delayed
* read request, the throw-away read will "consume" the results of a
* mis-directed read completion and subsequent read requests are guaranteed to
* be queued and completed after the write.
*
* RETURNS: TRUE if lock acquired.
* FALSE if lock not acquired.
*
* SEE ALSO: sysBusTasClear()
*/
BOOL sysBusTas
(
char * adrs /* address to be tested and set */
)
{
FAST int value; /* value to place in lock variable */
FAST int nChecks; /* number of times to re-check lock */
FAST int count; /* running count of re-checks */
int oldLvl; /* previous interrupt level */
volatile int * lockAdrs = (int *)adrs;
if (sysSmUtilTasValue == 0)
sysSmUtilTasValue = (TAS_CONST + sysProcNumGet ())<< 24;
value = sysSmUtilTasValue; /* special value to write */
nChecks = DEFAULT_TAS_CHECKS; /* number of checks to do */
/* Lock out interrupts */
oldLvl = intLock ();
/* Test that lock variable is initially empty */
if (*lockAdrs != 0)
{
intUnlock (oldLvl);
return (FALSE); /* someone else has lock */
}
/* Set lock value */
*lockAdrs = value;
/* Perform a preliminary read due to PCI bridge issues */
count = *lockAdrs;
/* Check that no one else is trying to take lock */
for (count = 0; count < nChecks; count++)
{
if (*lockAdrs != value)
{
intUnlock (oldLvl);
return (FALSE); /* someone else stole lock */
}
}
intUnlock (oldLvl);
return (TRUE); /* exclusive access obtained */
}
/******************************************************************************
*
* sysBusTasClear - clear a location set by sysBusTas()
*
* This routine clears a bus test and set location. This routine is only
* required if the sysBusTas() routine uses special semaphore techniques (such
* as bus locking). Since the sysBusTas routine doesn't use any special
* semaphore techniques, this routine is a no-op.
*
* If used, the BSP activates this routine by placing its address into the
* global variable 'smUtilTasClearRtn'.
*
* RETURNS: N/A
*
* SEE ALSO: sysBusTas()
*/
void sysBusTasClear
(
volatile char * address /* address to be tested-and-cleared */
)
{
}
/******************************************************************************
*
* sysSpuriousIntHandler - spurious interrupt handler
*
* This is the entry point for spurious interrupts.
*
* NOTE: This routine has no effect.
*
* This routine catches all spurious interrupts. It does nothing at all.
*
* RETURNS: N/A.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void sysSpuriousIntHandler (void)
{
}
/*******************************************************************************
*
* sysCpuCheck - confirm the CPU type
*
* This routine validates the cpu type. If the wrong cpu type is discovered
* a message is printed using the serial channel in polled mode.
*
* RETURNS: N/A.
*/
void sysCpuCheck (void)
{
int msgSize;
int msgIx;
SIO_CHAN * pSioChan; /* serial I/O channel */
/* Check for a valid CPU type; If one is found, just return */
if ((CPU_TYPE == CPU_TYPE_603) || (CPU_TYPE == CPU_TYPE_603E) ||(CPU_TYPE == CPU_TYPE_8245)||
(CPU_TYPE == CPU_TYPE_603P) || (CPU_TYPE == CPU_TYPE_603EK)||(CPU_TYPE == CPU_TYPE_750))
{
/*flashled(2,2);*/
return;
}
/* Invalid CPU type; print error message and terminate */
msgSize = strlen (wrongCpuMsg);
/* flashled(2,5);*/
sysSerialHwInit ();
pSioChan = sysSerialChanGet (0);
sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL);
for (msgIx = 0; msgIx < msgSize; msgIx++)
{
while (sioPollOutput (pSioChan, wrongCpuMsg[msgIx]) == EAGAIN);
}
sysToMonitor (BOOT_NO_AUTOBOOT);
}
/******************************************************************************
*
* sysMemProbeTrap - trap handler for vxMemProbe exception
*
* This routine is called from the excConnectCode stub if sysMemProbeSup
* generates an exception. By default, sysMemProbeSup returns OK.
* This code changes the PC value to "sysProbeExc" (within the sysMemProbeSup
* routine), and sysProbeExc sets the return value to ERROR.
*/
static int sysMemProbeTrap
(
ESFPPC * pEsf /* pointer to exception stack frame */
)
{
REG_SET *pRegSet = &pEsf->regSet;
pRegSet->pc = (_RType)sysProbeExc; /* sysProbeExc forces an ERROR return */
return (0);
}
/******************************************************************************
*
* sysMemProbeBus - probe an address on a bus.
*
* This routine probes a specified address to see if it is readable or
* writable, as specified by . The address will be read or written as
* 1, 2, or 4 bytes as specified by (values other than 1, 2, or 4
* yield unpredictable results). If the probe is a VX_READ, the value read will
* be copied to the location pointed to by . If the probe is a VX_WRITE,
* the value written will be taken from the location pointed to by .
* In either case, should point to a value of 1, 2, or 4 bytes, as
* specified by .
*
* This routine probes the specified address with interrupts disabled and
* a special handler for Machine Check, Data Access and Alignment exceptions.
*
* RETURNS: OK if probe succeeded or ERROR if an exception occured.
*/
static STATUS sysMemProbeBus
(
char * adrs, /* address to be probed */
int mode, /* VX_READ or VX_WRITE */
int length, /* 1, 2 or 4 byte probe */
char * pVal /* address of value to write OR */
/* address of location to place value read */
)
{
int oldLevel;
FUNCPTR oldVec1;
FUNCPTR oldVec2;
STATUS status;
UINT32 ppcHid0; /* H/W Implementation Dependent reg (PPC60x) */
UINT32 ppcMsr; /* PPC Machine Status Reg */
UINT16 temp;
/* Probes performed with interrupts disabled */
oldLevel = intLock ();
/* Handle Machine Check Exceptions locally */
oldVec1 = excVecGet ((FUNCPTR *) _EXC_OFF_MACH);
excVecSet ((FUNCPTR *) _EXC_OFF_MACH, FUNCREF(sysMemProbeTrap));
/*
* Handle Data Access Exceptions locally
*
* Data Access Exceptions will occur when trying to probe addresses
* that have not been mapped by the MMU.
*/
oldVec2 = excVecGet ((FUNCPTR *) _EXC_OFF_DATA);
excVecSet ((FUNCPTR *) _EXC_OFF_DATA, FUNCREF(sysMemProbeTrap));
/* Enable Machine Check Pin (EMCP) */
ppcHid0 = vxHid0Get();
vxHid0Set(ppcHid0 | _PPC_HID0_EMCP);
/* Enable Machine Check exception */
ppcMsr = vxMsrGet();
vxMsrSet(ppcMsr | _PPC_MSR_ME);
/* clear the PCI abort bits in the PCI status word */
sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + MPC8240_CFG_STATUS),
(MPC8240_PCI_RCV_MSTR_ABORT | MPC8240_PCI_RCV_TGT_ABORT));
/* do probe */
if (mode == VX_READ)
{
status = sysMemProbeSup (length, adrs, pVal);
SYNC;
}
else
{
status = sysMemProbeSup (length, pVal, adrs);
SYNC;
}
/* check for valid address */
temp = sysPciConfigInWord((UINT16 *)(CNFG_PCI_HOST_BRDG +
MPC8240_CFG_STATUS));
if (temp & (MPC8240_PCI_RCV_MSTR_ABORT | MPC8240_PCI_RCV_TGT_ABORT))
status = ERROR;
/* clear the PCI status reg. bits */
sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + MPC8240_CFG_STATUS),
(MPC8240_PCI_RCV_MSTR_ABORT | MPC8240_PCI_RCV_TGT_ABORT));
/* Disable Machine Check Exceptions */
vxMsrSet(ppcMsr);
/* Disable Machine Check Pin (EMCP) */
vxHid0Set(ppcHid0);
/* restore original vectors and unlock */
excVecSet ((FUNCPTR *) _EXC_OFF_DATA, oldVec2);
excVecSet ((FUNCPTR *) _EXC_OFF_MACH, oldVec1);
intUnlock (oldLevel);
return (status);
}
/******************************************************************************
*
* sysProbeErrClr - clear errors associated with probing an address on a bus.
*
* This routine clears the error flags and conditions in the DAR, DSISR, SRR0
* and SRR1 PowerPC registers arising from probing addresses as well as the
* PCI_CFG_STATUS registers and the Universe PCI_CSR and V_AMERR registers.
*
* RETURNS: N/A
*/
void sysProbeErrClr (void)
{
/* Clear PowerPC Data Access Exception Registers */
vxDarSet (0);
vxDsisrSet (0);
vxSrr0Set (0);
vxSrr1Set (0);
}
/******************************************************************************
*
* sysPciProbe - probe a PCI bus address
*
* This routine probes an address on the PCI bus. The PCI bridge chip
* must have a special setup to enable generation of Master Abort cycles on
* write probes and reception of Target Abort cycles on read probes.
* The CPU must be configured to enable Machine Check exceptions. In
* addition, if the probe is a write, the Universe must be configured to
* disable Posted Writes. All probing is done with interrupts disabled.
*
* RETURNS: OK or ERROR if address cannot be probed
*/
STATUS sysPciProbe
(
char * adrs, /* address to be probed */
int mode, /* VX_READ or VX_WRITE */
int length, /* 1, 2 or 4 byte probe */
char * pVal /* address of value to write OR */
/* address of location to place value read */
)
{
STATUS status = ERROR;
/* Perform probe */
status = sysMemProbeBus (adrs, mode, length, pVal);
return (status);
}
/******************************************************************************
*
* sysBusProbe - probe a bus address based on bus type.
*
* This routine is a function hook into vxMemProbe. It determines which bus,
* PCI or local is being probed based on the address to be probed.
* If the PCI bus is being probed, the sysPciProbe() routine is called to do the
* special PCI probing. If the local bus is being probed, the routine calls an
* architecture-specific probe routine.
*
* RETURNS: ERROR if the probed address does not respond or causes a MMU fault.
* Returns OK if the probed address responds.
*/
STATUS sysBusProbe
(
char * adrs, /* address to be probed */
int mode, /* VX_READ or VX_WRITE */
int length, /* 1, 2 or 4 byte probe */
char * pVal /* address of value to write OR */
/* address of location to place value read */
)
{
STATUS status;
/* Clear any existing errors/exceptions */
sysProbeErrClr ();
/* Handle PCI bus in special manner */
if (IS_PCI_ADDRESS(adrs))
status = sysPciProbe (adrs, mode, length, pVal);
/* Handle local bus in architecture-specific manner */
else
status = vxMemArchProbe (adrs, mode, length, pVal);
/* Clear any errors/exceptions before exiting */
sysProbeErrClr ();
return (status);
}
/******************************************************************************
*
* sysUsDelay - delay at least the specified amount of time (in microseconds)
*
* This routine will delay for at least the specified amount of time using the
* lower 32 bit "word" of the Time Base register as the timer. The accuracy of
* the delay increases as the requested delay increases due to a certain amount
* of overhead. As an example, a requested delay of 10 microseconds is
* accurate within approximately twenty percent, and a requested delay of 100
* microseconds is accurate within approximately two percent.
*
* NOTE: This routine will not relinquish the CPU; it is meant to perform a
* busy loop delay. The minimum delay that this routine will provide is
* approximately 10 microseconds. The maximum delay is approximately the
* size of UINT32; however, there is no roll-over compensation for the total
* delay time, so it is necessary to back off two times the system tick rate
* from the maximum.
*
* RETURNS: N/A
*/
void sysUsDelay
(
UINT32 delay /* length of time in microsec to delay */
)
{
register UINT baselineTickCount;
register UINT curTickCount;
register UINT terminalTickCount;
register int actualRollover = 0;
register int calcRollover = 0;
UINT ticksToWait;
UINT requestedDelay;
UINT oneUsDelay;
/* Exit if no delay count */
if ((requestedDelay = delay) == 0)
return;
/*
* Get the Time Base Lower register tick count, this will be used
* as the baseline.
*/
baselineTickCount = sysTimeBaseLGet();
/*
* Calculate number of ticks equal to 1 microsecond
*
* The Time Base register and the Decrementer count at the same rate:
* once per 4 System Bus cycles.
*
* e.g., 66666666 cycles 1 tick 1 second 16 tick
* --------------- * ------ * -------- = ----------
* second 4 cycles 1000000 microsec microsec
*/
oneUsDelay = ((DEC_CLOCK_FREQ / 4) / 1000000);
/* Convert delay time into ticks */
ticksToWait = requestedDelay * oneUsDelay;
/* Compute when to stop */
terminalTickCount = baselineTickCount + ticksToWait;
/* Check for expected rollover */
if (terminalTickCount < baselineTickCount)
{
calcRollover = 1;
}
do
{
/*
* Get current Time Base Lower register count.
* The Time Base counts UP from 0 to
* all F's.
*/
curTickCount = sysTimeBaseLGet();
/* Check for actual rollover */
if (curTickCount < baselineTickCount)
{
actualRollover = 1;
}
if (((curTickCount >= terminalTickCount)
&& (actualRollover == calcRollover)) ||
((curTickCount < terminalTickCount)
&& (actualRollover > calcRollover)))
{
/* Delay time met */
break;
}
}
while (TRUE);
}
/******************************************************************************
*
* sysDebugMsg - print a debug string to the console in polled mode.
*
* This routine prints a message to the system console in polled mode and
* optionally exits to the monitor.
*
* RETURNS: N/A
*
*/
void sysDebugMsg
(
char * str,
UINT32 recovery
)
{
int msgSize;
int msgIx;
SIO_CHAN * pSioChan; /* serial I/O channel */
/* add by zoutl delay a while */
for (msgIx = 0; msgIx < 50000; msgIx++)
{
msgSize = msgIx;
}
msgSize = strlen (str);
sysSerialHwInit ();
pSioChan = sysSerialChanGet (0);
sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL);
for (msgIx = 0; msgIx < msgSize; msgIx++)
{
while (sioPollOutput (pSioChan, str[msgIx]) == EAGAIN);
}
/* follow caller's error recovery policy. */
#ifdef DEBUGMSG_RECOVERY
if (recovery == EXIT_TO_SYSTEM_MONITOR)
sysToMonitor (BOOT_NO_AUTOBOOT);
#endif
}
/*****************************************************************************
*
* sysPciInsertLong - Insert field into PCI data long
*
* This function writes a field into a PCI data long without altering any bits
* not present in the field. It does this by first doing a PCI long read
* (into a temporary location) of the PCI data long which contains the field
* to be altered. It then alters the bits in the temporary location to match
* the desired value of the field. It then writes back the temporary location
* with a PCI long write. All PCI accesses are byte and the field to alter is
* specified by the "1" bits in the 'bitMask' parameter.
*
* RETURNS: N/A
*/
void sysPciInsertLong
(
UINT32 adrs, /* PCI address */
UINT32 bitMask, /* Mask which defines field to alter */
UINT32 data /* data written to the offset */
)
{
UINT32 temp;
int key;
key = intLock ();
temp = sysPciInLong (adrs);
temp = (temp & ~bitMask) | (data & bitMask);
sysPciOutLong (adrs, temp);
intUnlock (key);
}
/*****************************************************************************
*
* sysPciInsertWord - Insert field into PCI data word
*
* This function writes a field into a PCI data word without altering any bits
* not present in the field. It does this by first doing a PCI word read
* (into a temporary location) of the PCI data word which contains the field
* to be altered. It then alters the bits in the temporary location to match
* the desired value of the field. It then writes back the temporary location
* with a PCI word write. All PCI accesses are word and the field to alter is
* specified by the "1" bits in the 'bitMask' parameter.
*
* RETURNS: N/A
*/
void sysPciInsertWord
(
UINT32 adrs, /* PCI address */
UINT16 bitMask, /* Mask which defines field to alter */
UINT16 data /* data written to the offset */
)
{
UINT16 temp;
int key;
key = intLock ();
temp = sysPciInWord (adrs);
temp = (temp & ~bitMask) | (data & bitMask);
sysPciOutWord (adrs, temp);
intUnlock (key);
}
/*****************************************************************************
*
* sysPciInsertByte - Insert field into PCI data byte
*
* This function writes a field into a PCI data byte without altering any bits
* not present in the field. It does this by first doing a PCI byte read
* (into a temporary location) of the PCI data byte which contains the field
* to be altered. It then alters the bits in the temporary location to match
* the desired value of the field. It then writes back the temporary location
* with a PCI byte write. All PCI accesses are byte and the field to alter is
* specified by the "1" bits in the 'bitMask' parameter.
*
* RETURNS: N/A
*/
void sysPciInsertByte
(
UINT32 adrs, /* PCI address */
UINT8 bitMask, /* Mask which defines field to alter */
UINT8 data /* data written to the offset */
)
{
UINT8 temp;
int key;
key = intLock ();
temp = sysPciInByte (adrs);
temp = (temp & ~bitMask) | (data & bitMask);
sysPciOutByte (adrs, temp);
intUnlock (key);
}
/*****************************************************************************
*
* sysPciOutByteConfirm - Byte out to PCI memory space and flush buffers.
*
* This function outputs a byte to PCI memory space and then flushes the PCI
* write posting buffers by reading from the target address. Since the PCI
* spec requires the completion of posted writes before the completion of delayed
* reads, when the read completes, the write posting buffers have been flushed.
*
* NOTE: If the write is performed through a PCI-to-PCI bridge to a shared
* location that is subject to unprotected access by multiple simultaneous
* processors, there is the possibility that the bridge will deliver a delayed
* read completion to a PCI bus master which was not the original initiator of
* the delayed read. When this occurs, it appears as if a PCI delayed read had
* passed a posted write, which would violate PCI transaction ordering rules.
* If this is a concern, an additional read must be performed outside of this
* routine to guarantee that the confirming read performed in this routine was
* not aliased.
*
* RETURNS: N/A
*/
void sysPciOutByteConfirm
(
UINT32 adrs, /* PCI address */
UINT8 data /* data to be written */
)
{
UINT8 temp;
sysPciOutByte (adrs, data);
temp = sysPciInByte (adrs);
}
/*****************************************************************************
*
* sysPciOutWordConfirm - Word out to PCI memory space and flush buffers.
*
* This function outputs a word to PCI memory space and then flushes the PCI
* write posting buffers by reading from the target address. Since the PCI
* spec requires the completion of posted writes before the completion of delayed
* reads, when the read completes, the write posting buffers have been flushed.
*
* NOTE: If the write is performed through a PCI-to-PCI bridge to a shared
* location that is subject to unprotected access by multiple simultaneous
* processors, there is the possibility that the bridge will deliver a delayed
* read completion to a PCI bus master which was not the original initiator of
* the delayed read. When this occurs, it appears as if a PCI delayed read had
* passed a posted write, which would violate PCI transaction ordering rules.
* If this is a concern, an additional read must be performed outside of this
* routine to guarantee that the confirming read performed in this routine was
* not aliased.
*
* RETURNS: N/A
*/
void sysPciOutWordConfirm
(
UINT32 adrs, /* PCI address */
UINT16 data /* data to be written */
)
{
UINT16 temp;
sysPciOutWord (adrs, data);
temp = sysPciInWord (adrs);
}
/*****************************************************************************
*
* sysPciOutLongConfirm - Long word out to PCI memory space and flush buffers.
*
* This function outputs a long word to PCI memory space and then flushes the
* PCI write posting buffers by reading from the target address. Since the PCI
* spec requires the completion of posted writes before the completion of delayed
* reads, when the read completes, the write posting buffers have been flushed.
*
* NOTE: If the write is performed through a PCI-to-PCI bridge to a shared
* location that is subject to unprotected access by multiple simultaneous
* processors, there is the possibility that the bridge will deliver a delayed
* read completion to a PCI bus master which was not the original initiator of
* the delayed read. When this occurs, it appears as if a PCI delayed read had
* passed a posted write, which would violate PCI transaction ordering rules.
* If this is a concern, an additional read must be performed outside of this
* routine to guarantee that the confirming read performed in this routine was
* not aliased.
*
* RETURNS: N/A
*/
void sysPciOutLongConfirm
(
UINT32 adrs, /* PCI address */
UINT32 data /* data to be written */
)
{
UINT32 temp;
sysPciOutLong (adrs, data);
temp = sysPciInLong (adrs);
}
/*******************************************************************************
*
* sysIntDisable - disable a bus interrupt level (vector)
*
* This routine disables reception of a specified local or Compact PCI bus
* interrupt. If the interrupt level (vector) specified is used for shared
* memory interrupts, a distributed shared memory interrrupt routine is called
* to disable shared memory interrupts from all PCI or cPCI shared memory
* devices. If the level (vector) is not the one used for shared memory, the
* standard intDisable function is called to disable the interrupt at the MPIC.
*
* RETURNS: The results of sysSmIntDisable or intDisable.
*
* SEE ALSO: sysSmIntDisable, sysIntEnable()
*/
STATUS sysIntDisable
(
int intLevel /* interrupt level (vector) */
)
{
return (intDisable (intLevel));
}
/*******************************************************************************
*
* sysIntEnable - enable a bus interrupt level (vector)
*
* This routine enables reception of a specified local or Compact PCI bus
* interrupt. If the interrupt level (vector) specified is used for shared
* memory interrupts, a distributed shared memory interrrupt routine is called
* to enable shared memory interrupts from all PCI or cPCI shared memory
* devices. If the level (vector) is not the one used for shared memory, the
* standard intEnable function is called to enable the interrupt at the MPIC.
*
* RETURNS: The results of sysSmIntEnable or intEnable.
*
* SEE ALSO: sysSmIntEnable, sysIntDisable()
*/
STATUS sysIntEnable
(
int intLevel /* interrupt level (vector) */
)
{
return (intEnable (intLevel) );
}
/*******************************************************************************
*
* sysBusIntAck - acknowledge a bus interrupt
*
* This routine acknowledges a specified Compact PCI bus interrupt level.
*
* NOTE: This routine is included for BSP compliance only. Since PCI and Compact
* PCI bus interrupts are routed directly to the interrupt controller, interrupts
* are re-enabled in the interrupt controller's handler and this routine is a
* no-op.
*
* RETURNS: NULL.
*
* SEE ALSO: sysBusIntGen()
*/
int sysBusIntAck
(
int intLevel /* interrupt level to acknowledge */
)
{
return (NULL);
}
/*******************************************************************************
*
* sysBusIntGen - generate a bus interrupt
*
* This routine generates an out-bound PCI or Compact PCI backpanel interrupt.
* The method used to generate the interrupt is based on the current
* configuration and operating mode of the BSP. If the BSP was built with
* DEC2155X support and the BSP is operating as the (local) PCI Host device, the
* outbound Compact PCI bus interrupt is generated by calling
* sysDec2155xBusIntGen which sets a bit in the secondary mailbox register of
* the 2155x. If the BSP does not contain DEC2155X support or is operating as a
* PCI Slave device, the outbound PCI interrupt is generated by calling
* sysMpicBusIntGen which sets a bit in the CPU 1 portion of the MPIC's
* Inter-Process Interrupt mechanism. The PRPMC750 hardware ties the CPU 1
* interrupt line to one of the PCI bus interrupt pins which allows this
* mechanism to generate PCI bus interrupts.
*
* RETURNS: The results of sysDec2155xBusIntGen or sysMpicBusIntGen.
*
* SEE ALSO: sysBusIntAck()
*/
STATUS sysBusIntGen
(
int level, /* interrupt level to generate (not used) */
int vector /* interrupt vector for interrupt */
)
{
#ifdef INCLUDE_DEC2155X
return (sysDec2155xBusIntGen (level, vector));
#endif
return (OK);
}
#ifdef INCLUDE_SM_NET
/*****************************************************************************
*
* sysSmParamsCompute - Compute dynamic run-time shared memory parameters.
*
* This function computes the shared memory the SM_INT_ARG1 parameter
* (saved in smIntArg1).
*
* RETURNS: NA
*/
LOCAL void sysSmParamsCompute (void)
{
smIntArg1 = PCI_SPACE_MEM_SEC;
}
/*****************************************************************************
*
* sysSmArg2Compute - Compute dynamic run-time shared memory parameters.
*
* This function computes the shared memory SM_INT_ARG2 parameter.
*
* RETURNS: NA
*/
int sysSmArg2Compute (void)
{
UINT32 smAddr;
UINT32 pciAddr;
UINT32 locAddr;
pciConfigInLong (0, DEC2155X_PCI_DEV_NUMBER, 0,
DEC2155X_CFG_SEC_CSR_MEM_BAR, &pciAddr);
pciAddr += DEC2155X_CSR_SEC_SET_IRQ + (DEC2155X_SM_DOORBELL_BIT >= 8);
sysBusToLocalAdrs (PCI_SPACE_MEM_PRI, (char *)pciAddr,
(char **)&locAddr);
/* Wait for Drawbridge to be configured by host */
while (sysLocalToBusAdrs (PCI_SPACE_MEM_SEC, (char *)locAddr,
(char **)&smAddr) != OK );
return((int)smAddr);
}
#if defined(SYS_SM_ANCHOR_POLL_LIST) && defined(INCLUDE_DEC2155X)
/*****************************************************************************
*
* sysSmAnchorCandidate - Dynamically poll for the anchor address.
*
* This function will determine whether a given bus, device, and function
* number correspond to a defined device on the SYS_SM_ANCHOR_POLL_LIST
*
* RETURNS: TRUE if device is on the SYS_SM_ANCHOR_POLL_LIST
* FALSE if device is not on the SYS_SM_ANCHOR_POLL_LIST
*/
LOCAL UINT sysSmAnchorCandidate
(
UINT busNo, /* candidate's PCI bus number */
UINT deviceNo, /* candidate's PCI device number */
UINT funcNo /* candidate's PCI function number */
)
{
UINT i;
UINT found = FALSE;
UINT devVend;
UINT subIdVend;
for (i = 0 ; (sysSmAnchorPollList[i].devVend != 0xffffffff) ; i++)
{
sysPciConfig21554InLong (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID,
&devVend);
if (devVend == sysSmAnchorPollList[i].devVend)
{
sysPciConfig21554InLong (busNo, deviceNo, funcNo,
PCI_CFG_SUB_VENDER_ID, &subIdVend);
if (subIdVend == sysSmAnchorPollList[i].subIdVend)
{
found = TRUE;
break;
}
}
}
return (found);
}
#endif /* SYS_SM_ANCHOR_POLL_LIST && INCLUDE_DEC2155X */
/*****************************************************************************
*
* sysSmAnchorFind - Dynamically poll for the anchor address.
*
* This function makes one pass on a polling list of devices in an attempt
* to find the shared memory anchor address. The list of devices polled
* includes the system memory DRAM if SYS_SM_SYSTEM_MEM_POLL is defined.
* In addition, if SYS_SM_ANCHOR_POLL_LIST is defined, the devices on this
* list are also included in the search. If SYS_SM_ANCHOR_POLL_LIST is not
* defined, then all devices on the "pciBus" parameter are polled for the
* existence of the shared memory anchor. The "window" which is searched
* corresponds to PCI_CFG_BASE_ADDRESS_0 and the offset queried is
* SM_ANCHOR_OFFSET. If a value of SM_READY is found, the shared memory
* anchor is assumed to be at the corresponding address.
*
* RETURNS: OK if SM_READY found, 'anchor' parameter will contain local address.
* ERROR if SM_READY not find after one scan of the list.
*/
LOCAL STATUS sysSmAnchorFind
(
int pciBus, /* PCI bus number */
char ** anchor /* return variable */
)
{
SM_ANCHOR * tryAddr;
#ifdef INCLUDE_DEC2155X
UINT32 devVend;
UINT32 memBarVal;
int deviceNo;
int maxDevNo;
#endif
#ifdef SYS_SM_SYSTEM_MEM_POLL
LOCAL UINT beat1 = 0;
LOCAL UINT beat2 = 0;
#endif
if (sysProcNumGet () == 0)
{
#if (SM_OFF_BOARD == FALSE)
*anchor = (char *)LOCAL_SM_ANCHOR_ADRS;
return (OK);
#else
/*
* Anchor in host DRAM:
* We will receive an ERROR return initially if the host has not
* yet enabled the bus master bit in the primary PCI command register.
*/
if ( sysBusToLocalAdrs (PCI_SPACE_MEM_SEC,
(char *)(CPCI_MSTR_MEM_BUS + SM_ANCHOR_OFFSET),
(char **)&tryAddr) != OK )
return (ERROR);
*anchor = (char *)tryAddr;
return (OK);
#endif
}
#ifdef SYS_SM_SYSTEM_MEM_POLL
/*
* Look in host DRAM for anchor:
* We will receive an ERROR return initially if the host has not
* yet enabled the bus master bit in the primary PCI command register.
*/
if ( sysBusToLocalAdrs (PCI_SPACE_MEM_SEC,
(char *)(CPCI_MSTR_MEM_BUS + SM_ANCHOR_OFFSET),
(char **)&tryAddr) != OK )
return (ERROR);
/*
* Check for SM_READY to appear and for a heartbeat that changes
* from one call into this routine to the next.
*/
if (tryAddr->readyValue == SM_READY)
{
beat2 = *(UINT *)((UINT)(tryAddr->smPktHeader) + (UINT)tryAddr);
if (beat1 == 0)
/*
* First time through we just record the heartbeat value so
* we can check in on the next call.
*/
beat1 = beat2;
else
{
/*
* On second and subsequent calls, we just check for a change
* in the heartbeat
*/
if (beat1 != beat2)
{
*anchor = (char *)tryAddr;
return (OK);
}
}
}
#endif /* SYS_SM_SYSTEM_MEM_POLL */
#ifdef INCLUDE_DEC2155X
# ifdef SYS_SM_ANCHOR_POLL_LIST
/* if polling list is defined but empty then we're done */
if (sysSmAnchorPollList[0].devVend != 0xffffffff)
# endif
{
if (pciBus == SYS_SM_CPCI_BUS_NUMBER)
maxDevNo = 16;
else
maxDevNo = PCI_MAX_DEV;
for (deviceNo = 0; deviceNo < maxDevNo; deviceNo++)
{
if (sysPciConfig21554InLong (pciBus, deviceNo, 0, 0,
&devVend) != OK)
continue;
# ifdef SYS_SM_ANCHOR_POLL_LIST
if (!sysSmAnchorCandidate (pciBus, deviceNo, 0))
continue;
# endif
if (sysPciConfig21554InLong (pciBus, deviceNo, 0,
PCI_CFG_BASE_ADDRESS_0, &memBarVal) != OK)
continue;
if (sysBusToLocalAdrs (PCI_SPACE_MEM_SEC,
(char *)(memBarVal + SM_ANCHOR_OFFSET),
(char **)&tryAddr) != OK)
continue;
if (tryAddr->readyValue == SM_READY)
{
*anchor = (char *)tryAddr;
return (OK);
}
}
}
#endif /* INCLUDE_DEC2155X */
return (ERROR);
}
/*****************************************************************************
*
* sysSmAnchorPoll - Dynamically poll for the anchor address.
*
* This function will loop and repeatedly call a polling routine to search
* for the shared memrory anchor on the cPCI bus number indicated by
* SYS_SM_CPCI_BUS_NUMBER. It returns with an anchor address only when the
* anchor is actually found.
*
* RETURNS: Anchor address
*/
LOCAL char *sysSmAnchorPoll (void)
{
char *anchor;
int count = 0;
while (sysSmAnchorFind (SYS_SM_CPCI_BUS_NUMBER, &anchor) != OK)
{
if (((++count) % 6) == 0)
printf ("sysSmAnchorPoll() searching for shared memory anchor\n");
sysUsDelay (1000000);
}
return (anchor);
}
/*****************************************************************************
*
* sysSmAnchorAdrs - Dynamically compute anchor address
*
* This function is called if SM_OFF_BOARD == TRUE, that is the shared memory
* anchor is not on this node. If the anchor has been found by a previous
* call to this routine, the previously found anchor value is returned.
* Otherwise if this BSP is running as a PCI Host, a polling routine is called
* which will dynamically search for the anchor. If this BSP is running in
* Slave-Mode, the shared memory anchor must be in the local PCI Host's DRAM.
* This routine is aliased to SM_ANCHOR_ADRS and thus is first called when
* SM_ANCHOR_ADRS is first referenced.
*
* RETURNS: Anchor address
*/
char *sysSmAnchorAdrs (void)
{
static char *anchorAddr;
static int anchorFound = FALSE;
if (anchorFound)
return (anchorAddr);
/* perform the standard search */
anchorAddr = sysSmAnchorPoll ();
anchorFound = TRUE;
return (anchorAddr);
}
#endif /* INCLUDE_SM_NET */
/*******************************************************************************
*
* sysMailboxInt - mailbox interrupt handler
*
* The interrupt dispatcher will clear the in-bound interrupt for us,
* so all we need to do is call the mailbox routine, if it exists.
*/
void sysMailboxInt (void)
{
#ifdef INCLUDE_SM_NET
if (sysMailbox.routine != NULL)
(sysMailbox.routine) (sysMailbox.arg);
#endif /* INCLUDE_SM_NET */
}
/*******************************************************************************
*
* sysMailboxConnect - connect a routine to the in-bound mailbox interrupt
*
* This routine connects a local interrupt service routine to a operating mode
* dependent interrupt vector. If DEC2155X driver support was included, then
* the interrupt handler is connected to the 2155X's interrupt vector.
*
* NOTE: The mailbox interrupt is DEC2155X_MAILBOX_INT_VEC.
*
* RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
*
* SEE ALSO: intConnect(), sysMailboxEnable()
*/
STATUS sysMailboxConnect
(
FUNCPTR routine, /* routine called at each mailbox interrupt */
int arg /* argument with which to call routine */
)
{
#ifdef INCLUDE_SM_NET
if (!sysMailbox.connected)
{
#ifdef INCLUDE_DEC2155X
if (intConnect (INUM_TO_IVEC(DEC2155X_MAILBOX_INT_VEC),
sysMailboxInt, NULL) == ERROR)
return (ERROR);
(void) sysDec2155xIntClear (DEC2155X_MAILBOX_INT_VEC);
#endif
}
/*
* Save the routine address and argument, then mark the mailbox interrupt
* handler connected.
*/
sysMailbox.arg = arg;
sysMailbox.routine = routine;
sysMailbox.connected = TRUE;
#endif /* INCLUDE_SM_NET */
return (OK);
}
/*******************************************************************************
*
* sysMailboxEnable - enable the in-bound mailbox interrupt
*
* This routine enables an operating mode dependent in-bound mailbox interrupt.
* If the BSP was built with DEC2155X support and the BSP is operating as the
* (local) PCI Host, sysDec2155xIntEnable is called to enable the proper bit in
* the 2155X's Secondary mailbox register.
*
* RETURNS: The results of sysDec2155xIntEnable
*
* SEE ALSO: sysMailboxConnect(), sysMailboxDisable()
*/
STATUS sysMailboxEnable
(
char *mailboxAdrs /* address of mailbox (ignored) */
)
{
#ifdef INCLUDE_DEC2155X
return (sysDec2155xIntEnable (DEC2155X_MAILBOX_INT_VEC));
#endif
return (OK);
}
/*******************************************************************************
*
* sysMailboxDisable - disable the in-bound mailbox interrupt
*
* This routine disables an operating mode dependent in-bound mailbox interrupt.
* If the BSP was built with DEC2155X support and the BSP is operating as the
* (local) PCI Host, sysDec2155xIntDisable is called to disable the proper bit in
* the 2155X's Secondary mailbox register.
*
* RETURNS: The results of sysDec2155xIntDisable
*
* SEE ALSO: sysMailboxConnect(), sysMailboxEnable()
*/
STATUS sysMailboxDisable
(
char *mailboxAdrs /* address of mailbox (ignored) */
)
{
#ifdef INCLUDE_DEC2155X
/* calculate the bit in the register */
bit = DEC2155X_MAILBOX_INT_VEC - DEC2155X_DOORBELL0_INT_VEC;
/*
* clear any pending interrupt by writing a one to the proper bit in the
* the Secondary Clear IRQ Register
*/
sysPciOutWord (DEC2155X_CSR_ADRS(DEC2155X_CSR_SEC_CLR_IRQ),
(UINT16)(1 << bit));
/* disable the interrupt */
return (sysDec2155xIntDisable (DEC2155X_MAILBOX_INT_VEC));
#endif
return (OK);
}
void SerialTest(char *TestMsg)
{
ULONG msgIx,msgSize;
/*char TestMsg[]= "This is a test string";*/
SIO_CHAN * pSioChan;
msgSize = strlen(TestMsg);
sysSerialHwInit ();
pSioChan = sysSerialChanGet (0);
sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL);
for (msgIx = 0; msgIx < msgSize; msgIx++)
{
while (sioPollOutput (pSioChan, TestMsg[msgIx]) == EAGAIN);
}
}
/**************************************************************
* Get internal bus speed, megahertz
*/
UINT sysGetBusSpd(void)
{
UINT8 ucPCR;
UINT dwBusSpd = 66;
/* 读PLL配置寄存器 */
ucPCR = sysPciConfigInByte ((UINT8*)0x800000E2);
if((ucPCR & 0xf8) == 0x08 )
{
dwBusSpd = 100;
}
if((ucPCR & 0xf8) == 0x50 )
{
dwBusSpd = 66;
}
return (dwBusSpd);
}
/**************************************************************
* Get internal bus speed, Hz
*/
UINT sysGetBusSpdHertz(void)
{
UINT8 ucPCR;
UINT dwBusSpd = 66700000;
/* 读PLL配置寄存器 */
ucPCR = sysPciConfigInByte ((UINT8*)0x800000E2);
if((ucPCR & 0xf8) == 0x08 )
{
dwBusSpd = 100000000;
}
if((ucPCR & 0xf8) == 0x50 )
{
dwBusSpd = 66700000;
}
return (dwBusSpd);
}
/**************************************************************
* Get cpu speed, Hz
*/
UINT sysGetMpuSpd(void)
{
return(DEFAULT_INTERNAL_CLOCK);
}
/***************************************************************
* Get PCI bus speed, Hz
*/
UINT sysGetPciSpd(void)
{
return(DEFAULT_PCI_CLOCK);
}
/*******************************************************************************
*
* sysMsDelay - delay for the specified amount of time (MS)
*
* This routine will delay for the specified amount of time by counting
* decrementer ticks.
*
* This routine is not dependent on a particular rollover value for
* the decrementer, it should work no matter what the rollover
* value is.
*
* A small amount of count may be lost at the rollover point resulting in
* the sysMsDelay() causing a slightly longer delay than requested.
*
* This routine will produce incorrect results if the delay time requested
* requires a count larger than 0xffffffff to hold the decrementer
* elapsed tick count. For a System Bus Speed of 67 MHZ this amounts to
* about 258 seconds.
*
* RETURNS: N/A
*/
void sysMsDelay
(
UINT delay /* length of time in MS to delay */
)
{
register UINT oldval; /* decrementer value */
register UINT newval; /* decrementer value */
register UINT totalDelta; /* Dec. delta for entire delay period */
register UINT decElapsed; /* cumulative decrementer ticks */
/*
* Calculate delta of decrementer ticks for desired elapsed time.
* The macro DEC_CLOCK_FREQ MUST REFLECT THE PROPER 6xx BUS SPEED.
*/
totalDelta = ((DEC_CLOCK_FREQ / 4) / 1000) * delay;
/*
* Now keep grabbing decrementer value and incrementing "decElapsed" until
* we hit the desired delay value. Compensate for the fact that we may
* read the decrementer at 0xffffffff before the interrupt service
* routine has a chance to set in the rollover value.
*/
decElapsed = 0;
oldval = vxDecGet ();
while (decElapsed < totalDelta)
{
newval = vxDecGet ();
if ( DELTA(oldval,newval) < 1000 )
decElapsed += DELTA(oldval,newval); /* no rollover */
else
if (newval > oldval)
decElapsed += abs((int)oldval); /* rollover */
oldval = newval;
}
}
/*******************************************************************************
*
* sysDelay - delay for approximately one millisecond
*
* Delay for approximately one milli-second.
*
* RETURNS: N/A
*/
void sysDelay (void)
{
sysMsDelay (1);
}
void led11(unsigned short i)
{
unsigned char * ledbit;
ledbit=(unsigned char *)(0xff000000);
if(i==0)
*ledbit&=~(0x01<<(7-7));
else
*ledbit|=0x01<<(7-7);
}
void led12(unsigned short i)
{
unsigned char * ledbit;
ledbit=(unsigned char *)(0xff000000);
if(i==0)
*ledbit&=~(0x01<<(7-6));
else
*ledbit|=0x01<<(7-6);
}
void flashled(unsigned short whichled,unsigned short flashnumber)
{
int i,j ;
switch(whichled)
{
case 1:
for (i=0;i