Пример #1
0
/*
 *  ======== WMD_CHNL_Close ========
 *  Purpose:
 *      Ensures all pending I/O on this channel is cancelled, discards all
 *      queued I/O completion notifications, then frees the resources allocated
 *      for this channel, and makes the corresponding logical channel id
 *      available for subsequent use.
 */
DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
{
	DSP_STATUS status;
	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;

	/* Check args: */
	if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
		status = DSP_EHANDLE;
		goto func_cont;
	}
	{
		/* Cancel IO: this ensures no further IO requests or
		 * notifications.*/
		status = WMD_CHNL_CancelIO(hChnl);
	}
func_cont:
	if (DSP_SUCCEEDED(status)) {
		/* Assert I/O on this channel is now cancelled: Protects
		 * from IO_DPC. */
		DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
		/* Invalidate channel object: Protects from
		 * CHNL_GetIOCompletion(). */
		pChnl->dwSignature = 0x0000;
		/* Free the slot in the channel manager: */
		pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
		pChnl->pChnlMgr->cOpenChannels -= 1;
		if (pChnl->hNtfy) {
			NTFY_Delete(pChnl->hNtfy);
			pChnl->hNtfy = NULL;
		}
		/* Reset channel event: (NOTE: hUserEvent freed in user
		 * context.). */
		if (pChnl->hSyncEvent) {
			SYNC_ResetEvent(pChnl->hSyncEvent);
			SYNC_CloseEvent(pChnl->hSyncEvent);
			pChnl->hSyncEvent = NULL;
		}
		/* Free I/O request and I/O completion queues:  */
		if (pChnl->pIOCompletions) {
			FreeChirpList(pChnl->pIOCompletions);
			pChnl->pIOCompletions = NULL;
			pChnl->cIOCs = 0;
		}
		if (pChnl->pIORequests) {
			FreeChirpList(pChnl->pIORequests);
			pChnl->pIORequests = NULL;
			pChnl->cIOReqs = 0;
		}
		if (pChnl->pFreeList) {
			FreeChirpList(pChnl->pFreeList);
			pChnl->pFreeList = NULL;
		}
		/* Release channel object. */
		MEM_FreeObject(pChnl);
		pChnl = NULL;
	}
	DBC_Ensure(DSP_FAILED(status) ||
		  !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
	return status;
}
Пример #2
0
/*
 *  ======== CreateChirpList ========
 *  Purpose:
 *      Initialize a queue of channel I/O Request/Completion packets.
 *  Parameters:
 *      uChirps:    Number of Chirps to allocate.
 *  Returns:
 *      Pointer to queue of IRPs, or NULL.
 *  Requires:
 *  Ensures:
 */
static struct LST_LIST *CreateChirpList(u32 uChirps)
{
	struct LST_LIST *pChirpList;
	struct CHNL_IRP *pChirp;
	u32 i;

	pChirpList = MEM_Calloc(sizeof(struct LST_LIST), MEM_NONPAGED);

	if (pChirpList) {
		INIT_LIST_HEAD(&pChirpList->head);
		/* Make N chirps and place on queue. */
		for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
		    NULL); i++) {
			LST_PutTail(pChirpList, (struct list_head *)pChirp);
		}

		/* If we couldn't allocate all chirps, free those allocated: */
		if (i != uChirps) {
			FreeChirpList(pChirpList);
			pChirpList = NULL;
		}
	}

	return pChirpList;
}
Пример #3
0
/*
 *  ======== CreateChirpList ========
 *  Purpose:
 *      Initialize a queue of channel I/O Request/Completion packets.
 *  Parameters:
 *      uChirps:    Number of Chirps to allocate.
 *  Returns:
 *      Pointer to queue of IRPs, or NULL.
 *  Requires:
 *  Ensures:
 */
static struct LST_LIST *CreateChirpList(u32 uChirps)
{
	struct LST_LIST *pChirpList;
	struct CHNL_IRP *pChirp;
	u32 i;

	pChirpList = LST_Create();

	if (pChirpList) {
		/* Make N chirps and place on queue. */
		for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
		    NULL); i++) {
			LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
		}

		/* If we couldn't allocate all chirps, free those allocated: */
		if (i != uChirps) {
			FreeChirpList(pChirpList);
			pChirpList = NULL;
		}
	}

	return pChirpList;
}
Пример #4
0
/*
 *  ======== WMD_CHNL_Open ========
 *      Open a new half-duplex channel to the DSP board.
 */
DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
			 struct CHNL_MGR *hChnlMgr, short int uMode,
			 u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
{
	DSP_STATUS status = DSP_SOK;
	struct CHNL_MGR *pChnlMgr = hChnlMgr;
	struct CHNL_OBJECT *pChnl = NULL;
	struct SYNC_ATTRS *pSyncAttrs = NULL;
	struct SYNC_OBJECT *hSyncEvent = NULL;
	/* Ensure DBC requirements:  */
	DBC_Require(phChnl != NULL);
	DBC_Require(pAttrs != NULL);
	DBC_Require(hChnlMgr != NULL);
	*phChnl = NULL;

	/* Validate Args:  */
	if (pAttrs->uIOReqs == 0) {
		status = DSP_EINVALIDARG;
	} else {
		if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
			status = DSP_EHANDLE;
		} else {
			if (uChnlId != CHNL_PICKFREE) {
				if (uChnlId >= pChnlMgr->cChannels)
					status = CHNL_E_BADCHANID;
				else if (pChnlMgr->apChannel[uChnlId] !=
					  NULL)
					status = CHNL_E_CHANBUSY;
			} else {
				/* Check for free channel */
				status = SearchFreeChannel(pChnlMgr, &uChnlId);
			}
		}
	}
	if (DSP_FAILED(status))
		goto func_end;

	DBC_Assert(uChnlId < pChnlMgr->cChannels);
	/* Create channel object:  */
	MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
	if (!pChnl) {
		status = DSP_EMEMORY;
		goto func_end;
	}
	/* Protect queues from IO_DPC: */
	pChnl->dwState = CHNL_STATECANCEL;
	/* Allocate initial IOR and IOC queues: */
	pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
	pChnl->pIORequests = CreateChirpList(0);
	pChnl->pIOCompletions = CreateChirpList(0);
	pChnl->cChirps = pAttrs->uIOReqs;
	pChnl->cIOCs = 0;
	pChnl->cIOReqs = 0;
	status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
	if (DSP_SUCCEEDED(status))
		status = NTFY_Create(&pChnl->hNtfy);

	if (DSP_SUCCEEDED(status)) {
		if (pChnl->pIOCompletions && pChnl->pIORequests &&
		   pChnl->pFreeList) {
			/* Initialize CHNL object fields:    */
			pChnl->pChnlMgr = pChnlMgr;
			pChnl->uId = uChnlId;
			pChnl->uMode = uMode;
			pChnl->hUserEvent = hSyncEvent;	/* for Linux */
			pChnl->hSyncEvent = hSyncEvent;
			/* Get the process handle */
			pChnl->hProcess = current->tgid;
			pChnl->pCBArg = 0;
			pChnl->cBytesMoved = 0;
			/* Default to proc-copy */
			pChnl->uChnlType = CHNL_PCPY;
		} else {
			status = DSP_EMEMORY;
		}
	}

	if (DSP_FAILED(status)) {
		/* Free memory */
		if (pChnl->pIOCompletions) {
			FreeChirpList(pChnl->pIOCompletions);
			pChnl->pIOCompletions = NULL;
			pChnl->cIOCs = 0;
		}
		if (pChnl->pIORequests) {
			FreeChirpList(pChnl->pIORequests);
			pChnl->pIORequests = NULL;
		}
		if (pChnl->pFreeList) {
			FreeChirpList(pChnl->pFreeList);
			pChnl->pFreeList = NULL;
		}
		if (hSyncEvent) {
			SYNC_CloseEvent(hSyncEvent);
			hSyncEvent = NULL;
		}
		if (pChnl->hNtfy) {
			NTFY_Delete(pChnl->hNtfy);
			pChnl->hNtfy = NULL;
		}
		MEM_FreeObject(pChnl);
	} else {
		/* Insert channel object in channel manager: */
		pChnlMgr->apChannel[pChnl->uId] = pChnl;
		SYNC_EnterCS(pChnlMgr->hCSObj);
		pChnlMgr->cOpenChannels++;
		SYNC_LeaveCS(pChnlMgr->hCSObj);
		/* Return result... */
		pChnl->dwSignature = CHNL_SIGNATURE;
		pChnl->dwState = CHNL_STATEREADY;
		*phChnl = pChnl;
	}
func_end:
	DBC_Ensure((DSP_SUCCEEDED(status) &&
		  MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
		  (*phChnl == NULL));
	return status;
}