📄 syslib.c
字号:
** + = Refer to target.txt file for explaination of older boards* with Universe II (U2).* ++ = Refer to target.txt file for explaination of newer boards* with Universe II (U2).* +++ = The master's hardware does not preserve the atomic RMW.* ++++ = If SM_OFF_BOARD == TRUE, the method used will be the same* as if the master board is acting like a slave board; namely:* RMW for UNIVERSE_II and VOWN for UNIVERSE_I* .CE** NOTE: Although the address passed-in to sysBusTas() is defined as* "char *", vxTas() operates on the address as a "void *".* For PowerPC, this implies that the location tested-and-set is* actually a 32-bit entity.* * RETURNS: TRUE if the value had not been set but is now, or* FALSE if the value was set already.** SEE ALSO: vxTas(), sysBusTasClear()*/BOOL sysBusTas ( char * adrs /* address to be tested and set */ ) { /* Check for master node */ if (sysProcNumGet() == 0) {#ifdef ANY_BRDS_IN_CHASSIS_NOT_RMW /* * A slave board in the chassis cannot generate a VMEbus RMW, * and/or the master board cannot translate an incoming VMEbus * RMW into an atomic operation, and/or the master board cannot * generate a VMEbus RMW; therefore, the master must set * VOWN before doing a TAS. */ return (sysVmeVownTas(adrs));#else#if (SM_OFF_BOARD == FALSE) BOOL state = FALSE; /* semaphore state */ int lockKey; /* interrupt lock key */ /* * All slave boards in the chassis are generating a VMEbus RMW, and * the master board can translate an incoming VMEbus RMW into an * atomic operation; therefore, the master can simply call vxTas() * (lwarx/stwcx sequence) because the write portion of the RMW will * be detected. */ /* lock interrupts so that vxTas() can execute without preemption */ lockKey = intLock (); /* Perform TAS on local address */ state = vxTas ((UINT *)adrs); EIEIO_SYNC; intUnlock (lockKey); /* return TAS test result */ return (state);#else /* The master board can generate a VMEbus RMW */ return (sysVmeRmwTas(adrs));#endif /* SM_OFF_BOARD */#endif /* ANY_BRDS_IN_CHASSIS_NOT_RMW */ } else /* Slave node */ { /* A board with the UNIVERSE_II can generate a VMEbus RMW */ return (sysVmeRmwTas(adrs)); } }/******************************************************************************** sysBusTasClear - clear a location set by sysBusTas()** This routine clears the specified 32-bit location typically set* by sysBusTas(). The following table defines the method used to* insure an atomic operation.** .CS* Master Slave_1 Slave_2** VME Chip Don't Care U1 U1* ---------- ---- ----* Method VOWN VOWN VOWN** VME Chip Don't Care U1 U2* ---------- ---- ----* Method VOWN VOWN RMW** VME Chip U1 or U2 U2* U2+* ---------- ---- ----* Method VOWN+++ RMW RMW** VME Chip U2++ U2 U2* PCI Bridge or Hawk* ------------ ------------ ------------* Method simple clear simple clear simple clear*** + = Refer to target.txt file for explaination of older boards* with Universe II (U2).* ++ = Refer to target.txt file for explaination of newer boards* with Universe II (U2).* +++ = The master's hardware does not preserve the atomic RMW.* ++++ = If SM_OFF_BOARD == TRUE, no special/additional processing* is required.* .CE** RETURNS: N/A** SEE ALSO: sysBusTas()*/void sysBusTasClear ( volatile char * adrs /* Address of semaphore to be cleared */ ) {#ifdef ANY_BRDS_IN_CHASSIS_NOT_RMW /* * A slave board in the chassis cannot generate a VMEbus RMW, * and/or the master board cannot translate an incoming VMEbus * RMW into an atomic operation; therefore, the master must set * VOWN before clearing a local TAS location. */ BOOL state; int lockKey; /* interrupt lock key */ UINT32 ticksToWait; /* number of time base ticks to wait */ UINT32 startTick; /* starting timebase low tick value */ /* Check for master node or slave node with UNIVERSE_I */ if (sysProcNumGet() == 0) { /* * convert LOCK_TIMEOUT to timebase ticks as follows: * * ticks/Usec = (bus frequency / decrementer pre-scaler) / 1000000 * * ticks to wait = LOCK_TIMEOUT (in Usecs) * ticks/USec. */ ticksToWait = LOCK_TIMEOUT * ((DEC_CLOCK_FREQ/DECREMENTER_PRESCALE)/USECS_PER_SECOND); /* do clearing with no interference */ lockKey = intLock (); /* request ownership of the VMEbus */ *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN); EIEIO_SYNC; /* snapshot starting time base low value */ startTick = sysTimeBaseLGet (); /* Wait for the VME controller to give you the BUS or timeout */ while (!VMEBUS_OWNER && (sysTimeBaseLGet () - startTick) < ticksToWait); /* * do nothing */ /* clear the location */ *(UINT *)adrs = 0; EIEIO_SYNC; /* release the VME BUS */ *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN); /* enable normal operation */ intUnlock (lockKey); } else /* Slave node == UNIVERSE_II */ { /* Lock interrupts so that setting up SCG and issuing RMW are atomic */ lockKey = intLock (); /* Enable RMW cycle */ sysBusRmwEnable(VME_SCG_COMPARE_MASK, VME_SCG_COMPARE_TO_CLEAR, VME_SCG_SWAP_TO_CLEAR, (char *)adrs); /* perform RMW to clear TAS location */ state = *((UINT *)adrs); EIEIO_SYNC; /* Disable RMW cycle */ sysBusRmwDisable(); /* unlock the interrupt */ intUnlock (lockKey); }#else#if (SM_OFF_BOARD == FALSE) /* * All slave boards in the chassis can generate a VMEbus RMW, and * the master board can translate an incoming VMEbus RMW into an * atomic operation therefore, all boards can do a simple clear. */ *(UINT *)adrs = 0; EIEIO_SYNC;#else /* SM_OFF_BOARD == TRUE */ /* Check for master node or slave node with UNIVERSE_I */ if (sysProcNumGet() == 0) { /* * convert LOCK_TIMEOUT to timebase ticks as follows: * * ticks/Usec = (bus frequency / decrementer pre-scaler) / 1000000 * * ticks to wait = LOCK_TIMEOUT (in Usecs) * ticks/USec. */ ticksToWait = LOCK_TIMEOUT * (DEC_CLOCK_FREQ/DECREMENTER_PRESCALE)/USECS_PER_SECOND); /* do clearing with no interference */ lockKey = intLock (); /* request ownership of the VMEbus */ *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN); EIEIO_SYNC; /* snapshot starting time base low value */ startTick = sysTimeBaseLGet (); /* Wait for the VME controller to give you the BUS or timeout */ while (!VMEBUS_OWNER && (sysTimeBaseLGet () - startTick) < ticksToWait); /* * do nothing */ /* clear the location */ *(UINT *)adrs = 0; EIEIO_SYNC; /* release the VME BUS */ *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN); /* enable normal operation */ intUnlock (lockKey); } else /* Slave node == UNIVERSE_II */ { /* Lock interrupts so that setting up SCG and issuing RMW are atomic */ lockKey = intLock (); /* Enable RMW cycle */ sysBusRmwEnable(VME_SCG_COMPARE_MASK, VME_SCG_COMPARE_TO_CLEAR, VME_SCG_SWAP_TO_CLEAR, (char *)adrs); /* perform RMW to clear TAS location */ state = *((UINT *)adrs); EIEIO_SYNC; /* Disable RMW cycle */ sysBusRmwDisable(); /* unlock the interrupt */ intUnlock (lockKey); }#endif /* SM_OFF_BOARD */#endif /* ANY_BRDS_IN_CHASSIS_NOT_RMW */ }#ifdef ANY_BRDS_IN_CHASSIS_NOT_RMW/********************************************************************************* sysVmeVownTas - test and set a location across the VMEbus** This routine performs a test-and-set (TAS) instruction on the specified* address. To prevent deadlocks, interrupts are disabled and the VMEbus is* locked during the test-and-set operation.** NOTE: Although the address passed-in to sysBusTas() is defined as* "char *", vxTas() operates on the address as a "void *".* For PowerPC, this implies that the location tested-and-set is* actually a 32-bit entity.* * RETURNS: TRUE if the value had not been set but is now* FALSE if the VMEbus cannot be locked or the value was already set.** SEE ALSO: vxTas(), sysVmeVownTasClear()*/LOCAL BOOL sysVmeVownTas ( char * adrs /* address to be tested and set */ ) { BOOL state = FALSE; /* semaphore state */ int lockKey; /* interrupt lock key */ UINT32 ticksToWait; /* number of time base ticks to wait */ UINT32 startTick; /* starting timebase low tick value */ /* * convert LOCK_TIMEOUT to timebase ticks as follows: * * ticks/Usec = (bus frequency / decrementer pre-scaler) / 1000000 * * ticks to wait = requested delay (in Usecs) * ticks/USec. */ ticksToWait = LOCK_TIMEOUT * ((DEC_CLOCK_FREQ/DECREMENTER_PRESCALE)/USECS_PER_SECOND); /* lock interrupts so there will be no TAS interference */ lockKey = intLock (); /* Request ownership of the VMEbus */ *UNIVERSE_MAST_CTL |= LONGSWAP(MAST_CTL_VOWN); EIEIO_SYNC; /* snapshot starting time base low value */ startTick = sysTimeBaseLGet (); /* Wait for the VME controller to give you the BUS or timeout */ while (!VMEBUS_OWNER && (sysTimeBaseLGet () - startTick) < ticksToWait); /* * do nothing */ /* perform the TAS */ if (VMEBUS_OWNER) { state = vxTas ((UINT *)adrs); EIEIO_SYNC; } /* release the VME BUS */ *UNIVERSE_MAST_CTL &= LONGSWAP(~MAST_CTL_VOWN); /* unlock the interrupt */ intUnlock (lockKey); /* return TAS test result */ return (state); }#endif /* ANY_BRDS_IN_CHASSIS_NOT_RMW *//********************************************************************************* sysVmeRmwTas - test and set a location across the VMEbus utilizing RMW** This routine performs a test-and-set (TAS) instruction on the specified* address. To prevent deadlocks, interrupts are disabled and the VMEbus is* locked during the test-and-set operation.** NOTE: Although the address passed-in to sysBusTas() is defined as* "char *", vxTas() operates on the address as a "void *".* For PowerPC, this implies that the location tested-and-set is* actually a 32-bit entity.* * RETURNS: TRUE if the value had not been set but is now* FALSE if the VMEbus cannot be locked or the value was already set.** SEE ALSO: vxTas()*/LOCAL BOOL sysVmeRmwTas ( char * adrs /* address to be tested and set */ ) { BOOL state = FALSE; /* semaphore state */ int lockKey; /* interrupt lock key */ /* A board with the UNIVERSE_II can generate a VMEbus RMW */ /* * Lock interrupts so that setting up SCG and issuing RMW * are atomic */ lockKey = intLock (); /* Enable RMW cycle */ sysBusRmwEnable(VME_SCG_COMPARE_MASK, VME_SCG_COMPARE_TO_SET, VME_SCG_SWAP_TO_SET, (char *)adrs); /* perform RMW to try and set TAS location */ state = *((UINT *)adrs); EIEIO_SYNC; /* Disable RMW cycle */ sysBusRmwDisable(); /* unlock the interrupt */ intUnlock (lockKey);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -