HRESULT llcIntEventAddCallback(uint32 idx, INTEVENT_CALLBACK callback) { HRESULT hResult = NO_ERROR; if (idx < LLC_INT_ITEMS) { if (intEventCallback[idx] == NULL) { intEventCallback[idx] = callback; llcIntInstalledMask |=LLC_INT_BIT(idx); llcLinkRegWrite(INTR_MASK_REG_SET_DP, LLC_INT_BIT(idx)); } else { hResult = E_LLC_INTEVENT_CB_ERR; } } else { hResult = E_LLC_INTEVENT_CB_RANGE_ERR; } return hResult; }
BOOL llcIntEventIsIntEnabled(uint32 index) { uint32 intEventReg; uint32 bit; if (index >= LLC_INT_ITEMS) { return FALSE; } bit = LLC_INT_BIT(index); llcLinkRegRead(INTR_MASK_REG_SET_DP, &intEventReg); return ((bit & intEventReg) == bit); }
/* Initialize this module Add interrupt procedure to vector addresses */ HRESULT llcIntInitialize(void) { HRESULT hResult = NO_ERROR; llcIntState = LLC_INT_STATE_WAIT_BUSRESET; hResult = llcIntEventInitCallbacks(); if (hResult != NO_ERROR) return hResult; // Clear all pending interrupts llcLinkRegWrite(INTERRUPT_REG_CLEAR_DP, LLC_ALL_INTR_MASK); //TCInterruptInstallHandler(CYGNUM_HAL_INTERRUPT_SLINK, NULL, &llcIntEventHandler); hResult = TCInterruptInstallEcosHandler(CYGNUM_HAL_INTERRUPT_SLINK, &llc_interrupt_isr, &llc_interrupt_dsr); //hResult = TCInterruptCreateLLC(&llcIntEventHandler); if (hResult != NO_ERROR) return hResult; // Enable interrupts from Samsung LLC llcLinkRegWrite(INTR_MASK_REG_SET_DP, LLC_INT_BIT(LLCID_INTR_OUT)); return hResult; }
HRESULT llcIntEventRemoveCallback(uint32 idx) { HRESULT hResult = NO_ERROR; if (idx < LLC_INT_ITEMS) { if (intEventCallback[idx] != NULL) { intEventCallback[idx] = NULL; llcIntInstalledMask &= ~LLC_INT_BIT(idx); llcLinkRegWrite(INTR_MASK_REG_CLEAR_DP, LLC_INT_BIT(idx)); } else { hResult = E_LLC_INTEVENT_CB_ERR; } } else { hResult = E_LLC_INTEVENT_CB_RANGE_ERR; } return hResult; }
HRESULT llcIntEventAddIsr(uint32 idx, INTEVENT_ISR_CALLBACK callback) { HRESULT hResult = NO_ERROR; if (idx <= LLC_INT_ISR_TX) { if (intEventIsrCallback[idx] == NULL) { intEventIsrCallback[idx] = callback; llcIsrInstalledMask |=LLC_INT_BIT((idx==LLC_INT_ISR_RX)?LLCID_ASY_RX_PKT_AVL:LLCID_ASY_TX_CMPL); } else { hResult = E_LLC_INTEVENT_CB_ERR; } } else { hResult = E_LLC_INTEVENT_CB_RANGE_ERR; } return hResult; }
uint32 llc_interrupt_isr(uint32 vector, void *data) { uint32 intEventReg; BOOL bDsr = FALSE; llcLinkRegRead(INTERRUPT_REG_CLEAR_DP, &intEventReg); //events which are not masked if ((intEventReg & LLC_INT_BIT(LLCID_INTR_OUT)) == 0) return CYG_ISR_HANDLED; //mask all those handled by DSR, DSR will unmask when done bDsr = intEventReg & llcIntInstalledMask; if (bDsr) llcLinkRegWrite(INTR_MASK_REG_CLEAR_DP, ~(HANDLE_BY_ISR | LLC_INT_BIT(LLCID_INTR_OUT))); // Clear the ones we are handeling here llcLinkRegWrite(INTERRUPT_REG_CLEAR_DP, intEventReg&(HANDLE_BY_ISR | LLC_INT_BIT(LLCID_INTR_OUT))); llcIntEvents++; //we need to look for bus reset and if we see it we must mask out LLCID_ASY_RX_PKT_AVL and leave it //to the DSR BR handler to read whatever is in the FIFO //The LLCID_BUS_RST_RXD might be masked waiting for DSR so we need to check the raw status uint32 rawEvent; llcLinkRegRead(INTERRUPT_REG_DP, &rawEvent); if (rawEvent & LLC_INT_BIT(LLCID_BUS_RST_RXD)) { //at some point the DSR will handle this, we really don't need and ISR processing for now llcLinkRegWrite(INTR_MASK_REG_CLEAR_DP, HANDLE_BY_ISR); //we have to rely on the DSR putting us back into normal mode } else { if (intEventReg & LLC_INT_BIT(LLCID_ASY_RX_PKT_AVL)) if (_llcIntEventIsrCallCallback(LLC_INT_ISR_RX)) llcIsrDsrRxEvent = 1; if (intEventReg & LLC_INT_BIT(LLCID_ASY_TX_CMPL)) if (_llcIntEventIsrCallCallback(LLC_INT_ISR_TX)) llcIsrDsrTxEvent = 1; } //as long as we have unhandled Isr->dsr's keep calling the DSR. if (llcIsrDsrRxEvent || llcIsrDsrTxEvent) bDsr = 1; return bDsr ? CYG_ISR_CALL_DSR : CYG_ISR_HANDLED; }
void llc_interrupt_dsr(uint32 vector, uint32 count, void * data) { uint32 intEventReg; llcLinkRegRead(INTERRUPT_REG_DP, &intEventReg); //read raw interrupt stat intEventReg &=llcIntInstalledMask; //and with handled stat //is there any ISR requests if (llcIsrDsrTxEvent) { intEventReg |= LLC_INT_BIT(LLCID_ASY_TX_CMPL); llcIsrDsrTxEvent = 0; } if (llcIsrDsrRxEvent) { intEventReg |= LLC_INT_BIT(LLCID_ASY_RX_PKT_AVL); llcIsrDsrRxEvent = 0; } //fSYS_TRACE1(SYSDEBUG_TRACE_TESTS,intEventReg); if (!intEventReg) { //should never happen llcLinkRegWrite(INTR_MASK_REG_SET_DP, llcIntInstalledMask & ~HANDLE_BY_ISR); return; } // Clear all pending interrupts serviced llcLinkRegWrite(INTERRUPT_REG_CLEAR_DP, intEventReg & ~(HANDLE_BY_ISR | LLC_INT_BIT(LLCID_INTR_OUT))); if (llcIntState == LLC_INT_STATE_WAIT_BUSRESET || llcIntState == LLC_INT_STATE_PROCESS_NORMAL || llcIntState == LLC_INT_STATE_PROCESS_SI) { if (intEventReg & LLC_INT_BIT(LLCID_BUS_RST_RXD)) //new bus reset { _llcIntEventSetState(LLC_INT_STATE_WAIT_SI_COMPLETE); llcIntEvent[LLCID_BUS_RST_RXD]++; _llcIntEventCallCallback(LLCID_BUS_RST_RXD); } } if (llcIntState == LLC_INT_STATE_WAIT_SI_COMPLETE) { if (intEventReg & LLC_INT_BIT(LLCID_BUS_INIT_OVR)) //new selfid complete { llcIntEvent[LLCID_BUS_INIT_OVR]++; _llcIntEventSetState(LLC_INT_STATE_PROCESS_SI); _llcIntEventCallCallback(LLCID_BUS_INIT_OVR); } } if (llcIntState == LLC_INT_STATE_PROCESS_NORMAL) { uint8 i; uint8 id; //only handle general items for optimization for (i = 0; i < LLCINT_EVENT_GENERAL_ITEMS; i++) { id = llcIntEventGeneral[i]; if (intEventReg & LLC_INT_BIT(id)) { llcIntEvent[id]++; _llcIntEventCallCallback(id); intEventReg &= ~LLC_INT_BIT(id); if (intEventReg == 0) break; } } } llcLinkRegWrite(INTR_MASK_REG_SET_DP, llcIntInstalledMask & ~(HANDLE_BY_ISR | LLC_INT_BIT(LLCID_INTR_OUT))); }
static HRESULT context1PostPacket(PB * pPacket,uint32 semID) { HRESULT hResult = NO_ERROR; //check if context is available, should be as we only have one thread using the context volatile POSTED_TX_CONTEXT * pContext = &postedTxState.contexts[1]; if (pContext->bPosted) { hResult = E_LAL_RESPONSE_UNEXPECTED; sysLogError(hResult, __LINE__, moduleName); return hResult; } PB_HEADER* pHeader = 0; uint32 speedCode = 0; #ifdef _LOOSE_ISO uint8 asyncStream = FALSE; #endif //_LOOSE_ISO // ML 140610: Busreset storm fix. Let's skip if we ar ein bus reset if (postedTxState.inBr) { hResult = E_LAL_BUS_RESET_IN_PROGRESS; sysLogError(hResult, __LINE__, moduleName); return hResult; } pbGetPacketHeader(pPacket, &pHeader); pbGetPacketSpeed(pPacket, &speedCode); PB_PACKETTYPE packetType; pbGetPacketType(pPacket, &packetType); pContext->header.quadlets[0] = (pHeader->quadlets[0] & 0x0000ffff); // 0:spd,tag,ch,tcode,sy pContext->header.quadlets[0]|= speedCode; #ifdef _LOOSE_ISO pbIsAsyncStreamPacket (pPacket, &asyncStream); if (asyncStream == TRUE) { pContext->header.quadlets[1] = (pHeader->quadlets[1] & 0xffff0000); // 1:data_length,reserved } else #endif //_LOOSE_ISO if (packetType == TCODE_PHY_PACKET) { pContext->header.quadlets[0] = ((uint32)TCODE_LLC_SPECIFIC) << SHIFT_TCODE; pContext->header.quadlets[1] = pHeader->quadlets[0]; pContext->header.quadlets[2] = ~pHeader->quadlets[0]; } else { pContext->header.quadlets[0] |= LLC_SOURCEID_NODEID; pContext->header.quadlets[1] = (pHeader->quadlets[0] & 0xffff0000); // 1:dstId,destination_offsetHigh pContext->header.quadlets[1] |= (pHeader->quadlets[1] & 0x0000ffff); pContext->header.quadlets[2] = pHeader->quadlets[2]; // 2:destination_offsetLow pContext->header.quadlets[3] = pHeader->quadlets[3]; // 3:data_length,extended_tcode } hResult = lhlGetHeaderQuadSizeFromTCode(LHL_TX, packetType, (uint16 *)&pContext->headerLen); if (hResult != NO_ERROR) return hResult; uint32 payloadNumBytes=0; pbGetPayload(pPacket, (void **)&pContext->pPayload); pbGetPayloadSize(pPacket, &payloadNumBytes); //Ugly, the payload is not always refering to the outgoing packet. if ((packetType==PB_TYPE_READ_REQUEST) || (packetType==PB_TYPE_READ_REQUEST_QUADLET) ||(packetType==PB_TYPE_WRITE_RESPONSE) || (packetType==TCODE_PHY_PACKET)) payloadNumBytes=0; //Another hack as the read resp payload should always be one quadlet even in case of error if (packetType==PB_TYPE_READ_RESPONSE_QUADLET) payloadNumBytes=4; pContext->payloadLen = (payloadNumBytes+3)>>2; // ML 140610: Busreset storm fix. There is potentially a race condition here if // Isr or Dsr comes here. Fixed with interrupt disable. TCInterruptGlobalDisable(); if (postedTxState.inBr) { TCInterruptGlobalEnable(); hResult = E_LAL_BUS_RESET_IN_PROGRESS; sysLogError(hResult, __LINE__, moduleName); return hResult; } pContext->semID = semID; pContext->bPosted = TRUE; fSYS_TRACE1(SYSDEBUG_TRACE_TESTS,0); llcLinkRegWrite(INTERRUPT_REG_SET_DP, LLC_INT_BIT(LLCID_ASY_TX_CMPL)); TCInterruptGlobalEnable(); return hResult; }