Beispiel #1
0
Datei: ads.c Projekt: gass/libads
/**
 * \brief Builds the necessary headers and analises the ADSserver ADSstate response
 * This is an interface to AdsAPI.c.
 * Used by AdsSyncReadStateReq().
 * \param dc ADSConection handler
 * \param ADSstate Address of a variable that will receive the ADS status (see data type ADSSTATE).
 * \param devState Address of a variable that will receive the device status. 
 * \return Error code
 */
int ADSreadState(ADSConnection * dc,
				 unsigned short *ADSstate,
				 unsigned short *devState)
{
	AMSheader 			*h1;
//	AMS_TCPheader 		*h2; not used
	ADSpacket 			*p1;
	ADSpacket 			*p2;
	ADSstateResponse 	*StateResponse;
	int					rc;
	int					nErr;

	MsgOut(MSG_TRACE, "ADSreadState() called\n");

	p1 = (ADSpacket *) dc->msgOut;
	h1 = &(p1->amsHeader);
//	h2 = &(p1->adsHeader); not used
	_ADSsetupAmsHeader(dc, h1);
	h1->commandId = cmdADSreadState;
	h1->dataLength = 0;
	p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength;
	p1->adsHeader.reserved = 0;
	MsgAnalyzePacket("ADSreadState()", p1);

	/* sends the the packet */
	rc = _ADSWritePacket(dc->iface, p1, &nErr);
	if(rc <= 0){
#ifdef LOG_ALL_MESSAGES
		syslog(LOG_USER | LOG_ERR, "ADSreadState() failed().");
#endif
		MsgOut(MSG_ERROR, "ADSreadState failed().\n");
		return( _ADStranslateWrError(rc, nErr));
	}

	/*Read the answer */
	dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr);
	MsgDumpPacket("ADSreadState()", dc->msgIn, dc->AnswLen);
	MsgAnalyzePacket("ADSreadState()", (ADSpacket*)dc->msgIn);
	if (dc->AnswLen > 0 && nErr == 0 ) {
		p2 = (ADSpacket *) dc->msgIn;
		if (p2->amsHeader.commandId == cmdADSreadState) {
			MsgAnalyzePacket("ADSreadState()", p2);
			StateResponse = (ADSstateResponse *) (dc->msgIn + 38);
			*ADSstate = StateResponse->ADSstate;;
			*devState = StateResponse->devState;
			MsgOut(MSG_TRACE,
				   MsgStr("ADSreadState() returns 0x%x (0 means OK)\n", StateResponse->result));
			return StateResponse->result;
		}
		else
			return p2->amsHeader.errorCode;
	}

	/* if there is an error */
#ifdef LOG_ALL_MESSAGES
	syslog(LOG_USER | LOG_ERR, "ADSreadState failed().");
#endif
	MsgOut(MSG_ERROR, "ADSreadState failed().\n");
	return(_ADStranslateRdError(dc->AnswLen, nErr));
}
Beispiel #2
0
Datei: ads.c Projekt: gass/libads
/**
 * This is an interface to AdsAPI.c.
 * Used by ADSreadDeviceInfo().
 */
int ADSreadDeviceInfo(ADSConnection * dc, char *pDevName, PAdsVersion pVersion)
{
	AMSheader 		*h1;
//	AMS_TCPheader 	*h2; not used
	ADSpacket 		*p1;
	ADSpacket 		*p2;
	ADSdeviceInfo 	*DeviceInfo;
	int				rc;
	int				nErr;

	MsgOut(MSG_TRACE, "ADSreadDeviceInfo() called\n");

	p1 = (ADSpacket *) dc->msgOut;
	h1 = &(p1->amsHeader);
//	h2 = &(p1->adsHeader); not used
	_ADSsetupAmsHeader(dc, h1);
	h1->commandId = cmdADSreadDevInfo;
	h1->dataLength = 0;
	p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength;
	p1->adsHeader.reserved = 0;

	MsgAnalyzePacket("ADSreadDeviceInfo()", p1);
	rc = _ADSWritePacket(dc->iface, p1, &nErr);
	if(rc <= 0){
#ifdef LOG_ALL_MESSAGES
		syslog(LOG_USER | LOG_ERR, "ADSreadDeviceInfo() failed().");
#endif
		MsgOut(MSG_ERROR, "ADSreadDeviceInfo() failed().\n");
		return( _ADStranslateWrError(rc, nErr));
	}

	/*Reads the answer */
	dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr);
	if (dc->AnswLen > 0 && nErr == 0 ) {
		p2 = (ADSpacket *) dc->msgIn;
		if (p2->amsHeader.commandId == cmdADSreadDevInfo) {
			MsgAnalyzePacket("ADSreadDeviceInfo()", (ADSpacket*)dc->msgIn);
			DeviceInfo = (ADSdeviceInfo *) (dc->msgIn + 38);
			*pVersion = DeviceInfo->Version;
			memcpy(pDevName, DeviceInfo->name, 16);
			MsgOut(MSG_TRACE,
				   MsgStr("ADSreadDeviceInfo() returns 0x%x (0 means OK)\n", DeviceInfo->result));
			return DeviceInfo->result;
		}
		else
			return p2->amsHeader.errorCode;
	}

	/* if there is an error */
#ifdef LOG_ALL_MESSAGES
	syslog(LOG_USER | LOG_ERR, "ADSreadDeviceInfo() failed().");
#endif
	MsgOut(MSG_ERROR, "ADSreadDeviceInfo() failed().\n");
	return(_ADStranslateRdError(dc->AnswLen, nErr));

}
Beispiel #3
0
static int
MemoryTrackerTrackDeallocate( 
	IN void *pMemory )
{
	MEM_ALLOC_HDR	*pHdr;
	LIST_ITEM		*pListItem;
	int				result = 0;

	if( pMemTracker )
	{
		SpinLockAcquire( &pMemTracker->Lock );

		// Removes an item from the allocation tracking list given a pointer
		// To the user's data and returns the pointer to header referencing the
		// allocated memory block.
		pListItem = 
			QListFindFromTail( &pMemTracker->AllocList, NULL, pMemory );

		if( pListItem )
		{
			// Get the pointer to the header.
			pHdr = PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem );
#ifdef MEM_TRACK_FTR
			MemoryTrackerCheckOverrun(pHdr);
#endif	// MEM_TRACK_FTR

			if (pHdr->displaying) {
				pHdr->deallocate = TRUE;
			} else {
				// Remove the item from the list.
				MemoryTrackerUnlink(pHdr);
			}
		} else {
			int ii;
			for (ii=0; ii<unTindex; ii++) {
				if (unTAddr[ii] == pMemory) {
					unTAddr[ii] = 0; /* found it */
					break;
				}
			}
			if (ii == unTindex) {
				result = 1;
#if defined(VXWORKS)
				MsgOut( "UNMATCHED FREE %p ra=%p\n", pMemory, __builtin_return_address(0));
#else
				MsgOut( "BAD FREE %p\n", pMemory);
#endif
				DumpStack();
			}
		}
		SpinLockRelease( &pMemTracker->Lock );
	}
	return result;
}
Beispiel #4
0
static void MemoryTrackerDereference(MemoryTrackerFileName_t *trk) {
	if (trk == NULL) {
		MsgOut("Could not find reference to trk=%p\n", trk);
	} else {
		--trk->referenceCount;
	}
}
Beispiel #5
0
//
// Allocate and initialize the memory tracker object.
//
static __inline boolean
CreateMemTracker( void )
{
	MEM_TRACKER *tmp;

	if( pMemTracker )
		return TRUE;

	// Allocate the memory tracker object. Don't update global until we're done
	tmp = (MEM_TRACKER*)MEMORY_ALLOCATE_PRIV( sizeof(MEM_TRACKER), IBA_MEM_FLAG_LEGACY, TRK_TAG );

	if( !tmp )
		return FALSE;

	// Pre-initialize all objects in the memory tracker object.
	QListInitState( &tmp->AllocList );
	SpinLockInitState( &tmp->Lock );
	QListInitState( &tmp->FreeHrdList );

	// Initialize the list.
	if( !QListInit( &tmp->AllocList ) )
	{
		/* global isn't initialize, don't call Destroy func; do the clean up */
		MEMORY_DEALLOCATE_PRIV( tmp );
		return FALSE;
	}

	// Initialize the spin lock to protect list operations.
	if( !SpinLockInit( &tmp->Lock ) )
	{
		/* global isn't initialize, don't call Destroy func; do the clean up */
		QListDestroy( &tmp->AllocList );
		SpinLockDestroy( &tmp->Lock );
		MEMORY_DEALLOCATE_PRIV( tmp );
		return FALSE;
	}

	// Initialize the free list.
	if( !QListInit( &tmp->FreeHrdList ) )
	{
		/* global isn't initialize, don't call Destroy func; do the clean up */
		QListDestroy( &tmp->AllocList );
		SpinLockDestroy( &tmp->Lock );
		MEMORY_DEALLOCATE_PRIV( tmp );
		return FALSE;
	}

//	MsgOut( "\n\n\n*** Memory tracker object address = %p ***\n\n\n", tmp );
	MsgOut( "\n*** Memory tracker enabled ***\n" );

	/* NOW update the global */
	pMemTracker = tmp;

	return TRUE;
}
Beispiel #6
0
static void
MemoryTrackerShow(
		IN char *prefix, 
		IN MEM_ALLOC_HDR	*pHdr,
		IN char *suffix)
{
#if defined(VXWORKS)
	if ((int)pHdr->LineNum >= 0x00408000) {
		MsgOut( "%s%p(%u) %s ra=%p tick=%u%s\n", prefix,
				pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename,
				(void *)pHdr->LineNum, pHdr->tick, suffix );
	} else 
		MsgOut( "%s%p(%u) in file %s line %d tick=%u%s\n", prefix,
				pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename,
				pHdr->LineNum, pHdr->tick, suffix );
#else
		MsgOut( "%s%p(%u) in file %s line %d%s\n", prefix,
				pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename,
				pHdr->LineNum, suffix );
#endif
}
Beispiel #7
0
Datei: ads.c Projekt: gass/libads
/**
 * This is an internal function
 * Input: netIDstring, something like "127.0.0.1.1.1"
 * Output: id, the input converted to an AmsNetID struct.
 */
int _ADSparseNetID(const char *netIDstring, AmsNetId *id)
{
	const char *p;
	char *q;
	int i;

	MsgOut(MSG_TRACE, "_ADSparseNetID() called\n");
	q = (char *) id;
	p = netIDstring;
	for (i = 0; i < 6; i++) {
		q[i] = atoi(p);
		MsgOut(MSG_TRACE_V, MsgStr("%d:  %d\n", i, q[i]));
		p = strchr(p, '.');
		if (p == NULL){
			MsgOut(MSG_TRACE_V, MsgStr("_ADSparseNetID() returns %d\n", 5 - i));
			return 5 - i;
		}
		p++;
	}
	MsgOut(MSG_TRACE, MsgStr("_ADSparseNetID() returns %d\n", 0));
	return 0;
}
Beispiel #8
0
//
// Clean up memory tracking.
//
static __inline void
MemoryTrackStop( void )
{
#if defined(MEM_TRACK_ON)
	LIST_ITEM	*pListItem;

	if( !pMemTracker )
		return;

	if( QListCount( &pMemTracker->AllocList ) )
	{
		// There are still items in the list.  Print them out.
		MemoryDisplayUsage(1, 0, 0);
	} else {
		MsgOut( "\n*** Memory tracker stopped, no leaks detected ***\n" );
		MsgOut("IbAccess max allocations=%u bytes=%u\n",
						max_allocations, max_allocated);
	}

	// Free all allocated headers.
	SpinLockAcquire( &pMemTracker->Lock );
	while( (pListItem = QListRemoveHead( &pMemTracker->AllocList )) != NULL )
	{
		SpinLockRelease( &pMemTracker->Lock );
		MEMORY_DEALLOCATE_PRIV( PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ) );
		SpinLockAcquire( &pMemTracker->Lock );
	}
	while( (pListItem = QListRemoveHead( &pMemTracker->FreeHrdList )) != NULL )
	{
		SpinLockRelease( &pMemTracker->Lock );
		MEMORY_DEALLOCATE_PRIV( PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ) );
		SpinLockAcquire( &pMemTracker->Lock );
	}
	SpinLockRelease( &pMemTracker->Lock );

	DestroyMemTracker();
#endif	// MEM_TRACK_ON
}
Beispiel #9
0
/**
 * @brief Returns the local NetId and port number.
 * @param port  port number of an Ads port that had previously been opened with
 *				AdsPortOpenEx or AdsPortOpen..
 * @param pAddr Pointer to the structure of type AmsAddr.
 * @return Returns the function's error status.
 */
int32_t AdsGetLocalAddressEx(int32_t port, PAmsAddr pAddr)
{
	if(port <= 0){
#ifdef LOG_ALL_MESSAGES
		syslog(LOG_USER | LOG_ERR,
			   "AdsGetMeAddress(): returns 0x18, port %d not valid.", port);
#endif
		MsgOut(MSG_ERROR,
			   MsgStr("AdsGetMeAddress(): returns 0x18, port %d not valid.\n",
					  port));
		return(0x18);
	}

	return AdsGetMeAddress(pAddr, AMSPORT_R0_PLC_RTS1);
}
Beispiel #10
0
FSTATUS
BmaLoad(
	IN IBT_COMPONENT_INFO		*ComponentInfo
	)
{
	FSTATUS						status = FSUCCESS;
	extern uint32 BmaDbg;
#ifdef IB_TRACE
	extern uint32 BmaTrace;
#endif


	_DBG_ENTER_LVL(_DBG_LVL_MAIN, BMALoad);
	_DBG_INIT;

	__DBG_LEVEL__ = BmaDbg;
#ifdef IB_TRACE
	__DBG_TRACE_LEVEL__ = BmaTrace;
#endif
#if defined(IB_DEBUG) || defined(DBG)
	MsgOut ("Bma:DebugFlags = 0x%8x\n", __DBG_LEVEL__);
#endif

#if defined(VXWORKS)
	_DBG_PRINT(_DBG_LVL_MAIN,  
	(" InfiniBand Baseboard Management Class agent. Built %s %s\n",\
	__DATE__, __TIME__ ));
#else
	_DBG_PRINT(_DBG_LVL_MAIN,  
	(" InfiniBand Baseboard Management Class agent. Built %s %s\n",\
	_DBG_PTR(__DATE__), _DBG_PTR(__TIME__) ));
#endif

	_TRC_REGISTER();

	//
    // Establish dispatch entry points for the functions supported.
	//

	MemoryClear( ComponentInfo, sizeof(IBT_COMPONENT_INFO) );

	ComponentInfo->AddDevice = BmaAddDevice;
	ComponentInfo->RemoveDevice = BmaRemoveDevice;
	ComponentInfo->Unload = BmaUnload;

	
	//
    // Read any registry parameters for the driver which may be present.
	//
	//BmaReadRegistryParameters();

	//
    // This function is called to initialize the GSA subsystem. This must be 
	// called only once and if the function does not return success, the 
	// caller must unload the component containing GSA or else not use the 
	// GSA functionality since GSA will not be available.
	//
	// We are being asked to do a one-time initialization. Here we initialize 
	// the list of channel adapters as well as initialize the list of service 
	// classes as well as initialize the spin locks guarding these lists.
	//


	//
	// Allocate space for Global data
	//

	g_BmaGlobalInfo = (BMA_GLOBAL_INFO*)MemoryAllocateAndClear(
									 sizeof(BMA_GLOBAL_INFO), FALSE, BMA_TAG );
	if ( NULL != g_BmaGlobalInfo )
	{
	
		//
		// initialize global data
		//

		g_BmaGlobalInfo->binitsuccess = FALSE; 

		SpinLockInitState( &g_BmaGlobalInfo->DevListLock );
		if( !SpinLockInit( &g_BmaGlobalInfo->DevListLock ) )
		{
			_DBG_ERROR(( "Unable to initialize spin locks!\n" ));
			status = FINSUFFICIENT_RESOURCES;
			goto fail_lock;
		}

		//
		// Recv Queue and Thread
		//
		CmdThreadInitState(&g_BmaGlobalInfo->RecvThread);
		if ( ! CmdThreadCreate(&g_BmaGlobalInfo->RecvThread,
				THREAD_PRI_HIGH, "Bma", (CMD_THREAD_CALLBACK)BmaThreadCallback,
				(CMD_THREAD_CALLBACK)BmaFreeCallback, (void*)g_BmaGlobalInfo))
		{
			_DBG_ERROR(("BmaMain: Unable to Create RecvThread\n"));
			status = FINSUFFICIENT_RESOURCES;
			goto fail_thread;
		}
		

		// initialize this general service class manager with GSI
		status = iba_gsi_register_class(MCLASS_BM, 
									IB_BM_CLASS_VERSION,
									GSI_REGISTER_RESPONDER,	// Register as a Responder
									FALSE,					// No SAR cap needed
									g_BmaGlobalInfo,		// Context
									BmaSendCallback,
									BmaRecvCallback,
									&g_BmaGlobalInfo->GsaHandle);
							
		if (status != FSUCCESS)
		{
			CmdThreadDestroy(&g_BmaGlobalInfo->RecvThread);
fail_thread:
			SpinLockDestroy( &g_BmaGlobalInfo->DevListLock );
fail_lock:
			MemoryDeallocate(g_BmaGlobalInfo);
			g_BmaGlobalInfo = NULL;

			_DBG_ERROR(("BmaMain: Unable to register with GSA!!! <status %d>\n", status));

			_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);

			return status;
		}
 
	}
	else
	{
		status = FINSUFFICIENT_RESOURCES;
		_DBG_PRINT(_DBG_LVL_MAIN,("Not enough memory!\n"));
	}

    
	_DBG_LEAVE_LVL(_DBG_LVL_MAIN);
    
    return status;
}
Beispiel #11
0
Datei: ads.c Projekt: gass/libads
/**
 * This is an interface to AdsAPI.c.
 * Used by AdsSyncReadStateReq().
 */
int ADSwriteControl(ADSConnection *dc,
					int ADSstate,
					int devState,
					void *data, int length)
{
	AMSheader 				*h1;
//	AMS_TCPheader 			*h2; not used
	ADSpacket 				*p1;
	ADSpacket				*p2;
	ADSwriteControlRequest 	*rq;
	ADSwriteResponse		*wr;
	int						rc;
	int						nErr;

	MsgOut(MSG_TRACE, "ADSwriteControl() called\n");

	p1 = (ADSpacket *) dc->msgOut;
	h1 = &(p1->amsHeader);
//	h2 = &(p1->adsHeader); not used

	_ADSsetupAmsHeader(dc, h1);
	h1->commandId = cmdADSwriteControl;
	h1->dataLength = sizeof(ADSwriteControlRequest);
	p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength;
	p1->adsHeader.reserved = 0;

	rq = (ADSwriteControlRequest *) & p1->data;
	rq->ADSstate = ADSstate;
	rq->devState = devState;
	rq->length = 0;
	if (data != NULL) {
		memcpy(rq->data, data, length);
		rq->length = length;
		h1->dataLength += length;
	}

	MsgAnalyzePacket("ADSwriteControl()", p1);
	rc = _ADSWritePacket(dc->iface, p1, &nErr);
	if(rc <= 0){
#ifdef LOG_ALL_MESSAGES
		syslog(LOG_USER | LOG_ERR, "ADSwriteControl() failed().");
#endif
		MsgOut(MSG_ERROR, "ADSwriteControl() failed().\n");
		return( _ADStranslateWrError(rc, nErr));
	}


	dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr);
	p2 = (ADSpacket *) dc->msgIn;
	if (dc->AnswLen > 0 && nErr == 0 ) {
		MsgAnalyzePacket("ADSwriteControl()", p2);
		wr = (ADSwriteResponse *) (dc->msgIn + 38);
		MsgOut(MSG_TRACE,
			   MsgStr("ADSwriteControl() returns 0x%x (0 means OK)\n", wr->result));
		return wr->result;
	}
	else{
		return p2->amsHeader.errorCode;
	}
	/* if there is an error */
#ifdef LOG_ALL_MESSAGES
	syslog(LOG_USER | LOG_ERR, "ADSwriteControl() failed().");
#endif
	MsgOut(MSG_ERROR, "ADSwriteControl() failed().\n");
	return(_ADStranslateRdError(dc->AnswLen, nErr));
}
Beispiel #12
0
Datei: ads.c Projekt: gass/libads
/**
 * This is an interface to AdsAPI.c.
 * Used by AdsSyncReadWriteReqEx().
 */
int ADSreadWriteBytes(ADSConnection * dc,
                      uint32_t indexGroup, uint32_t offset,
                      uint32_t readLength, void *readBuffer,
                      uint32_t writeLength, void *writeBuffer,
                      uint32_t* pnRead)
{
	AMSheader 				*h1;
    AMS_TCPheader 			*h2;
	ADSreadWriteRequest 	*rq;
	ADSreadWriteResponse	*rr;
	int						rc;
	int						nErr;

	ADSpacket *p1 = (ADSpacket *) dc->msgOut;
	ADSpacket *p2;

	MsgOut(MSG_TRACE, "ADSreadWriteBytes() called\n");

	h1 = &(p1->amsHeader);
    h2 = &(p1->adsHeader);

	_ADSsetupAmsHeader(dc, h1);
	h1->commandId = cmdADSreadWrite;
	h1->dataLength = sizeof(ADSreadWriteRequest) - MAXDATALEN + writeLength;

    h2->length = h1->dataLength + sizeof(AMSheader);
    h2->reserved = 0;

	rq = (ADSreadWriteRequest *) & p1->data;
	rq->indexGroup = indexGroup;
	rq->indexOffset = offset;
	rq->writeLength = writeLength;
	rq->readLength = readLength;
	if (writeBuffer != NULL) {
		memcpy(rq->data, writeBuffer, writeLength);
	}
	MsgOut(MSG_PACKET_V, MsgStr("Index Group:   0x%x\n", rq->indexGroup));
	MsgOut(MSG_PACKET_V, MsgStr("Index Offset:  %d\n", rq->indexOffset));
	MsgOut(MSG_PACKET_V, MsgStr("Data length:   %d\n", rq->writeLength));

	MsgAnalyzePacket("ADSreadWriteBytes()", p1);
	rc = _ADSWritePacket(dc->iface, p1, &nErr);
	if(rc <= 0){
		MsgOut(MSG_ERROR, "ADSreadWriteBytes() failed().\n");
		return( _ADStranslateWrError(rc, nErr));
	}

	/*Reads the answer */
	dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr);
	if (dc->AnswLen > 0 && nErr == 0 ) {
		p2 = (ADSpacket *) dc->msgIn;
		if (p2->amsHeader.commandId == cmdADSreadWrite) {

			MsgAnalyzePacket("ADSreadWriteBytes()", p2);
			rr = (ADSreadWriteResponse *) (dc->msgIn + 38);
			if(rr->length > readLength){
				char strBuf[256];
				sprintf(strBuf, "ADSreadWriteBytes() failed(): Max Read: %lu, got %u", readLength, rr->length);
				return(0x705); // parameter size not correct
			}
// 			memcpy(readBuffer, rr->data, readLength);
			memcpy(readBuffer, rr->data, rr->length);
			if(pnRead != NULL)
				*pnRead = rr->length;

			MsgOut(MSG_TRACE,
				   MsgStr("ADSreadBytes() returns 0x%x (0 means OK)\n", rr->result));
			return rr->result;
		}
		else
			return p2->amsHeader.errorCode;
	}

	/* if there is an error */
	MsgOut(MSG_ERROR, "ADSreadWriteBytes() failed().\n");
	return(_ADStranslateRdError(dc->AnswLen, nErr));
}
Beispiel #13
0
Datei: ads.c Projekt: gass/libads
/**
 * This is an interface to AdsAPI.c.
 * Used by AdsSyncWriteReq().
 */
int ADSwriteBytes(ADSConnection *dc,
				  int indexGroup, int offset,
				  int length, void *data)
{
	ADSpacket			*p1;
	ADSpacket			*p2;
	AMSheader			*h1;
//	AMS_TCPheader		*h2; not used
	ADSwriteRequest		*rq;
	ADSwriteResponse	*wr;
	int					rc;
	int					nErr;

	MsgOut(MSG_TRACE, "ADSwriteBytes() called\n");

	p1 = (ADSpacket *) dc->msgOut;
	h1 = &(p1->amsHeader);
//	h2 = &(p1->adsHeader); not used

	_ADSsetupAmsHeader(dc, h1);
	h1->commandId = cmdADSwrite;
	h1->dataLength = sizeof(ADSwriteRequest) - MAXDATALEN + length;
	p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength;
	p1->adsHeader.reserved = 0;

	rq = (ADSwriteRequest *) & p1->data;
	rq->indexGroup = indexGroup;
	rq->indexOffset = offset;
	rq->length = length;
	if (data != NULL)
		memcpy(rq->data, data, length);

	MsgOut(MSG_PACKET_V, MsgStr("Index Group:   %x\n", rq->indexGroup));
	MsgOut(MSG_PACKET_V, MsgStr("Index Offset:  %d\n", rq->indexOffset));
	MsgOut(MSG_PACKET_V, MsgStr("Data length:   %d\n", rq->length));

	MsgAnalyzePacket("ADSwriteBytes()", p1);
	rc = _ADSWritePacket(dc->iface, p1, &nErr);
	if(rc <= 0){
		MsgOut(MSG_ERROR, "ADSwriteBytes() failed().\n");
		return( _ADStranslateWrError(rc, nErr));
	}

	/*Reads the answer */
	dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr);
	if (dc->AnswLen >= (sizeof(AMS_TCPheader) + sizeof(AMSheader))) {
		p2 = (ADSpacket *) dc->msgIn;
		if(nErr == 0 ) {
			MsgAnalyzePacket("ADSwriteBytes()", (ADSpacket*)dc->msgIn);
			wr = (ADSwriteResponse *) (dc->msgIn + 38);
			MsgOut(MSG_TRACE,
				MsgStr("ADSwriteBytes() returns 0x%x (0 means OK)\n", wr->result));
			return wr->result;
		}
		else
			return p2->amsHeader.errorCode;
	}

	/* if there is an error */
	MsgOut(MSG_ERROR, "ADSwriteBytes() failed().\n");
	return(_ADStranslateRdError(dc->AnswLen, nErr));
}
Beispiel #14
0
Datei: ads.c Projekt: gass/libads
/**
 * This is an interface to AdsAPI.c.
 * Used by AdsSyncReadReqEx()
 */
int ADSreadBytes(ADSConnection *dc,
                 uint32_t indexGroup, uint32_t offset,
                 uint32_t length, void *buffer,
                 uint32_t *pnRead)
{
	AMSheader 		*h1;
//	AMS_TCPheader 	*h2; not used
	ADSpacket 		*p1;
	ADSpacket 		*p2;
	ADSreadRequest  *rq;
	ADSreadResponse *rr;
	int				rc;
	int				nErr;

	MsgOut(MSG_TRACE, "ADSreadBytes() called\n");

	p1 = (ADSpacket *) dc->msgOut;
	h1 = &(p1->amsHeader);
//	h2 = &(p1->adsHeader); not used
	_ADSsetupAmsHeader(dc, h1);

	h1->commandId = cmdADSread;
	h1->dataLength = sizeof(ADSreadRequest);

	p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength;
	p1->adsHeader.reserved = 0;

	rq = (ADSreadRequest *) &p1->data;
	rq->indexGroup = indexGroup;
	rq->indexOffset = offset;
	rq->length = length;

	MsgOut(MSG_PACKET_V, MsgStr("Index Group:   0x%x\n", rq->indexGroup));
	MsgOut(MSG_PACKET_V, MsgStr("Index Offset:  %d\n", rq->indexOffset));
	MsgOut(MSG_PACKET_V, MsgStr("Data length:   %d\n", rq->length));

	MsgAnalyzePacket("ADSreadBytes", p1);

	rc = _ADSWritePacket(dc->iface, p1, &nErr);
	if(rc <= 0){
#ifdef LOG_ALL_MESSAGES
		syslog(LOG_USER | LOG_ERR, "ADSreadBytes() failed().");
#endif
        MsgOut(MSG_ERROR, "ADSreadBytes() failed().\n");
		return( _ADStranslateWrError(rc, nErr));
	}

	dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr);
	if (dc->AnswLen > 0 && nErr == 0 ) {
		p2 = (ADSpacket *) dc->msgIn;
// 		if (p2->amsHeader.commandId == cmdADSread && p2->amsHeader.errorCode == 0) {
		if (p2->amsHeader.commandId == cmdADSread) {
			MsgDumpPacket("ADSreadBytes", dc->msgIn, dc->AnswLen);
			MsgAnalyzePacket("ADSreadBytes", (ADSpacket *)dc->msgIn);

			rr = (ADSreadResponse *) (dc->msgIn + 38);
/*			if (rr->result != 0){
#ifdef LOG_ALL_MESSAGES
				syslog(LOG_USER | LOG_ERR,
					   "ADSreadBytes(): ADSreadResponse() failed with error 0x%x.",
					   rr->result);
#endif
				MsgOut(MSG_ERROR,
					   MsgStr("ADSreadBytes(): ADSreadResponse() failed with error 0x%x.\n",
							  rr->result));
				return rr->result;
			}*/
			dc->dataPointer = dc->msgIn + 46;
			dc->AnswLen = rr->length;
			if (buffer != NULL) {
				if(rr->length > length){
					char strBuf[256];
					sprintf(strBuf, "ADSreadBytes() failed(): Buffer sized %lu bytes, got %u bytes.", length, rr->length);
#ifdef LOG_ALL_MESSAGES
					syslog(LOG_USER | LOG_ERR, strBuf);
#endif
					MsgOut(MSG_ERROR, MsgStr("%s\n", strBuf));
					return(0x705); // parameter size not correct
				}
				memcpy(buffer, dc->dataPointer, rr->length);
			}
			if(pnRead != NULL)
				*pnRead = rr->length;

			MsgOut(MSG_DEVEL,
				   MsgStr("ADSreadBytes() invokeId=%d\n", p2->amsHeader.invokeId));
			MsgOut(MSG_TRACE, "ADSreadBytes() returns 0 (OK)\n");
// 			return 0;

// printf("rr->result=0x%x, p2->amsHeader.errorCode=0x%x\n", rr->result, p2->amsHeader.errorCode);

			return rr->result;
		}
		else
			return p2->amsHeader.errorCode;
	}

#ifdef LOG_ALL_MESSAGES
	syslog(LOG_USER | LOG_ERR, "ADSreadBytes() failed().");
#endif
	MsgOut(MSG_ERROR, "ADSreadBytes() failed().\n");
	return(_ADStranslateRdError(dc->AnswLen, nErr));
}
Beispiel #15
0
//
// Display memory usage.
//
void
MemoryDisplayUsage( int method, uint32 minSize, uint32 minTick )
{
#if defined(MEM_TRACK_ON)
	uint32 allocated = 0;
	uint32 allocations = 0;
	MEM_ALLOC_HDR	*pHdr;
	LIST_ITEM *item, *next, *tail, *head;
	unsigned int allocations_per_sec = 0;
	uint32 currentTime;
	boolean all = (method == 1);

	if( !pMemTracker ) {
		MsgOut( "*** IbAccess Memory Tracking is disabled ***\n" );
		return;
	}

	/* "lock" present allocations by setting
	 * displaying flag, so other allocates/frees will not affect them
	 * This gives us a snapshot while permitting the system to run
	 * while we perform the output (the output itself may use memory allocate)
	 * However, our report loop below must stay within head/tail
	 */
	SpinLockAcquire( &pMemTracker->Lock );
	tail = QListTail(&pMemTracker->AllocList);
	head = QListHead(&pMemTracker->AllocList);
	for(item = head; item != NULL; item = QListNext(&pMemTracker->AllocList, item)) {
		pHdr = PARENT_STRUCT( item, MEM_ALLOC_HDR, ListItem );
		pHdr->displaying = TRUE;
	}
	SpinLockRelease (&pMemTracker->Lock);
	
	MsgOut( "*** IbAccess Memory Usage %s minSize=%d minTick=%d ***\n", all?"All":"Unreported", minSize, minTick );

	if (head && tail) {
		item = head;
		do {
			next = QListNext(&pMemTracker->AllocList, item);
			pHdr = PARENT_STRUCT( item, MEM_ALLOC_HDR, ListItem );
	
	#ifdef MEM_TRACK_FTR
			// Check that the user did not overrun his memory allocation.
			if (pHdr->deallocate == FALSE) {
				MemoryTrackerCheckOverrun(pHdr);
			}
	#endif	// MEM_TRACK_FTR
			if ((pHdr->Bytes >= minSize) && (pHdr->tick >= minTick) && (all || (pHdr->reported == 0))) {
				// method 2 just marks all current allocations as reported, without actually reporting them
				// method 3 displays the items without changing their reported state (allows us to avoid the FREED messages)
				if (method != 2)
					MemoryTrackerShow("", pHdr, "");
				if (method != 3)
					pHdr->reported = 1;
			}
			allocated += pHdr->Bytes;
			++allocations;
			SpinLockAcquire( &pMemTracker->Lock );
			pHdr->displaying = FALSE;
			if (pHdr->deallocate) {
				MemoryTrackerUnlink(pHdr);
			}
			SpinLockRelease (&pMemTracker->Lock);
			item = next;
		} while (&pHdr->ListItem != tail && item != NULL);
	}
	currentTime = GetTimeStampSec();
	if (last_reported_secs && currentTime != last_reported_secs) {
		allocations_per_sec = (total_allocations - last_reported_allocations) / (currentTime - last_reported_secs);
	}
	last_reported_secs = currentTime;
	last_reported_allocations = total_allocations;
	MsgOut("IbAccess current allocations=%u bytes=%u max allocations=%u bytes=%u p/s=%d\n",
			allocations, allocated, max_allocations, max_allocated, allocations_per_sec);
#endif	// MEM_TRACK_ON
}
Beispiel #16
0
// called in a thread context, so can preempt
void 
GsaCompletionCallback(
	IN	void				*CaContext,
	IN	IB_HANDLE			CqHandle
	)
{
	FSTATUS					status;

	IBT_DGRM_ELEMENT		*pDgrm			= NULL;
	boolean					bRearmed		= FALSE;

	IBT_DGRM_ELEMENT_PRIV	*pDgrmPrivate;
	GSA_POST_SEND_LIST		*pPostList;
	MAD_COMMON				*pMadHdr;
	GSA_SERVICE_CLASS_INFO	*classInfo;
	IB_WORK_COMPLETION		workCompletion;
	uint8					clientId;
	uint64					portGuid;

	_DBG_ENTER_LVL(_DBG_LVL_CALLBACK, GsaCompletionCallback);
	//
	// Processing completions on the CQ is done as follows:
	//	1. Repeatedly Poll till all entries are done. 
	//	2. Rearm CQ and Poll again. If there are no more completions bail out.
	//	3. If there are completions go back to step 1.
	//	4. Skip step 2 and loop through 3.
	//
	//	We follow these steps to optimize on hardware events and race 
	//	conditions.
	//

	while (1)
	{
#ifdef SA_ALLOC_DEBUG
		if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Callback\n");
#endif
		//
		// Loop and pull out all sends and receives
		//
		while ( FSUCCESS == (status = iba_poll_cq( CqHandle, &workCompletion )) )
		{
			// fill in common values
			pDgrm = (IBT_DGRM_ELEMENT *)((uintn)MASK_WORKREQID(workCompletion.WorkReqId));

			// This should never happen. test for bad hardware
			ASSERT ( pDgrm );
			if ( NULL == pDgrm )
			{
				//
				// This is for debug only. We should remove this conditional 
				// once the problem is debugged
				//
				_DBG_ERROR (("Spurious CQ Event!!!\n"
							"\tCompleted WQE.....:(%s)\n"
							"\tSTATUS............:x%x\n"
							"\tLength............:x%x\n",
							_DBG_PTR(((WCTypeSend == workCompletion.WcType) ? \
								"Send":"Recv")),
							workCompletion.Status,
							workCompletion.Length));

				if ( WCTypeRecv == workCompletion.WcType )
				{
					_DBG_ERROR (("\n"
							"\tQP Number.........:x%x\n"
							"\tSourceLID.........:x%x\n",
							workCompletion.Req.RecvUD.SrcQPNumber,
							workCompletion.Req.RecvUD.SrcLID));
				}

				_DBG_BREAK;
				break;
			}

			// process work completion
			pDgrm->Element.Status	= workCompletion.Status;
			pDgrmPrivate			= (IBT_DGRM_ELEMENT_PRIV *)pDgrm;
					
			_DBG_PRINT (_DBG_LVL_CALLBACK,(
				"Completed %s WQE (%p):\n"
				"\tSTATUS.......:x%X (%s)\n",
				_DBG_PTR(((WCTypeSend == workCompletion.WcType) ? "Send":"Recv")), 
				_DBG_PTR(pDgrm),
				workCompletion.Status, 
				_DBG_PTR(iba_wc_status_msg(workCompletion.Status)) ));

			if (IS_SQ_WORKREQID(workCompletion.WorkReqId))
			{
#ifdef SA_ALLOC_DEBUG
				if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl\n");
#endif
			
				if (! pDgrm->Allocated) {
					_DBG_ERROR(("GSI ERROR: Send Completion for non-allocated Dgrm, discard: pDgrm=%p completion type=%d OnrecvQ=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->OnRecvQ));
					if (Gsa_debug_params.debug_level & _DBG_LVL_STORE)
					{
						ASSERT(pDgrm->Allocated);
					}
					DEBUG_ASSERT(pDgrm->Allocated);
					continue;
				}
				if (pDgrm->OnRecvQ) {
					_DBG_ERROR(("GSI ERROR: Send Completion for Recv Q Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType));
					if (Gsa_debug_params.debug_level & _DBG_LVL_STORE)
					{
						ASSERT(! pDgrm->OnRecvQ);
					}
					DEBUG_ASSERT(! pDgrm->OnRecvQ);
					continue;
				}
				if (! pDgrm->OnSendQ) {
					_DBG_ERROR(("GSI ERROR: Send Completion for non-OnSendQ Dgrm, discard: pDgrm=%p completion type=%d allocated=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->Allocated));
					if (Gsa_debug_params.debug_level & _DBG_LVL_STORE)
					{
						ASSERT(pDgrm->OnSendQ);
					}
					DEBUG_ASSERT(pDgrm->OnSendQ);
					continue;
				}
				pDgrm->OnSendQ = FALSE;


				// Handle common send completion.  Only for SendInvalid
				// will a Recv Pool Dgrm be used, we get correct pMadHdr
				// mainly so log messages below are correct
				if (((IBT_DGRM_ELEMENT_PRIV *)pDgrm)->MemPoolHandle->ReceivePool )
					pMadHdr	= (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm);
				else
					pMadHdr	= (MAD_COMMON *)GsiDgrmGetSendMad(pDgrm);

				BSWAP_MAD_HEADER ((MAD*)pMadHdr);

				pPostList		= pDgrmPrivate->Base;
				AtomicIncrementVoid( &pPostList->DgrmOut);

#ifdef ICS_LOGGING
				_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"Send Info:\n"
						"\tClass........:x%x\n"
						"\tResponseBit..:x%x\n"	
						"\tTID..........:x%"PRIx64"\n"
						"Local\n"
						"\tPathBits.....:x%X\n"
						"Remote:\n"
						"\tLID..........:x%X\n"
						"\tQP...........:x%X\n",
						(uint8)pMadHdr->MgmtClass, 
						pMadHdr->mr.s.R,
						pMadHdr->TransactionID,
						pDgrmPrivate->DgrmElement.PathBits,
						pDgrmPrivate->DgrmElement.RemoteLID,
						pDgrmPrivate->DgrmElement.RemoteQP
						));

				_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"Send Info:\n"
						"\tClass........:x%x\n"
						"\tResponseBit..:x%x\n"	
						"\tTID..........:x%"PRIx64"\n"
						"Local\n"
						"\tQKey.........:x%X\n"
						"\tServiceLvl...:x%X\n"
						"\tGlobalRoute..:%s\n",
						(uint8)pMadHdr->MgmtClass, 
						pMadHdr->mr.s.R,
						pMadHdr->TransactionID,
						pDgrmPrivate->DgrmElement.RemoteQKey,
						pDgrmPrivate->DgrmElement.ServiceLevel,
						_DBG_PTR((pDgrmPrivate->DgrmElement.GlobalRoute	? "TRUE":"FALSE") )
						));

#else
				_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"Send Info:\n"
						"\tClass........:x%x\n"
						"\tResponseBit..:x%x\n"	
						"\tTID..........:x%"PRIx64"\n"
						"Local\n"
						"\tPathBits.....:x%X\n"
						"Remote:\n"
						"\tLID..........:x%X\n"
						"\tQP...........:x%X\n"
						"\tQKey.........:x%X\n"
						"\tServiceLvl...:x%X\n"
						"\tRate.........:x%d\n"
						"\tGlobalRoute..:%s\n",
						(uint8)pMadHdr->MgmtClass, 
						pMadHdr->mr.s.R,
						pMadHdr->TransactionID,
						pDgrmPrivate->DgrmElement.PathBits,
						pDgrmPrivate->DgrmElement.RemoteLID,
						pDgrmPrivate->DgrmElement.RemoteQP,
						pDgrmPrivate->DgrmElement.RemoteQKey,
						pDgrmPrivate->DgrmElement.ServiceLevel,
						pDgrmPrivate->DgrmElement.StaticRate,
						(pDgrmPrivate->DgrmElement.GlobalRoute	? "TRUE":"FALSE") 
						));

#endif
				// Send completion for Send initiated by RMPP protocol
				if( pPostList->SARRequest)
				{
#ifdef SA_ALLOC_DEBUG
					if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: SAR\n");
#endif
					// send was posted by RMPP protocol handler
					// let it process the completion
					ProcessSARSendCompletion((MAD*)pMadHdr, pDgrm);
					continue;
				}
				
				// The datagram has been successfully sent.  Reset the
				// transaction ID to that specified by the user if this is
				// not a response.  Responses use the transaction ID from
				// the original request.
				if (MAD_IS_REQUEST((MAD*)pMadHdr))
				{
					// Restore the original TID from the user.  We cannot
					// use the context manager here, since we may have already
					// completed the request.  (The associated receive may
					// be processed before the send is completed.)
					pMadHdr->TransactionID = pDgrmPrivate->SavedSendTid;
				}

				// Free resources
				ASSERT ( pDgrmPrivate->AvHandle );
				status = PutAV( NULL, pDgrmPrivate->AvHandle );
				classInfo		= (GSA_SERVICE_CLASS_INFO*)pDgrmPrivate->MemPoolHandle->ServiceHandle;
				if ( NULL == classInfo )
				{
					// no associated class, must be a GSI initiated MAD
					DEBUG_ASSERT(pPostList->DgrmIn == AtomicRead(&pPostList->DgrmOut));
					status = DgrmPoolPut( pPostList->DgrmList );
					continue;
				}
				
				// Match all sends before callback
				if ( pPostList->DgrmIn != AtomicRead(&pPostList->DgrmOut) )
				{
#ifdef SA_ALLOC_DEBUG
					if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: more to do\n");
#endif
					_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"All sends not completed in send list:\n"
						"\tTotal.....:%d\n"
						"\tDone......:%d\n",
						pPostList->DgrmIn,
						AtomicRead(&pPostList->DgrmOut) ));

					continue;
				}

				// Call user's send completion
#ifdef SA_ALLOC_DEBUG
				if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: class callback: %p\n", classInfo->SendCompletionCallback);
#endif
				if ( classInfo->SendCompletionCallback )
				{
					(classInfo->SendCompletionCallback)(
									classInfo->ServiceClassContext,
									pPostList->DgrmList );
				} else {
					status = DgrmPoolPut( pPostList->DgrmList );
				}	// Class Callback
			} else {
				// Receive Completion processing
				uint32 post_count;
				IBT_BUFFER *Current = NULL;
				uint32 Length = 0;
#ifdef SA_ALLOC_DEBUG
				if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Recv Compl\n");
#endif
				if (pDgrm->OnSendQ) {
					_DBG_ERROR(("GSI ERROR: Recv Completion for Send Q Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType));
					if (Gsa_debug_params.debug_level & _DBG_LVL_STORE)
					{
						ASSERT(! pDgrm->OnSendQ);
					}
					DEBUG_ASSERT(! pDgrm->OnSendQ);
					continue;
				}
				if (! pDgrm->OnRecvQ) {
					_DBG_ERROR(("GSI ERROR: Recv Completion for non-OnRecvQ Dgrm, discard: pDgrm=%p completion type=%d allocated=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->Allocated));
					if (Gsa_debug_params.debug_level & _DBG_LVL_STORE)
					{
						ASSERT(pDgrm->OnRecvQ);
					}
					DEBUG_ASSERT(pDgrm->OnRecvQ);
					continue;
				}

				if (! pDgrm->Allocated) {
					_DBG_ERROR(("GSI ERROR: Completion for non-allocated Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType));
					if (Gsa_debug_params.debug_level & _DBG_LVL_STORE)
					{
						ASSERT(pDgrm->Allocated);
					}
					DEBUG_ASSERT(pDgrm->Allocated);
					pDgrm->OnRecvQ = FALSE;
					continue;
				}
				pDgrm->OnRecvQ = FALSE;


				status = DecrementGsiRecvQPostedForPortGuid(
												pDgrm->PortGuid, &post_count);
				_DBG_PRINT (_DBG_LVL_CALLBACK,("0x%"PRIx64": got post count of %u: %d\n",pDgrm->PortGuid, post_count, status));
				if (FSUCCESS == status
					&& post_count < g_GsaSettings.MinBuffersToPostPerPort
					)
				{
					// replenish to desired min
					post_count = g_GsaSettings.MinBuffersToPostPerPort - post_count;
				} else {
					// can't be sure, just repost 1
					post_count = 1;
				}
				_DBG_PRINT (_DBG_LVL_CALLBACK,("computed post count of %u\n", post_count));

				// Do not callback for QpFlush 
				if ( WRStatusWRFlushed == workCompletion.Status )
				{
#ifdef SA_ALLOC_DEBUG
				if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Recv Compl: Flush\n");
#endif
					_DBG_PRINT (_DBG_LVL_CALLBACK,("WRFlushed: skip users.\n"));
					status = DgrmPoolPut( pDgrm );	
					continue;
				}
				/* MADs can be of variable length */
				if ( workCompletion.Length > (sizeof(IB_GRH) + sizeof(MAD)))
				{
					_DBG_ERROR ((
						"Invalid MAD receive length (%d bytes)! <Discard>\n",
						workCompletion.Length ));
					status = DgrmPoolPut( pDgrm );	
					continue;
				}
				// Overload base with SAR field
				pDgrmPrivate->Base = 0;		// not a SAR Receive Dgrm
				
				// Fill in bytes rcvd
				pDgrm->TotalRecvSize = workCompletion.Length;
				pDgrm->Element.RecvByteCount = workCompletion.Length;

				// Save GUID for a post since the user may FPENDING the Dgrm
				portGuid = pDgrm->PortGuid;

				// GRH is first buffer, MAD is second
				pDgrm->Element.pBufferList->ByteCount = sizeof(IB_GRH);

				Current = pDgrm->Element.pBufferList->pNextBuffer;
				Length = workCompletion.Length - sizeof(IB_GRH);

				pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm);

				while (Length && Current)
				{
					Current->ByteCount = (pMadHdr->BaseVersion == IB_BASE_VERSION)
						? MIN(Length, IB_MAD_BLOCK_SIZE)
						: MIN(Length, STL_MAD_BLOCK_SIZE);

					if (__DBG_LEVEL__ & _DBG_LVL_PKTDUMP)
					{
						_DBG_DUMP_MEMORY(_DBG_LVL_PKTDUMP, ("Recv GSI MAD Packet"),
								Current->pData,
								MIN(Current->ByteCount, Length));
					}

					Length -= Current->ByteCount;
					Current = Current->pNextBuffer;
				}

				BSWAP_MAD_HEADER ((MAD*)pMadHdr);
#ifdef ICS_LOGGING
				_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"Receive Info:\n"
						"\tClass........:x%x\n"
						"\tResponseBit..:x%x\n"
						"\tTID..........:x%"PRIx64"\n"
						"Local\n"
						"\tPathBits.....:x%X\n"
						"Remote:\n"
						"\tLID..........:x%X\n"
						"\tQP...........:x%X\n",
						(uint8)pMadHdr->MgmtClass, 
						pMadHdr->mr.s.R,
						pMadHdr->TransactionID,
						workCompletion.Req.RecvUD.DestPathBits,
						workCompletion.Req.RecvUD.SrcLID,
						workCompletion.Req.RecvUD.SrcQPNumber
						));
				_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"Receive Info:\n"
						"\tClass........:x%x\n"
						"\tResponseBit..:x%x\n"
						"\tTID..........:x%"PRIx64"\n"
						"Remote:\n"
						"\tPKeyIndex....:x%X\n"
						"\tServiceLvl...:x%X\n"
						"\tGlobalRoute..:%s\n",
						(uint8)pMadHdr->MgmtClass, 
						pMadHdr->mr.s.R,
						pMadHdr->TransactionID,
						workCompletion.Req.RecvUD.PkeyIndex,
						workCompletion.Req.RecvUD.ServiceLevel,
						_DBG_PTR((workCompletion.Req.RecvUD.Flags.s.GlobalRoute ? "TRUE":"FALSE"))
						));
				
#else
				_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"Receive Info:\n"
						"\tClass........:x%x\n"
						"\tResponseBit..:x%x\n"
						"\tTID..........:x%"PRIx64"\n"
						"Local\n"
						"\tPathBits.....:x%X\n"
						"Remote:\n"
						"\tLID..........:x%X\n"
						"\tQP...........:x%X\n"
						"\tPKeyIndex....:x%X\n"
						"\tServiceLvl...:x%X\n"
						"\tGlobalRoute..:%s\n",
						(uint8)pMadHdr->MgmtClass, 
						pMadHdr->mr.s.R,
						pMadHdr->TransactionID,
						workCompletion.Req.RecvUD.DestPathBits,
						workCompletion.Req.RecvUD.SrcLID,
						workCompletion.Req.RecvUD.SrcQPNumber,
						workCompletion.Req.RecvUD.PkeyIndex,
						workCompletion.Req.RecvUD.ServiceLevel,
						(workCompletion.Req.RecvUD.Flags.s.GlobalRoute ? "TRUE":"FALSE")
						));

#endif
				// Port Number and Q pair are filled-up during 
				// Gsa's PostRecv
				pDgrm->PathBits		= workCompletion.Req.RecvUD.DestPathBits;
				pDgrm->RemoteLID	= workCompletion.Req.RecvUD.SrcLID;
				pDgrm->RemoteQP		= workCompletion.Req.RecvUD.SrcQPNumber;
				pDgrm->RemoteQKey	= QP1_WELL_KNOWN_Q_KEY;
				pDgrm->PkeyIndex	= workCompletion.Req.RecvUD.PkeyIndex;
				pDgrm->ServiceLevel	= workCompletion.Req.RecvUD.ServiceLevel;
				// IB does not have Static rate in UD LRH
				// so we can't be sure what rate of remote port is
				// we use a constant value for GSI QPs
				pDgrm->StaticRate	= IB_STATIC_RATE_GSI;
				pDgrm->GlobalRoute	= workCompletion.Req.RecvUD.Flags.s.GlobalRoute;

				if (workCompletion.Req.RecvUD.Flags.s.GlobalRoute)
				{
					IB_GRH *pGrh = GsiDgrmGetRecvGrh(pDgrm);
					BSWAP_IB_GRH ( pGrh);
					pDgrm->GRHInfo.DestGID = pGrh->SGID;
					pDgrm->GRHInfo.FlowLabel = pGrh->u1.s.FlowLabel;
					pDgrm->GRHInfo.SrcGIDIndex = 0; // BUGBUG - lookup DGID
					pDgrm->GRHInfo.HopLimit = pGrh->HopLimit;
					pDgrm->GRHInfo.TrafficClass = pGrh->u1.s.TClass;

					_DBG_PRINT (_DBG_LVL_CALLBACK,(
						"GRH Info:\n"
						"\tDGID.........:x%"PRIx64":%"PRIx64"\n"
						"\tSGID.........:x%"PRIx64":%"PRIx64"\n"
						"\tPayload......:%d bytes\n",
						pGrh->DGID.Type.Global.SubnetPrefix,
						pGrh->DGID.Type.Global.InterfaceID,
						pGrh->SGID.Type.Global.SubnetPrefix,
						pGrh->SGID.Type.Global.InterfaceID,
						pGrh->PayLen ));
				}

				//
				//TBD:
				// Chain replies to process later
				//
				//pDgrm->pNextCompDgrm
			
				// For RMPP R bit be set in all packets which compose a response
				// message  Even ABORT, STOP, etc.
				// transaction ID will be consistent in all packets for
				// a given request/respone message pair.
				// R bit be 0 in all packets which compose a request message
				// event ACK, ABORT, STOP, etc

				// See if the received MAD was in response to a previously
				// sent MAD request.
                if (MAD_IS_RESPONSE((MAD*)pMadHdr))
				{
					// Response to clients.  client id was a field
					// in the transaction ID sent on wire
					clientId = (uint8)(pMadHdr->TransactionID & 0xff);
				} else {
					// This is a new request or not a request/response pair
					// TID unmodified TID is visible to client (for a request
					// TID was remotely generated and we can't modify)
					clientId = MAX_CLIENT_ID;
					status = FSUCCESS;
				}

				// Validate Attributes to be processed
				if( status == FSUCCESS )
				{
					// Does the Client want us to do RMPP protocol for it?
					if( IsSarClient( clientId, pMadHdr->MgmtClass ) )
					{
						// Process the segment.  If all segments have been
						// received, pDgrm will be updated to point to the
						// first segment.
						status = ProcessSARRecvCompletion((MAD*)pMadHdr,&pDgrm);
						if( status == FCOMPLETED )
						{
							// remove clientid from all TIDs before give to user
							IBT_ELEMENT *pElement;
							for (pElement = &pDgrm->Element; pElement != NULL; pElement = pElement->pNextElement)
							{
								// first buffer is GRH, 2nd is start of MAD
								RemoveClientIdFromTID(
									(MAD_COMMON *)
									pElement->pBufferList->pNextBuffer->pData);
							}

							// adjust pMadHdr to be first in list of Dgrms,
							// pDgrm could have been changed by SAR processing
							pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm);
						}
					} else {
						// No SAR is needed.

						// remove clientid from TID before give to user
						RemoveClientIdFromTID(pMadHdr);
						status = FCOMPLETED;
					}

					// Notify the user of fully received MADs.
					if( status == FCOMPLETED )
					{
						status = GsaNotifyClients( clientId, pMadHdr, pDgrm );
					}

					if (status == FNOT_FOUND)
					{
						// no client found
						if (MAD_EXPECT_GET_RESP((MAD*)pMadHdr))
						{
							// reply with a bad class version response
							GsiSendInvalid(pDgrm);
						}
						status = FREJECT;	// free dgrm below
					}
					// Free the datagram(s) if not required for SAR and not
					// being used by the client.
					if( status == FCOMPLETED || status == FREJECT )
					{
						DgrmPoolPut( pDgrm );
					}
				}

				// Post back a recv to Q 
				status = PostRecvMsgToPort( post_count, portGuid );
			}			// recv
		}				// while loop

		if ( FNOT_DONE != status )
		{
			_DBG_ERROR (("Got %s Status!!!\n", _DBG_PTR(FSTATUS_MSG(status)) ));
		}
		
		// Rearm CQ for race conditions
		if ( FALSE == bRearmed )
		{
			status = iba_rearm_cq( CqHandle, CQEventSelNextWC );						
			bRearmed = TRUE;
		} else {
			break;
		}
	}	// while 1

    _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK);
}