Beispiel #1
0
HRESULT nciCBGeneric(PB *packetBlock, uint32 nciCBtype)
{
	HRESULT			hResult = NO_ERROR;
	uint32			numBytes = 0;
	uint16			i;
	PB_HEADER		*pHeader = NULL;
	QUADLET			*pPayload = NULL;
	QUADLET			*pRespPayload = NULL;
	PB*				respPacket = NULL;
	PB_PACKETTYPE	packetType = PB_TYPE_UNDEF;
	PB_LOCKTYPE		lockType = PB_LOCKTYPE_NONE;
	RCODE_1394		rCode = RSP_ADDRESS_ERROR;
	OFFSET_1394		destOffset;
	uint16			reqType = LHL_REQ_READ;

	hResult = pbGetPacketHeader(packetBlock, &pHeader);
	if (hResult != NO_ERROR) return hResult;
	hResult = pbGetPacketType(packetBlock, &packetType);
	if (hResult != NO_ERROR) return hResult;
	hResult = pbGetLockType(packetBlock, &lockType);
	if (hResult != NO_ERROR) return hResult;
	hResult = pbGetPayload(packetBlock, (void **) &pPayload);
	if (hResult != NO_ERROR) return hResult;

	// no broadcasts supported here
	if (pbPacketIsBroadcast(packetBlock))
	{
		return hResult;
	}

	switch (packetType)
	{
		case PB_TYPE_READ_REQUEST_QUADLET:
		case PB_TYPE_READ_REQUEST:
			reqType = LHL_REQ_READ;
			break;
		case PB_TYPE_WRITE_REQUEST_QUADLET:
		case PB_TYPE_WRITE_REQUEST:
			reqType = LHL_REQ_WRITE;
			break;
		case PB_TYPE_LOCK_REQUEST:
			reqType = LHL_REQ_LOCK;
			break;
	}

	switch (packetType)
	{
		case PB_TYPE_READ_REQUEST_QUADLET:
		case PB_TYPE_WRITE_REQUEST_QUADLET:
			numBytes = 4;
			break;
		case PB_TYPE_READ_REQUEST:
		case PB_TYPE_WRITE_REQUEST:
		case PB_TYPE_LOCK_REQUEST:
			hResult = pbGetDataLen(packetBlock, &numBytes);
			if (hResult != NO_ERROR) return hResult;
			break;
	}

	hResult = pbGetDestinationOffset(packetBlock, &destOffset);
	if (hResult != NO_ERROR) return hResult;

	switch (nciCBtype)
	{
		case NCI_CB_ARCH_SPACE:
			switch (packetType)
			{
				case PB_TYPE_READ_REQUEST_QUADLET:
				case PB_TYPE_READ_REQUEST:
				case PB_TYPE_WRITE_REQUEST_QUADLET:
				case PB_TYPE_WRITE_REQUEST:
					if (destOffset.Low + numBytes <= CSR_ARCH_SPACE_END + 1)
					{
						QUADLET		**pData = NULL;
						uint32		respLen = 0;

						switch (packetType)
						{
							case PB_TYPE_READ_REQUEST_QUADLET:
							case PB_TYPE_READ_REQUEST:
								pData = &pRespPayload;
								respLen = numBytes;
								break;
							case PB_TYPE_WRITE_REQUEST_QUADLET:
							case PB_TYPE_WRITE_REQUEST:
								pData = &pPayload;
								respLen = 0;
								break;
						}

						hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) respLen, NULL, PB_CREATE_NCI_CB);
						if (hResult != NO_ERROR) return hResult;

						hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
						if (hResult != NO_ERROR) return hResult;

						for (i = 0; i < numBytes / 4; i++)
						{
							hResult = lhlLLCHandleCSR(destOffset, 4, *pData + i, reqType);
							if (hResult != NO_ERROR)
							{
								break;
							}
							destOffset.Low += 4;
						}
						if (hResult == NO_ERROR)
						{
							rCode = RSP_COMPLETE;
						}
						numBytes = respLen;
					}
				break;
			}
			break;

		case NCI_CB_SB_SPACE:
			switch (destOffset.Low)
			{
				case CSR_SB_CYCLE_TIME:
				case CSR_SB_BUS_TIME:
				case CSR_SB_BUSY_TIME_OUT:
					switch (packetType)
					{
						case PB_TYPE_READ_REQUEST_QUADLET:
							hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
							if (hResult != NO_ERROR) return hResult;

							hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
							if (hResult != NO_ERROR) return hResult;

							rCode = lhlWatchTransRead(destOffset.Low, pRespPayload);
							break;

						case PB_TYPE_WRITE_REQUEST_QUADLET:
							if (numBytes == 4) // only allow quadlet write
							{
									hResult = pbCreateDuplicatePacketWithSize (packetBlock, &respPacket, (uint16) 0, NULL, PB_CREATE_NCI_CB);
									if (hResult != NO_ERROR) return hResult;

									rCode = lhlWatchTransWrite(destOffset.Low, pPayload[0]);
							}

							break;
					}
					break;
				case CSR_SB_BM_ID:
				case CSR_SB_BW_AVAIL:
				case CSR_SB_CH_AVAIL_HI:
				case CSR_SB_CH_AVAIL_LO:
				case CSR_SB_BROADCAST_CH:
#ifdef _IRMC_CAPS
					if (nciIRMIsThisNodeIRM())
					{
						// handle IRM Registers here
						switch (packetType)
						{
							case PB_TYPE_READ_REQUEST_QUADLET:
								hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
								if (hResult != NO_ERROR) return hResult;

								hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
								if (hResult != NO_ERROR) return hResult;

								rCode = nciIRMRead(destOffset.Low, pRespPayload);
								break;

							case PB_TYPE_LOCK_REQUEST:
								if (numBytes == 8) // only allow quadlet lock
								{
									if (lockType == PB_LOCKTYPE_COMPARE_SWAP)
									{
										uint32		lockArg = pPayload[0];
										uint32		lockData = pPayload[1];

										// response payload length is 1/2 size of request packet
										numBytes /= 2;
										hResult = pbCreateDuplicatePacketWithSize (packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
										if (hResult != NO_ERROR) return hResult;

										hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
										if (hResult != NO_ERROR) return hResult;

										rCode = nciIRMLock(destOffset.Low, lockArg, lockData, pRespPayload);
									}
								}
								break;
							case PB_TYPE_WRITE_REQUEST:
								if (numBytes == 4) // only allow quadlet lock
								{
										hResult = pbCreateDuplicatePacketWithSize (packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
										if (hResult != NO_ERROR) return hResult;

										rCode = nciIRMWrite(destOffset.Low, pPayload[0]);
								}
								break;
						}
					}
#endif //_IRMC_CAPS
					break;
			}
			break;
	
		case NCI_CB_CONFIG_ROM:
			switch (packetType)
			{
				case PB_TYPE_READ_REQUEST_QUADLET:
				case PB_TYPE_READ_REQUEST:
					if ((destOffset.Low >= CSR_ROM_SPACE_START) && 
						(destOffset.Low + numBytes <= CSR_ROM_SPACE_START + csrGetConfigROMQuadletSize() * 4))
					{
						hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
						if (hResult != NO_ERROR) return hResult;

						hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
						if (hResult != NO_ERROR) return hResult;

						for (i = 0; i < numBytes / 4; i++)
						{
							pRespPayload[i] = csrReadConfigROMQuadlet(destOffset.Low + (i * 4));
						}
						rCode = RSP_COMPLETE;
					}
					break;
			}
			break;

#ifdef _BMC_CAPS
		case NCI_CB_TOPOLOGY_MAP:
			switch (packetType)
			{
				case PB_TYPE_READ_REQUEST_QUADLET:
				case PB_TYPE_READ_REQUEST:
					if (destOffset.Low + numBytes <= CSR_TOPOLOGY_MAP_END + 1)
					{
						uint32	index = (destOffset.Low - CSR_TOPOLOGY_MAP_START) / 4;
						BOOL	bBusMaster = TRUE;

						hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
						if (hResult != NO_ERROR) return hResult;

						hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
						if (hResult != NO_ERROR) return hResult;

						for (i = 0; i < numBytes / 4; i++)
						{
							hResult = nciBMGetTopologyMapIndex(bBusMaster, index + i, &(pRespPayload[i]));
							if (hResult != NO_ERROR)
							{
								break;
							}
						}
						if (hResult == NO_ERROR)
						{
							rCode = RSP_COMPLETE;
						}
					}
					break;
			}
			break;

		case NCI_CB_SPEED_MAP:
			switch (packetType)
			{
				case PB_TYPE_READ_REQUEST_QUADLET:
				case PB_TYPE_READ_REQUEST:
					if (destOffset.Low + numBytes <= CSR_SPEED_MAP_END + 1)
					{
						uint32	index = (destOffset.Low - CSR_SPEED_MAP_START) / 4;
						BOOL	bBusMaster = TRUE;

						hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB);
						if (hResult != NO_ERROR) return hResult;

						hResult = pbGetPayload(respPacket, (void **) &pRespPayload);
						if (hResult != NO_ERROR) return hResult;

						for (i = 0; i < numBytes / 4; i++)
						{
							hResult = nciBMGetSpeedMapIndex(bBusMaster, index + i, &(pRespPayload[i]));
							if (hResult != NO_ERROR)
							{
								break;
							}
						}
						if (hResult == NO_ERROR)
						{
							rCode = RSP_COMPLETE;
						}
					}
					break;
			}
			break;
#endif //_BMC_CAPS

		default:
			hResult = E_BAD_INPUT_PARAMETERS;
			sysLogError(hResult, __LINE__, moduleName);
			return hResult;
	}

	if (rCode != RSP_COMPLETE)
	{
		lhlReplyErrorResponse(packetBlock, rCode, TRUE);
		hResult = (HRESULT) (E_LHL_RSP_BASE + rCode);
	}
	else
	{
		switch (packetType)
		{
			case PB_TYPE_READ_REQUEST_QUADLET:
			case PB_TYPE_READ_REQUEST:
				hResult = lhlSendReadResponse(respPacket, rCode, (uint16) numBytes, pRespPayload);
				break;
			case PB_TYPE_WRITE_REQUEST_QUADLET:
			case PB_TYPE_WRITE_REQUEST:
				hResult = lhlSendWriteResponse(respPacket, rCode);
				break;
			case PB_TYPE_LOCK_REQUEST:
				hResult = lhlSendLockResponse(respPacket, rCode, (uint16) numBytes, pRespPayload);
				break;
		}
	}

	// clean up the resp packetBlock
	if (pbIsValid(respPacket))
	{
		pbPacketDone(respPacket, PB_DONE_NCI_CB);
	}
	
	return hResult;
}
Beispiel #2
0
 /*********************************************************
	The tx thread calls this when any transmit queue has one or more packets to transmit.
		
	the priority queue is always checked first and serviced until empty, the 
	general queue is ignored during bus reset.  this allows node handles to be 
	fixed up after a bus reset, making them transparent to the upper layers,
	unless a node has left the bus of course. this routine will call the appropriate
	send routine for request or response.
*/
static HRESULT lhlTxSndPacketPend(void)
{
	HRESULT		hResult = NO_ERROR;
	PB*			packetBlock = NULL;
	PB_HEADER 	*pHeader = NULL;
	uint32		tLabel = 0;
	uint32		tCode = 0;
	uint32		nodeAddr = 0;
	uint32 busGenCurrent = 0;
	uint32 busGenPacket = 0;

	DO_FOREVER 
	{
		// look for priority packets (non-blocking)
		hResult = lhlMsgQueueGetPacketBlock(LHL_QUEUE_PRIORITY, &packetBlock, TC_NO_WAIT);
		if (hResult != NO_ERROR) return hResult;

		if (pbIsValid(packetBlock))
		{	
			// if bus reset happened, queued requests must be thrown out
			briGetCurrentBusGeneration(&busGenCurrent);			
			pbGetBusGeneration (packetBlock, &busGenPacket);
			
			if (busGenCurrent != busGenPacket)
			{
				
				pbSwapSrcDstNodeAddr(packetBlock);

				pbSetFinalStatus(packetBlock, E_LHL_BUS_RESET_IN_PROGRESS);
				pbPacketDone(packetBlock, PB_DONE_LHL_ATX_SND_PEND_1);
				hResult = E_BRI_NEW_BUS_RESET;
				sysLogError(hResult, __LINE__, moduleName);
				return hResult;
			}
		}
		else
		{
			if (briInBusReset() == FALSE)
			{
				// if not in bus reset processing, look for general packets (non-blocking)
				hResult = lhlMsgQueueGetPacketBlock(LHL_QUEUE_GENERAL, &packetBlock, TC_NO_WAIT);
				if (hResult != NO_ERROR) return hResult;
			}
			else
			{
				DO_FOREVER
				{
					// if in bus reset processing, free for general packets (non-blocking)
					hResult = lhlMsgQueueGetPacketBlock(LHL_QUEUE_GENERAL, &packetBlock, TC_NO_WAIT);
					if (hResult != NO_ERROR) return hResult;

					if (pbIsValid(packetBlock))
					{
#if 1 
						pbSwapSrcDstNodeAddr(packetBlock);
#endif
						pbSetFinalStatus(packetBlock, E_LHL_BUS_RESET_IN_PROGRESS);
						pbPacketDone(packetBlock, PB_DONE_LHL_ATX_SND_PEND_2);
					}
					else
					{
						break; // no more packetBlocks to free
					}
				}
			}
		}

		if (pbIsValid(packetBlock))
		{
			briGetCurrentBusGeneration(&busGenCurrent);			
			pbGetBusGeneration (packetBlock, &busGenPacket);
			if (busGenCurrent != busGenPacket)
			{				
				pbSwapSrcDstNodeAddr(packetBlock);
				pbSetFinalStatus(packetBlock, E_LHL_BUS_RESET_IN_PROGRESS);
				pbPacketDone(packetBlock, PB_DONE_LHL_ATX_SND_PEND_1);
				hResult = E_BRI_NEW_BUS_RESET;
				sysLogError(hResult, __LINE__, moduleName);
				return hResult;
			}

			hResult = pbGetPacketHeader (packetBlock, &pHeader);
			if (hResult != NO_ERROR) return hResult;
			hResult = pbGetPacketTLabel (packetBlock, &tLabel);
			if (hResult != NO_ERROR) return hResult;
			hResult = pbGetPacketDstNodeAddr (packetBlock, &nodeAddr);
			if (hResult != NO_ERROR) return hResult;
			hResult = lhlPendingTxAdd(tLabel, nodeAddr, packetBlock);		// insert before send and remove if send error
			if (hResult != NO_ERROR) return hResult;    
			hResult = context1PostPacket(packetBlock,lhlTxDoneSemID);
			if (hResult != NO_ERROR)
			{
#if 1 
				pbSwapSrcDstNodeAddr(packetBlock);
#endif
				pbSetFinalStatus(packetBlock, hResult);
				pbPacketDone(packetBlock, PB_DONE_LHL_ATX_SND_PEND_3);
			}
			else
			{
				// We have now posted the write, the semaphore will be signaled
				uint8	matchResponse = FALSE; // error in sending req/rsp - match corresponding type in PendingTx
				pbIsResponsePacket(packetBlock, &matchResponse);

				hResult = TCSemaphoreWait(lhlTxDoneSemID);
				
				tCode = (pHeader->quadlets[0] & MASK_TCODE) >> SHIFT_TCODE;
				lhlTxPacketDoneLLC(tLabel, tCode, nodeAddr, matchResponse);
			}
		}
		else
		{
			break; // no more packets to send
		}
	}
Beispiel #3
0
static HRESULT mixer8firewireCoreCallback(PB *packetBlock)
{
	HRESULT hResult = NO_ERROR;
	PB_HEADER		*pHeader = NULL;
	PB_PACKETTYPE	packetType = PB_TYPE_UNDEF;
	PB_LOCKTYPE		lockType;
	OFFSET_1394		OffSetDest;
	uint32			payloadSize = 0;
	uint32			RegionOffSet = 0;	
	QUADLET			*pPayload = NULL;

	hResult = pbGetPacketHeader (packetBlock, &pHeader);
	if (hResult != NO_ERROR) return hResult;
	hResult = pbGetPacketType(packetBlock,&packetType);
	if (hResult != NO_ERROR) return hResult;
	hResult = pbGetDestinationOffset(packetBlock, &OffSetDest);
	if (hResult != NO_ERROR) return hResult;

	RegionOffSet = OffSetDest.Low - MIXER8_BASE_START;	

	hResult = pbGetDataLen(packetBlock,&payloadSize);
	if(hResult != NO_ERROR) 
		return hResult;	

	if (packetType == PB_TYPE_WRITE_REQUEST_QUADLET)
	{
		hResult = pbGetPayload(packetBlock, (void **)&pPayload);
		if (hResult != NO_ERROR) return hResult;
		hResult = pbGetDataLen(packetBlock,&payloadSize);
		if (hResult != NO_ERROR) return hResult;
		payloadSize = 4;

		if(mixer8firewireCheckForWrite(RegionOffSet))
		{
			if (RegionOffSet == (MIXER8_OFFSET(CurrentConfiguration)))
			{
				if(mixer8CheckValidConfiguration((uint32)*pPayload))
				{
					memcpy((uint32*) ((int)&mixer8 + (int)RegionOffSet), pPayload, payloadSize);
					hResult = lalReplyWriteResponse(packetBlock, RSP_COMPLETE, TRUE);
					TCSemaphoreSignal(mixer8SemID);
				}
				else
				{
					hResult = lalReplyWriteResponse(packetBlock, RSP_DATA_ERROR, TRUE);
				}
			}
			else
			{
				memcpy((uint32*) ((int)&mixer8 + (int)RegionOffSet), pPayload, payloadSize);
				hResult = lalReplyWriteResponse(packetBlock, RSP_COMPLETE, TRUE);
				TCSemaphoreSignal(mixer8SemID);
			}
		}
		else
		{
			hResult = lalReplyWriteResponse(packetBlock, RSP_ADDRESS_ERROR, TRUE);			
		}		
	}
	if (packetType == PB_TYPE_WRITE_REQUEST)
	{
		hResult = pbGetPayload(packetBlock, (void **) &pPayload);
		if (hResult != NO_ERROR) return hResult;
		hResult = pbGetDataLen(packetBlock,&payloadSize);
		if (hResult != NO_ERROR) return hResult;

		if(mixer8firewireCheckForBulkWrite(RegionOffSet,payloadSize))
		{			
			memcpy((uint32*) ((int)&mixer8 + (int)RegionOffSet), pPayload, payloadSize);
			hResult = lalReplyWriteResponse(packetBlock, RSP_COMPLETE, TRUE);
			TCSemaphoreSignal(mixer8SemID);
		}
		else
		{
			hResult = lalReplyWriteResponse(packetBlock, RSP_ADDRESS_ERROR, TRUE);
		}
	}

	if (packetType == PB_TYPE_READ_REQUEST)
	{
		hResult = pbGetDataLen(packetBlock,&payloadSize);
		if (hResult != NO_ERROR) return hResult;

		hResult = lalReplyReadResponse(packetBlock, RSP_COMPLETE, (uint16) payloadSize,
			(uint32*) ((int)&mixer8 + (int)RegionOffSet), TRUE);
	}

	if (packetType == PB_TYPE_READ_REQUEST_QUADLET)
	{
		payloadSize = 4;
		hResult = lalReplyReadResponse(packetBlock, RSP_COMPLETE, (uint16) payloadSize,
			(uint32*) ((int)&mixer8 + (int)RegionOffSet), TRUE);
	}

	if (packetType == PB_TYPE_LOCK_REQUEST)
	{
		hResult = pbGetLockType(packetBlock, &lockType);
		if (hResult != NO_ERROR) return hResult;
		hResult = pbGetDataLen(packetBlock,&payloadSize);
		if (hResult != NO_ERROR) return hResult;
		hResult = pbGetPayload(packetBlock, (void **) &pPayload);
		if (hResult != NO_ERROR) return hResult;

		hResult = lalReplyLockResponse(packetBlock, RSP_COMPLETE, (uint16)payloadSize, pPayload, TRUE);
	}

	return hResult;
}
Beispiel #4
0
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;
}