/************************************************************************* $Archive: /pacs/OnBoard/SmcsDrv.c $ $Revision: 1.15 $ $Date: 2010/09/29 12:42:53 $ $Author: amazy $ $Log: SmcsDrv.c,v $ Revision 1.15 2010/09/29 12:42:53 amazy v6.033 * * 9 9/23/10 4:37p Pacs1 * * 8 9/22/10 6:00p Pacs1 * * 7 16/09/10 14:36 Amazy * - Introduced EDAC test code * - Introduced code to reset the DEC FPGA in SET_PARAM_BOTH * * 6 12/11/06 11:49a Amazy * introduced checksum in DMC HK * * 29 3/14/06 4:32p Pacs Egse * Version 6.001 * Cleaned and commented *************************************************************************/ #ifdef SIMULATOR #include "virtuosoSim.h" #else // SIMULATOR #include "v_macro.h" #include "node1.h" #include "k_struct.h" __asm("#include ;"); #endif #ifndef LINK1355_H #include "link1355.h" #endif //LINK1355_H #include "params.h" #include "error.h" #include "links.h" #include "u_bits.h" #include "m_smcsin.h" #include "m_smcsco.h" #include "m_smcsre.h" //**************************************************************** // GLOBAL PARAMETERS //**************************************************************** int gaLinkTransmitCompleted[6]; int gaLinkReceptionCompleted[6]; int gaStartReading[6]; int gaStartLink[6]; int gaLinkStatus[6] = {NOT_STARTED, NOT_STARTED, NOT_STARTED, NOT_STARTED, NOT_STARTED, NOT_STARTED}; // array containing the status of each of the 1355 link int gaLinkParityDisconnectError[6]; int gaMasterSlave[6]; int gSmcs1IsrCount; int gSmcs2IsrCount; int gSmcs1IsrHandledCount; int gSmcs2IsrHandledCount; int gLastSmcs2ISR; int gLastSmcs2IMR; extern K_TIMER* gpHkGeneralTimer; #ifndef SIMULATOR K_ARGS gSemaSMCS; K_TICKS gDisconnectTime; #endif //**************************************************************** // FUNCTION DECLARATION //**************************************************************** extern void ValidateBolHK(int validity); #ifndef SIMULATOR extern void smcs1_isr(); extern void smcs2_isr(); extern void SwitchOffChopperController(); extern void DisableGratingController(); //**************************************************************** // FUNCTION IMPLEMENTATION //**************************************************************** /* TASK_FUNCTION : void SmcsDrvIrq() ********************************* AUTHOR : AMazy This is the function implementing the SMCS DRIVER IRQ task This task is the interface between the SMCS interrupt routine and the other tasks when performing usual operation such as read/write. It is also used to detect the disconnection */ void SmcsDrvIrq() { int i=0; gSmcs1IsrCount = 0; gSmcs2IsrCount = 0; gSmcs1IsrHandledCount = 0; gSmcs2IsrHandledCount = 0; gLastSmcs2ISR = 0; gLastSmcs2IMR = 0; for (i = 0; i < 6; ++i) { gaLinkTransmitCompleted[i] = 0; gaLinkReceptionCompleted[i] = 0; gaLinkParityDisconnectError[i] = 0; gaStartReading[i] = 0; } //initiliaze the semaphore structure that is used to communicate between the ISR and the Task gSemaSMCS.Srce = 0; gSemaSMCS.Comm = SIGNALS; gSemaSMCS.Args.s1.sema = SEMA_SMCS_DRV_IRQ; while(1) { // wait for any event coming from the smcs interrupts (SMCS_1 & SMCS_2) or from the SMCS timer KS_SemaTestW(SEMA_SMCS_DRV_IRQ); for (i = 0; i < 6; i++) { if (gaLinkTransmitCompleted[i] != 0) { // Dangerous if an interrupt occurs right here !!!!! but it will never happen // since no task will start another transmition before having received the event // 'transmition completed' gaLinkTransmitCompleted[i] = 0; //signal the event to the task KS_EventSignal(gaEventsSmcsTransmitCompleted[i]); } if (gaLinkReceptionCompleted[i] != 0) { // Dangerous if an interrupt occurs right here !!!!! but it will never happen // since no task will start another reception before having received the event // 'reception completed' gaLinkReceptionCompleted[i] = 0; //signal the event to the task KS_EventSignal(gaEventsSmcsReceiveCompleted[i]); } if (gaLinkParityDisconnectError[i] != 0) { gaLinkParityDisconnectError[i] = 0; if ((i + K_SMCSCHANNEL_1) <= K_SMCSCHANNEL_3) { CLEAR_BIT(gaLinkStatus[i], CONNECTED); SET_BIT(gaLinkStatus[i], DISCONNECTED); StopLink(i+K_SMCSCHANNEL_1); } //the 3 mezzanine links are in 'autoreconnect mode' so, we don't stop the link if there was a disconnection switch (i) { case CHANNEL_DPU_ID : SetErrorIn(gpDpuSend->TaskStatus, ERR_LINK_DPU); SetErrorIn(gpDpuRec->TaskStatus, ERR_LINK_DPU); LOCK_WRITE_RES_PARAMS; SET_BITS(gpDpuSend->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_NOT_CONNECTED); SET_BITS(gpDpuRec->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_NOT_CONNECTED); UNLOCK_WRITE_RES_PARAMS; //if the connection with DPU has been lost; it means that the DPU has just performed //a chip reset (i.e because SPU has been switched on). In this case, we also need to //perform a chip reset and retry establishing the coonections with DPU and SPUs. //We will do so every 9 sec //store the current time to know when we need to retry to reconnect //gDisconnectTime = KS_LowTimerRead() - 9*TICKFREQ; //remove 9*TICKFREQ such that the first SMCS chip reset occurs almost immediately gDisconnectTime = KS_LowTimerRead(); //suspend HK while not connected to DPU. KS_LowTimerStop(gpHkGeneralTimer); SET_BIT(gaLinkStatus[i], RETRY_TO_CONNECT); // in case we never get the connection with DPU again, we should disable the grating controller and switch-off the chopper controller SwitchOffChopperController(); DisableGratingController(); break; case CHANNEL_BLUE_SPU_ID : SetErrorIn(gpBluePacketEncoder->TaskStatus, ERR_LINK_SPU_BLUE); LOCK_WRITE_RES_PARAMS; SET_BITS(gpBluePacketEncoder->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_NOT_CONNECTED); UNLOCK_WRITE_RES_PARAMS; break; case CHANNEL_BLUE_DEC_ID : SetErrorIn(gpBlueDecRec->TaskStatus, ERR_LINK_DEC_BLUE); SetErrorIn(gpBlueDecController->TaskStatus, ERR_LINK_DEC_BLUE); break; case CHANNEL_BOL_ID : SetErrorIn(gpBolRec->TaskStatus, ERR_LINK_BOL); SetErrorIn(gpBolController->TaskStatus, ERR_LINK_BOL); break; case CHANNEL_RED_SPU_ID : SetErrorIn(gpRedPacketEncoder->TaskStatus, ERR_LINK_SPU_RED); LOCK_WRITE_RES_PARAMS; SET_BITS(gpRedPacketEncoder->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_NOT_CONNECTED); UNLOCK_WRITE_RES_PARAMS; break; case CHANNEL_RED_DEC_ID : SetErrorIn(gpRedDecRec->TaskStatus, ERR_LINK_DEC_RED); SetErrorIn(gpRedDecController->TaskStatus, ERR_LINK_DEC_RED); break; default : }; } } } }; #endif //SIMULATOR /* TASK_FUNCTION : void SmcsDrvState() *********************************** AUTHOR : AMazy This is the function implementing the SMCS DRIVER STATE task This task is handling the status of the links: - it handles the connection (start link) - it handles the re-connection of the link with DPU */ void SmcsDrvState() { K_TIMER* pSmcsDriverTimer = NULL; int i=0; gaMasterSlave[CHANNEL_DPU_ID] = MASTER; gaMasterSlave[CHANNEL_BLUE_DEC_ID] = MASTER; gaMasterSlave[CHANNEL_BLUE_SPU_ID] = MASTER; gaMasterSlave[CHANNEL_RED_DEC_ID] = MASTER; gaMasterSlave[CHANNEL_RED_SPU_ID] = MASTER; gaMasterSlave[CHANNEL_BOL_ID] = MASTER; for (i = 0; i < 6; ++i) { gaStartLink[i] = 0; } #ifndef SIMULATOR // init the SMCS chips immediately at startup DSMCS_ResetSMCSChip(K_SMCS_1); DSMCS_ResetSMCSChip(K_SMCS_2); DSMCS_ConfigureSMCSNominal(K_SMCS_1); DSMCS_ConfigureSMCSNominal(K_SMCS_2); //wait to be released when the Sequencer has completed its start-up KS_SemaTestW(SEMA_SMCS_DRV_STATE); /*Install the Interrupt Handlers */ // enable smcs2 interrupt (IRQ1) KS_IRQSetHandler(7, smcs2_isr); // 7 is the bit number of IRQ1 in IMASK // IRQ1 must be level sensitive interrupt __asm(" bit clr MODE2 IRQ1E;"); // must be level sensitive interrupt __asm(" nop;"); KS_ISREnable(7); // the IRQ from SMCS2 goes through DMPSC chip. We need to configure the interrupt in the DMPSC register as well //SMCS2 interrupt must be level sensitive *((int*)K_DMADD_DMPSC_GENCONFSTT) = 0x00000801; //enable SMCS2 interrupt *((int*)K_DMADD_DMPSC_INTMASK) &= 0xFFFFFFF7; // enable smcs1 interrupt (IRQ2) KS_IRQSetHandler(6, smcs1_isr); // 6 is the bit number of IRQ2 in IMASK // IRQ2 must be level sensitive interrupt __asm(" bit clr MODE2 IRQ2E;"); // must be level sensitive interrupt __asm(" nop;"); KS_ISREnable(6); // start some of the links 1355 StartLink(CHANNEL_DPU, NO_SMCS_RESET); #endif //SIMULATOR //create a timer that will signal the semaphore every second (needed to test if connections are alive pSmcsDriverTimer = KS_LowTimerGet(); if (pSmcsDriverTimer == NULL) { SetGlobalError(ERR_SMCS_DRIVER_COULD_NOT_CREATE_TIMER); } else { // timer has been allocated, we can initialize it KS_LowTimerStart(pSmcsDriverTimer, TICKFREQ, TICKFREQ, SEMA_SMCS_DRV_STATE); } while(1) { // wait for any event coming from other tasks or from the SMCS timer KS_SemaTestW(SEMA_SMCS_DRV_STATE); for (i = 0; i < 6; i++) { // if the link is currently trying to connect if (TEST_ONE_BIT(gaLinkStatus[i], WAITING_CONNECTION)) { // test if NUL tokens have been received (connection established) if (Link1355Test(i + K_SMCSCHANNEL_1) == RC_OK) { //if yes, change the link status if (gaMasterSlave[i] == MASTER) { SET_BITS(gaLinkStatus[i], CONN_STATUS_MASK, CONNECTED_AS_MASTER); } else { #ifndef SIMULATOR // when nul tokens have been received, start emitting the nul tokens DSMCS_StartChannelAsSlave(i + K_SMCSCHANNEL_1); #endif//SIMULATOR SET_BITS(gaLinkStatus[i], CONN_STATUS_MASK, CONNECTED_AS_SLAVE); } #ifndef SIMULATOR //once the connection is established, we can enable the interrupts, configure the link and start using it EnableInterruptsForLink(i + K_SMCSCHANNEL_1); //for smcs chip 2 only, configure the link to autoreconnect if ((i + K_SMCSCHANNEL_1) > K_SMCSCHANNEL_3) { ConfigureLinkToAutoReconnect(i + K_SMCSCHANNEL_1); } EnableReadingAndWritingOnLink(i + K_SMCSCHANNEL_1); SET_BITS(gaLinkStatus[i], READ_FROM, READ_FROM_SMCS_DRV); #endif//SIMULATOR // and change the task status switch (i) { case CHANNEL_DPU_ID : LOCK_WRITE_RES_PARAMS; SET_BITS(gpDpuSend->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); SET_BITS(gpDpuRec->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); CLEAR_BIT(gaLinkStatus[i], RETRY_TO_CONNECT); UNLOCK_WRITE_RES_PARAMS; if (gpHkGeneralTimer) //if this is a reconnection after HK has already been started once { KS_SemaReset(SEMA_TIMER_HOUSEKEEPING_GENERAL); //this is to avoid to receive lots of packets if there has been a long time between the actual deconnection and the detect deconnection KS_LowTimerStart(gpHkGeneralTimer, TICKFREQ*2, TICKFREQ*2, SEMA_TIMER_HOUSEKEEPING_GENERAL); KS_EventSignal(EVENT_HK_PACKET_BUFFER_AVAILABLE); } //clear all messages (old hk packets) that were waiting to be sent. #ifndef SIMULATOR KS_FIFOPurge(DPUSENDER_FIFO); #endif //SIMULATOR break; case CHANNEL_BLUE_SPU_ID : LOCK_WRITE_RES_PARAMS; SET_BITS(gpBluePacketEncoder->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); UNLOCK_WRITE_RES_PARAMS; break; case CHANNEL_BLUE_DEC_ID : LOCK_WRITE_RES_PARAMS; SET_BITS(gpBlueDecController->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); SET_BITS(gpBlueDecRec->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); UNLOCK_WRITE_RES_PARAMS; break; case CHANNEL_BOL_ID : LOCK_WRITE_RES_PARAMS; SET_BITS(gpBolRec->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); SET_BITS(gpBolController->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); UNLOCK_WRITE_RES_PARAMS; ValidateBolHK(TRUE); break; case CHANNEL_RED_SPU_ID : LOCK_WRITE_RES_PARAMS; SET_BITS(gpRedPacketEncoder->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); UNLOCK_WRITE_RES_PARAMS; break; case CHANNEL_RED_DEC_ID : LOCK_WRITE_RES_PARAMS; SET_BITS(gpRedDecController->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); SET_BITS(gpRedDecRec->TaskStatus, K_BMASK_TASK_STATUS_LINK_STATUS, K_BMASK_TASK_STATUS_LINK_CONNECTED); UNLOCK_WRITE_RES_PARAMS; break; } } } } #ifndef SIMULATOR //test if there has been request to start links for (i = 0; i < 6; i++) { if (gaStartLink[i] != 0) { _StartLink(i+K_SMCSCHANNEL_1, gaStartLink[i] & (MASTER | SLAVE), gaStartLink[i] & RESET_SMCS); gaStartLink[i] = 0; } } //check if we are currently trying to (re)connect to DPU and if we need to reset the SMCS chip if (TEST_ONE_BIT(gaLinkStatus[CHANNEL_DPU_ID], RETRY_TO_CONNECT)) { K_TICKS current_time = KS_LowTimerRead(); //every 9 seconds, retry to connect if (((current_time - gDisconnectTime) > 9*TICKFREQ) || ((current_time - gDisconnectTime) < 0)) // it will be lower than zero when timer goes over the 32bits resolution { //reset the disconnect time gDisconnectTime = current_time; //restart DPU Link with a chip reset (it will also restart all the links that were already //started before the reset (including links to SPUs)) StartLink(CHANNEL_DPU, RESET_SMCS); } } #endif //SIMULATOR } } /* CMD_FUNCTION : BOOL CommandStartRedSpuLink(CommandParameter param) ****************************************************************** AUTHOR : Amazy USE : Start the 1355 link with Red SPU PARAMS: Uint : 0 = SLAVE, 1 = MASTER */ BOOL CommandStartRedSpuLink(CommandParameter param) { if (param.Uint == 0) { gaMasterSlave[CHANNEL_RED_SPU_ID] = SLAVE; } else { gaMasterSlave[CHANNEL_RED_SPU_ID] = MASTER; } //purge packet encoder fifo to make sure it does not send old packets if (gParameters.RedPacketEncoderLink == CHANNEL_RED_SPU) { KS_FIFOPurge(RED_PACKET_ENCODER_FIFO); } else { KS_FIFOPurge(BLUE_PACKET_ENCODER_FIFO); } StartLink(CHANNEL_RED_SPU, NO_SMCS_RESET); SequencerSendAck(DMC_START_RED_SPU_LINK); return TRUE; } /* CMD_FUNCTION : BOOL CommandStartBlueSpuLink(CommandParameter param) ******************************************************************* AUTHOR : Amazy USE : Start the 1355 link with Blue SPU PARAMS: Uint : 0 = SLAVE, 1 = MASTER */ BOOL CommandStartBlueSpuLink(CommandParameter param) { if (param.Uint == 0) { gaMasterSlave[CHANNEL_BLUE_SPU_ID] = SLAVE; } else { gaMasterSlave[CHANNEL_BLUE_SPU_ID] = MASTER; } //purge packet encoder fifo to make sure it does not send old packets if (gParameters.BluePacketEncoderLink == CHANNEL_BLUE_SPU) { KS_FIFOPurge(BLUE_PACKET_ENCODER_FIFO); } else { KS_FIFOPurge(RED_PACKET_ENCODER_FIFO); } StartLink(CHANNEL_BLUE_SPU, NO_SMCS_RESET); SequencerSendAck(DMC_START_BLUE_SPU_LINK); return TRUE; } /* CMD_FUNCTION : BOOL CommandResetSmcsChip2(CommandParameter paramNotUsed) ************************************************************************ AUTHOR : Amazy USE : Resets SMCS2 and try to connect to BOLC */ BOOL CommandResetSmcsChip2(CommandParameter paramNotUsed) { StartLink(CHANNEL_BOL, RESET_SMCS); SequencerSendAck(DMC_RESET_SMCS_CHIP_2); return TRUE; }