⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsimgrlib.c

📁 the vxworks system kernel souce packeg.there may be something you need .
💻 C
📖 第 1 页 / 共 4 页
字号:
	    break;	}    }/********************************************************************************* scsiMgrReplyProc - reply to a client** Parse the reply type and act accordingly.** NOTE* Currently only one reply type (transaction complete) is accepted, however* this routine is intended to allow other reply types in future (e.g., to* support SCSI target mode).** RETURNS: N/A*/LOCAL void scsiMgrReplyProc    (    SCSI_CTRL  * pScsiCtrl,    SCSI_REPLY * pReply    )    {    SCSI_REPLY_TYPE type = pReply->type;    SCSI_DEBUG_MSG ("scsiMgrReplyProc: client reply: %d\n",		    type, 0, 0, 0, 0, 0);		        switch (type)	{    	case SCSI_REPLY_COMPLETE:	    scsiMgrCompleteReply (pReply);	    break;    	default:	    logMsg ("scsiMgrReplyProc: invalid action (%d) requested\n",		    type, 0, 0, 0, 0, 0);	    break;	}    }/********************************************************************************* scsiMgrActivateRequest - process an "Activate" request from a client** Start a watchdog timer for the transaction, then add the thread to the* target device's wait queue.  It will be despatched at the next opportunity.** RETURNS: N/A*/LOCAL void scsiMgrActivateRequest    (    SCSI_REQUEST * pRequest    )    {    SCSI_THREAD * pThread = pRequest->thread;        SCSI_DEBUG_MSG ("scsiMgrActivateRequest: thread 0x%08x\n",		    (int) pThread, 0, 0, 0, 0, 0);    wdStart (pThread->wdog, pThread->timeout,	          (FUNCPTR) scsiMgrTimeoutNotify,	          (int)     pThread);    scsiMgrPhysDevWaitQAdd (pThread->pScsiPhysDev, pThread);    pThread->state = SCSI_THREAD_WAITING;    }/********************************************************************************* scsiMgrRequestComplete - terminate processing of an "Activate" request** Cancel the watchdog timer associated with the thread, and post a message* requesting the client be sent a reply.** NOTE:* It might seem peculiar not to just reply directly to the client here.* The current approach allows the SCSI manager to better prioritise its* activities, and avoids a subtle race condition which could otherwise occur.** (The exact scenario is as follows: suppose a client task of higher priority* than the SCSI manager issues a SCSI command and then deletes the physical* device.  If this routine unblocked the client rather than deferring this* to the top-level loop of the SCSI manager, the client would pre-empt the* SCSI manager and could then delete a device for which the SCSI manager may* still have some outstanding housekeeping to carry out.  This would most* likely cause the SCSI manager task to fail.  Although this sounds like a* contrived and unlikely scenario, it would actually happen during SCSI* auto-configuration by the root task or the shell.)*/LOCAL void scsiMgrRequestComplete    (    SCSI_THREAD * pThread    )    {    SCSI_REPLY  reply;    SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;        wdCancel (pThread->wdog);    reply.type    = SCSI_REPLY_COMPLETE;    reply.thread  = pThread;    reply.status  = pThread->status;    reply.errNum  = pThread->errNum;    if (rngBufPut (pScsiCtrl->replyQ,		   (char *) &reply, sizeof (reply)) != sizeof (reply))	{	logMsg ("scsiMgrRequestComplete: rngBufPut failed\n",		0, 0, 0, 0, 0, 0);	}    }/******************************************************************************** scsiMgrCompleteReply - process a "Complete" reply to be sent to a client** Build an appropriate reply message and send it on the thread's message* queue.  This unblocks the client task.  Th thread contains status and* errno values associated with the reply.** RETURNS: N/A*/LOCAL void scsiMgrCompleteReply    (    SCSI_REPLY  * pReply    )    {    SCSI_THREAD * pThread = pReply->thread;    SCSI_DEBUG_MSG ("scsiMgrCompleteReply: thread 0x%08x "		    "(status: %d, errno: %d)\n",		    (int) pThread, pThread->status, pThread->errNum, 0, 0, 0);		        if (msgQSend (pThread->replyQ, (char *) pReply,		                   sizeof (SCSI_REPLY),		                   NO_WAIT,		                   MSG_PRI_NORMAL) != OK)    	{	SCSI_ERROR_MSG ("scsiMgrCompleteReply: can't post reply message "			"(errno = %d)\n", errno, 0, 0, 0, 0, 0);	}    }/******************************************************************************** scsiMgrRequestExecute - execute a SCSI request** (This routine is called by a client task to have the SCSI manager execute a* request.)** Post the request message on the SCSI manager's request queue, notifying it* that there is something there by giving its semaphore.  Wait for the SCSI* manager's reply using the message queue associated with the thread.** NOTE:* Since the SCSI manager's request queue is implemented using a ring buffer,* access by multiple clients is serialised within this routine.  This is* achieved using the controller's mutex semaphore, which is also used to* serialise access to the free thread list.  This will not cause deadlock.** The return value of this function tells the caller whether the basic* request/reply mechanism worked or not, not whether or not the request* itself succeeded.  In fact, this function should never return ERROR unless* the software has failed or data structures have been corrupted.** This function should not be called directly by application programs.** RETURNS: OK, or ERROR if the request could not be executed.** NOMANUAL*/STATUS scsiMgrRequestExecute    (    SCSI_CTRL *    pScsiCtrl,    SCSI_REQUEST * pRequest,    SCSI_REPLY *   pReply    )    {    int requestSize = sizeof (SCSI_REQUEST);    int replySize   = sizeof (SCSI_REPLY);        /*     *	Send request to SCSI manager task     */    semTake (pScsiCtrl->mutexSem, WAIT_FOREVER);    if (rngFreeBytes (pScsiCtrl->requestQ) < requestSize)	{	semGive (pScsiCtrl->mutexSem);	logMsg ("scsiMgrRequestExecute: request queue is full\n",		0, 0, 0, 0, 0, 0);	return (ERROR);	}        if (rngBufPut (pScsiCtrl->requestQ,		   (char *) pRequest, requestSize) != requestSize)	{	semGive (pScsiCtrl->mutexSem);	logMsg ("scsiMgrRequestExecute: rngBufPut failed\n",			0, 0, 0, 0, 0, 0);	return (ERROR);	}    semGive (pScsiCtrl->mutexSem);    /*     *	Notify SCSI manager that request has been posted     */    semGive (pScsiCtrl->actionSem);        /*     *  Wait for request to be executed by SCSI manager     */    if (msgQReceive (pRequest->thread->replyQ,		     (char *) pReply, replySize, WAIT_FOREVER) != replySize)	{	SCSI_DEBUG_MSG ("scsiMgrRequestExecute: msgQReceive failed "			"(errno = %d)\n",			errno, 0, 0, 0, 0, 0);	return (ERROR);	}    return (OK);    }/********************************************************************************* scsiMgrTimeoutNotify - notify the SCSI manager of a transaction timeout** Post a timeout message on the appropriate SCSI manager queue, then notify* the SCSI manager that there is something to do.** NOTE:* No access serialisation is required because timeout messages are only* posted by the timeout watchdog ISR.** RETURNS: N/A*/LOCAL void scsiMgrTimeoutNotify    (    SCSI_THREAD * pThread    )    {    SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;        SCSI_TIMEOUT timeout;    timeout.thread = pThread;    if (rngBufPut (pScsiCtrl->timeoutQ,		   (char *) &timeout, sizeof (timeout)) != sizeof (timeout))	{	logMsg ("scsiMgrTimeoutNotify: can't post timeout message\n",		0, 0, 0, 0, 0, 0);	}    semGive (pScsiCtrl->actionSem);    }/********************************************************************************* scsiMgrEventNotify - notify the SCSI manager of a SCSI (controller) event** This routine posts an event message on the appropriate SCSI manager queue,* then notifies the SCSI manager that there is a message to be accepted.** NOTE:* This routine should not be called by application programs.** No access serialization is required, because event messages are only* posted by the SCSI controller ISR. See the reference entry for * scsiBusResetNotify().** RETURNS: OK, or ERROR if the SCSI manager's event queue is full.** SEE ALSO: scsiBusResetNotify()*/STATUS scsiMgrEventNotify    (    SCSI_CTRL *  pScsiCtrl, 	/* pointer to SCSI controller structure */    SCSI_EVENT * pEvent,	/* pointer to the SCSI event */    int          eventSize	/* size of the event information */    )    {    if (rngBufPut (pScsiCtrl->eventQ, (char *) pEvent, eventSize) != eventSize)	{	logMsg ("scsiMgrEventNotify: can't post event message\n",		0, 0, 0, 0, 0, 0);	return (ERROR);	}    semGive (pScsiCtrl->actionSem);    return (OK);    }/********************************************************************************* scsiMgrBusReset - handle a controller-bus reset event ** This routine resets in turn:  each attached physical device, each target,* and the controller-finite-state machine.  In practice, this routine * implements the SCSI hard reset option.** NOTE:* This routine does not physically reset the SCSI bus; see scsiBusReset().* This routine should not be called by application programs.** RETURNS: N/A*/void scsiMgrBusReset    (    SCSI_CTRL * pScsiCtrl		/* SCSI ctrlr on which bus reset */    )    {    UINT i;    /*     *	Reset all physical devices     */    for (i = 0; i < SCSI_MAX_PHYS_DEVS; ++i)	{    	SCSI_PHYS_DEV * pScsiPhysDev = pScsiCtrl->physDevArr[i];	if (pScsiPhysDev != 0)	    scsiMgrPhysDevReset (pScsiPhysDev);	}    /*     *	Reset all SCSI targets     */    for (i = 0; i < SCSI_MAX_TARGETS; ++i)	scsiTargetReset (pScsiCtrl, i);    /*     *	Reset controller state     */    scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED);    }/********************************************************************************* scsiMgrRunnableThreadGet - find the next thread to run, if any** If the controller is active, no thread can be started.  Otherwise, find the* highest priority waiting thread by querying each physical device.  If a* runnable thread is found, do not remove it from any wait queue.** NOTE: a simple round-robin scheme is used to avoid unfairly favouring* threads from any particular physical device, when they all have equal* priority.** RETURNS: thread ptr, or 0 if no runnable thread exists*/LOCAL SCSI_THREAD * scsiMgrRunnableThreadGet    (    SCSI_CTRL * pScsiCtrl    )    {    SCSI_PRIORITY   bestPriority;    SCSI_THREAD *   pBestThread;    int             bestDevIndex;    int             devIndex;    int             i;    /*     *	Can't do anything if the controller is active !     */    if (pScsiCtrl->scsiSpecialHandler == NULL)	if (pScsiCtrl->active)	    return (0);    /*     *	Find best available thread on all existing physical devices     */    bestPriority = SCSI_THREAD_MIN_PRIORITY;    pBestThread  = 0;    bestDevIndex = 0;    devIndex = pScsiCtrl->nextDev;    for (i = 0; i < SCSI_MAX_PHYS_DEVS; ++i)	{    	SCSI_PHYS_DEV * pScsiPhysDev = pScsiCtrl->physDevArr [devIndex];	/*	 *  If this phys dev exists, and has a runnable thread with	 *  higher priority than the best so far, remember it.	 */	if (pScsiPhysDev != 0)	    {	    SCSI_THREAD * pThread;	    	    pThread = scsiMgrPhysDevRunnableThreadGet (pScsiPhysDev);	    if ((pThread != 0) &&		SCSI_IS_HIGHER_PRIORITY (pThread->priority, bestPriority))	    	{	    	bestDevIndex = devIndex;	    	bestPriority = pThread->priority;	    	pBestThread  = pThread;		}	    }	if (++devIndex >= SCSI_MAX_PHYS_DEVS)	    devIndex = 0;	}    if (pBestThread != 0) 	{	pScsiCtrl->nextDev = bestDevIndex + 1;	if (pScsiCtrl->nextDev >= SCSI_MAX_PHYS_DEVS)	    pScsiCtrl->nextDev  = 0;	}        return (pBestThread);    }/********************************************************************************* scsiMgrThreadDespatch - despatch a new thread** Remove the thread from its device's wait queue, activate it and install it* on the device's active queue.  If activation fails, complete the thread* with a suitable error code.** RETURNS: N/A*/LOCAL void scsiMgrThreadDespatch    (    SCSI_THREAD * pThread    )    {    SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev;    scsiMgrPhysDevWaitQRemove (pScsiPhysDev, pThread);        if (scsiMgrThreadActivate (pThread) != OK)	{	pThread->status = ERROR;	pThread->errNum = errno;		scsiMgrThreadComplete (pThread);	return;	}    scsiMgrPhysDevActiveQAdd  (pScsiPhysDev, pThread);    }/******************************************************************************** scsiMgrThreadComplete - complete an initiator thread** Check for contingent allegiance condition by parsing the SCSI status set* by the target device; set or clear the physical device's contingent* allegiance flag accordingly.  (This affects the access serialisation rules* used to schedule threads on the device: for more details see* "scsiMgrPhysDevRunnableThreadGet()".)** Finish processing the client's request (i.e., eventually, reply).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -