?? universe.c
字號:
/* universe.c - Tundra Universe chip VME-to-PCI bridge interface library *//* Copyright 1984-2002 Wind River Systems, Inc. *//* Copyright 1996-2000 Motorola, Inc. All Rights Reserved *//*modification history--------------------01j,16apr02,dat Update for T2.2 release01i,07apr00,srr Modification history updated to show this came from mv2304.01h,04jun99,rhk added code to enable the A24 slave window.01g,16apr99,rhk changed PCI space define names.01f,05apr99,rhk legacy cleanup, removed references to "raven".01e,05mar99,rhk changed sysMailbox routines to use LM0 interrupt, added support for UNIV II location monitors/mailbox intrs.01d,24feb99,rhk setup to use dynamic base address for registers.01c,15feb99,dmw changed include from ravenMpic.h to kahluaEpic.h.01b,11dec98,srr changed comment from mv2600.h to mv2100.h.01a,11dec98,srr Written (from version 01v of 2304 bsp).*//*DESCRIPTIONThe routines addressed here include:Initialization of Universe chipBus interrupt functions:.IP "-"enable/disable VMEbus interrupt levels.IP "-"enable/disable additional VME interrupts.IP "-"install handlers for the additional VME interrupts.IP "-"generate bus interruptsMailbox/locations monitor functions:.IP "-"- enable mailbox/location monitor interruptsAll byte I/O is done via the macros UNIV_IN_BYTE and UNIV_OUT_BYTE which may beredefined by the BSP. By default, sysInByte() and sysOutByte() are used. Allother I/O (32-bit) is handled by the macros UNIV_IN_LONG and UNIV_OUT_LONGwhich may be redefined by the BSP. By default, sysPciRead32() andsysPciWrite32() are used.*//* includes */#include "vxWorks.h"#include "config.h"#include "vxLib.h"#include "kahluaEpic.h"#include "universe.h"/* defines */#ifndef UNIV_IN_BYTE# define UNIV_IN_BYTE(adr,pVal) \ *(volatile UCHAR *)(pVal)=sysInByte((volatile ULONG)(adr))#endif#ifndef UNIV_OUT_BYTE# define UNIV_OUT_BYTE(adr,val) \ sysOutByte((volatile ULONG)(adr),(volatile UCHAR)(val))#endif#ifndef UNIV_IN_LONG# define UNIV_IN_LONG(adr,pVal) \ *(UINT32 *)pVal = sysPciInLong((UINT32)(adr));#endif#ifndef UNIV_OUT_LONG# define UNIV_OUT_LONG(adr,val) \ sysPciOutLong((UINT32)(adr),(UINT32)(val));#endif# ifndef CPU_INT_LOCK# define CPU_INT_LOCK(pData) (*pData = intLock ())# endif# ifndef CPU_INT_UNLOCK# define CPU_INT_UNLOCK(data) (intUnlock (data))# endif/* forward declarations */LOCAL FUNCPTR sysMailboxRoutine = NULL;LOCAL int sysMailboxArg = 0;#ifdef INCLUDE_VME_DMALOCAL STATUS sysVmeDmaCopy(UCHAR *, UCHAR *, UINT32, UINT32);#endif /* INCLUDE_VME_DMA *//* extern declarations */IMPORT int intEnable (int);IMPORT int intDisable (int);IMPORT void sysOutByte (ULONG, UCHAR);IMPORT UCHAR sysInByte (ULONG);IMPORT void sysPciRead32 (UINT32, UINT32 *);IMPORT void sysPciWrite32 (UINT32, UINT32);IMPORT void sysUsDelay (UINT32);IMPORT INT_HANDLER_DESC * sysIntTbl [256];/* globals */int sysUnivIntsEnabled = 0; /* currently enabled Universe interrupts */int sysUnivIntLevel = 0; /* current level at which ints are disabled */UINT32 sysUnivVERRCnt = 0; /* #VME errors since power on */UINT32 univBaseAdrs;/* * Universe interrupt priority mapping table * * Interrupt priority level is equal to the index into the following array * where 0 is the lowest priority. The prioritization scheme used here * is arbitrary. If the scheme is changed, the interrupt masks (last column) * must be redefined accordingly. See universe.h and the Universe Manual for * bit assignments and further information. */static INT_LEVEL_MAP univIntTable[UNIV_NUM_INT + 1] = { /* Int Bit Mask Int Vector Int Level Mask */ /* ------------------------ ------------------------ -------------- */ {0, 0, 0x00FFF7FF}, {UNIVERSE_VOWN_INT, UNIV_VOWN_INT_VEC, 0x00FFF7FE}, {UNIVERSE_LM1_INT, UNIV_LM1_INT_VEC, 0x00DFF7FE}, {UNIVERSE_LM2_INT, UNIV_LM2_INT_VEC, 0x009FF7FE}, {UNIVERSE_LM3_INT, UNIV_LM3_INT_VEC, 0x001FF7FE}, {UNIVERSE_MBOX0_INT, UNIV_MBOX0_INT_VEC, 0x001EF7FE}, {UNIVERSE_MBOX1_INT, UNIV_MBOX1_INT_VEC, 0x001CF7FE}, {UNIVERSE_MBOX2_INT, UNIV_MBOX2_INT_VEC, 0x0018F7FE}, {UNIVERSE_MBOX3_INT, UNIV_MBOX3_INT_VEC, 0x0010F7FE}, {LVL1, -1, 0x0010F7FC}, {LVL2, -1, 0x0010F7F8}, {LVL3, -1, 0x0010F7F0}, {LVL4, -1, 0x0010F7E0}, {LVL5, -1, 0x0010F7C0}, {LVL6, -1, 0x0010F780}, {LVL7, -1, 0x0010F700}, {UNIVERSE_DMA_INT, UNIV_DMA_INT_VEC, 0x0010F600}, {UNIVERSE_LM0_INT, UNIV_LM0_INT_VEC, 0x0000F600}, {UNIVERSE_VME_SW_IACK_INT, UNIV_VME_SW_IACK_INT_VEC, 0x0000E600}, {UNIVERSE_PCI_SW_INT, UNIV_PCI_SW_INT_VEC, 0x0000C600}, {UNIVERSE_LERR_INT, UNIV_LERR_INT_VEC, 0x0000C400}, {UNIVERSE_VERR_INT, UNIV_VERR_INT_VEC, 0x0000C000}, {UNIVERSE_SYSFAIL_INT, UNIV_SYSFAIL_INT_VEC, 0x00008000}, {UNIVERSE_ACFAIL_INT, UNIV_ACFAIL_INT_VEC, 0x00000000} };/* locals */#ifdef INCLUDE_VME_DMALOCAL BOOL sysVmeDmaReady = FALSE;#endif /* INCLUDE_VME_DMA *//********************************************************************************* sysUniverseReset - reset the Universe VME chip** This routine performs the reseting of the Universe chip. All functions* and VME mapping are disabled.** RETURNS: N/A*/void sysUniverseReset (void) { UINT32 reg; /* initialize registers with defaults and disable mapping */ UNIV_OUT_LONG(UNIVERSE_SCYC_CTL, 0); UNIV_OUT_LONG(UNIVERSE_SCYC_ADDR, 0); UNIV_OUT_LONG(UNIVERSE_SCYC_EN, 0); UNIV_OUT_LONG(UNIVERSE_LMISC, LMISC_CRT_128_USEC); UNIV_OUT_LONG(UNIVERSE_DCTL, 0); UNIV_OUT_LONG(UNIVERSE_DTBC, 0); UNIV_OUT_LONG(UNIVERSE_DLA, 0); UNIV_OUT_LONG(UNIVERSE_DVA, 0); UNIV_OUT_LONG(UNIVERSE_DCPP, 0); UNIV_OUT_LONG(UNIVERSE_LINT_EN, 0); UNIV_OUT_LONG(UNIVERSE_LINT_MAP0, 0); UNIV_OUT_LONG(UNIVERSE_LINT_MAP1, 0); UNIV_OUT_LONG(UNIVERSE_VINT_EN, 0); UNIV_OUT_LONG(UNIVERSE_VINT_MAP0, 0); UNIV_OUT_LONG(UNIVERSE_VINT_MAP1, 0); UNIV_OUT_LONG(UNIVERSE_VSI0_CTL, 0); UNIV_OUT_LONG(UNIVERSE_VSI1_CTL, 0); UNIV_OUT_LONG(UNIVERSE_VSI2_CTL, 0); UNIV_OUT_LONG(UNIVERSE_VSI3_CTL, 0); UNIV_OUT_LONG(UNIVERSE_LSI0_CTL, 0); UNIV_OUT_LONG(UNIVERSE_LSI1_CTL, 0); UNIV_OUT_LONG(UNIVERSE_LSI2_CTL, 0); UNIV_OUT_LONG(UNIVERSE_LSI3_CTL, 0); UNIV_OUT_LONG(UNIVERSE_LM_CTL, 0); /* clear the SYSFAIL signal */ UNIV_OUT_LONG(UNIVERSE_VCSR_CLR, VCSR_CLR_SYSFAIL); /* clear any outstanding interrupts/error conditions */ UNIV_OUT_LONG(UNIVERSE_LINT_STAT, LINT_STAT_CLEAR); UNIV_OUT_LONG(UNIVERSE_VINT_STAT, VINT_STAT_CLEAR); UNIV_OUT_LONG(UNIVERSE_V_AMERR, V_AMERR_V_STAT); UNIV_IN_LONG(UNIVERSE_PCI_CSR, ®); reg |= PCI_CSR_D_PE | PCI_CSR_S_SERR | PCI_CSR_R_MA | PCI_CSR_R_TA | PCI_CSR_S_TA; UNIV_OUT_LONG(UNIVERSE_PCI_CSR, reg); UNIV_OUT_LONG(UNIVERSE_L_CMDERR, L_CMDERR_L_ENABLE); UNIV_OUT_LONG(UNIVERSE_DGCS, DGCS_STOP | DGCS_HALT | DGCS_DONE | DGCS_LERR | DGCS_VERR | DGCS_P_ERR); sysUnivIntsEnabled = 0; sysUnivIntLevel = 0; }/********************************************************************************* sysUniverseInit - initialize registers of the Universe chip** This routine initializes registers of the Universe VME-to-PCI bridge and maps* access to the VMEbus memory space.** NOTE: The sysProcNumSet() routine maps the master node's local memory on the* VMEbus.** RETURNS: OK, always.*/STATUS sysUniverseInit (void) { UINT32 temp_data; /* Put vme chip into a power-up/reset state */ sysUniverseReset (); if (pciToVmeDev == UNIVERSE_I) { UNIV_OUT_LONG(UNIVERSE_MAST_CTL, (MAST_CTL_RTRY_FOREVER | MAST_CTL_PWON_4096 | MAST_CTL_VRL3 | MAST_CTL_VRM_DEMAND | MAST_CTL_VREL_RWD | MAST_CTL_PABS_32 )); } else { /* pciToVmeDev == UNIVERSE_II */ UNIV_OUT_LONG(UNIVERSE_MAST_CTL, (MAST_CTL_RTRY_FOREVER | MAST_CTL_PWON_4096 | MAST_CTL_VRL3 | MAST_CTL_VRM_FAIR | MAST_CTL_VREL_ROR | MAST_CTL_PABS_128 )); } UNIV_IN_LONG(UNIVERSE_MISC_CTL, &temp_data); /* maintain power-up option bits */ temp_data &= ( MISC_CTL_SYSCON | MISC_CTL_V64AUTO ); temp_data |= ( MISC_CTL_VBTO_256USEC | MISC_CTL_VARB_RROBIN | MISC_CTL_VARBTO_256USEC | MISC_CTL_RESCIND ); UNIV_OUT_LONG(UNIVERSE_MISC_CTL, temp_data); UNIV_OUT_LONG(UNIVERSE_USER_AM, 0); UNIV_OUT_LONG(UNIVERSE_VRAI_CTL, 0); UNIV_OUT_LONG(UNIVERSE_VCSR_CTL, 0); /* clear the SYSFAIL signal */ UNIV_OUT_LONG(UNIVERSE_VCSR_CLR, VCSR_CLR_SYSFAIL); /* set the latency timer to max value */ UNIV_OUT_LONG(UNIVERSE_PCI_MISC0, PCI_MISC0_LATENCY_TIMER); /* Map to get to VMEbus using A32 */ UNIV_OUT_LONG(UNIVERSE_LSI1_BS, VAL_LSI1_BS); UNIV_OUT_LONG(UNIVERSE_LSI1_BD, VAL_LSI1_BD); UNIV_OUT_LONG(UNIVERSE_LSI1_TO, VAL_LSI1_TO); UNIV_OUT_LONG(UNIVERSE_LSI1_CTL, VAL_LSI1_CTL); /* Map to get to VMEbus using A24 */ UNIV_OUT_LONG(UNIVERSE_LSI2_BS, VAL_LSI2_BS); UNIV_OUT_LONG(UNIVERSE_LSI2_BD, VAL_LSI2_BD); UNIV_OUT_LONG(UNIVERSE_LSI2_TO, VAL_LSI2_TO); UNIV_OUT_LONG(UNIVERSE_LSI2_CTL, VAL_LSI2_CTL); /* Map to get to VMEbus using A16 */ UNIV_OUT_LONG(UNIVERSE_LSI3_BS, VAL_LSI3_BS); UNIV_OUT_LONG(UNIVERSE_LSI3_BD, VAL_LSI3_BD); UNIV_OUT_LONG(UNIVERSE_LSI3_TO, VAL_LSI3_TO); UNIV_OUT_LONG(UNIVERSE_LSI3_CTL, VAL_LSI3_CTL); /* Map to get to VMEbus LM/SIG Registers using A32 */ UNIV_OUT_LONG(UNIVERSE_LSI0_BS, VAL_LSI0_BS); UNIV_OUT_LONG(UNIVERSE_LSI0_BD, VAL_LSI0_BD); UNIV_OUT_LONG(UNIVERSE_LSI0_TO, VAL_LSI0_TO); UNIV_OUT_LONG(UNIVERSE_LSI0_CTL, VAL_LSI0_CTL); return (OK); }/********************************************************************************* sysUniverseInit2 - enable local memory accesses from the VMEbus** This routine enables local resources to be accessed from the VMEbus.* All target boards have an A32 window opened to access the VMEbus LM/SIG* registers. However, only the master node has an A32 and an A24* window open to its local memory space.** RETURNS: N/A** NOMANUAL*/void sysUniverseInit2 ( int procNum /* processor number */ ) {#ifndef DOC /* setup the VME LM registers address range */ UNIV_OUT_LONG(UNIVERSE_LM_CTL, VAL_LM_CTL); UNIV_OUT_LONG(UNIVERSE_LM_BS, VAL_LM_BS); if (procNum == 0) { /* setup the A32 window */ UNIV_OUT_LONG(UNIVERSE_VSI1_BS, VAL_VSI1_BS); UNIV_OUT_LONG(UNIVERSE_VSI1_BD, VAL_VSI1_BD); UNIV_OUT_LONG(UNIVERSE_VSI1_TO, VAL_VSI1_TO);#ifdef A24_SLV_WINDOW UNIV_OUT_LONG(UNIVERSE_VSI2_BS, VAL_VSI2_BS); UNIV_OUT_LONG(UNIVERSE_VSI2_BD, VAL_VSI2_BD); UNIV_OUT_LONG(UNIVERSE_VSI2_TO, VAL_VSI2_TO);#endif if (pciToVmeDev == UNIVERSE_I) { UNIV_OUT_LONG(UNIVERSE_VSI1_CTL, VAL_VSI1_CTL);#ifdef A24_SLV_WINDOW UNIV_OUT_LONG(UNIVERSE_VSI2_CTL, VAL_VSI2_CTL);#endif } else { /* pciToVmeDev == UNIVERSE_II */ UNIV_OUT_LONG(UNIVERSE_VSI1_CTL, VAL_VSI1_CTL | VSI_CTL_PWEN);#ifdef A24_SLV_WINDOW UNIV_OUT_LONG(UNIVERSE_VSI2_CTL, VAL_VSI2_CTL | VSI_CTL_PWEN);#endif#if (SM_OFF_BOARD == FALSE)#ifndef ANY_BRDS_IN_CHASSIS_NOT_RMW /* * All slave boards in the chassis generate a VMEbus RMW, and * the master is capable of translating an incoming RMW into * an atomic operation. */ /* * The A32 access range is now divided into 3 separate windows. * The first window will allow normal access to the start of local * memory up to the Shared Memory Region. It is defined above * thru the use of a conditional #define VAL_VSI1_BD in mv2100.h. * The second window will allow Read-Modify-Write (RMW) access to * the Standard VxWorks and VxMP's Shared Memory Region. The * third window will allow normal access to the local memory * starting after the Shared Memory Region up to the end of * physical memory. */ /* setup the second A32 window */ UNIV_OUT_LONG(UNIVERSE_VSI4_BS, VAL_VSI4_BS); UNIV_OUT_LONG(UNIVERSE_VSI4_BD, VAL_VSI4_BD); UNIV_OUT_LONG(UNIVERSE_VSI4_TO, VAL_VSI4_TO); UNIV_OUT_LONG(UNIVERSE_VSI4_CTL, VAL_VSI4_CTL); /* setup the third A32 window */ UNIV_OUT_LONG(UNIVERSE_VSI5_BS, VAL_VSI5_BS); UNIV_OUT_LONG(UNIVERSE_VSI5_BD, VAL_VSI5_BD); UNIV_OUT_LONG(UNIVERSE_VSI5_TO, VAL_VSI5_TO); UNIV_OUT_LONG(UNIVERSE_VSI5_CTL, VAL_VSI5_CTL);#endif /* ANY_BRDS_IN_CHASSIS_NOT_RMW */#endif /* SM_OFF_BAORD */ } }#endif }/********************************************************************************* sysIntDisable - disable a bus interrupt level** This routine disables reception of a specified VMEbus interrupt level.** NOTE: revision 1.0 Universe chips can fail and lockup if two or more interrupt* levels are enabled. For more details see Tundra Universe Errata sheet.** RETURNS: OK, or ERROR if <intLevel> is not in the range 1 - 7.** SEE ALSO: sysIntEnable()*/STATUS sysIntDisable
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -