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

📄 templatescsi2.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
** templateThreadDefer - defer execution of a thread** Set the thread's state to INACTIVE and notify the SCSI manager of the* deferral event.** This routine is invoked when a re-selection event occurs.** RETURNS: N/A*/LOCAL void templateThreadDefer    (    TEMPLATE_THREAD * pThread    )    {    SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;        SCSI_DEBUG_MSG ("templateThreadDefer: thread 0x%08x deferred\n",		    (int) pThread, 0, 0, 0, 0, 0);    templateThreadStateSet (pThread, SCSI_THREAD_INACTIVE);    scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DEFERRED);    }    	/********************************************************************************* templateThreadFail - complete execution of a thread, with error status** Set the thread's status and errno according to the type of error.  Set* the thread's state to INACTIVE, and notify the SCSI manager of the* completion event.** RETURNS: N/A*/LOCAL void templateThreadFail    (    TEMPLATE_THREAD * pThread,    int             errNum    )    {    SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;        SCSI_DEBUG_MSG ("templateThreadFail: thread 0x%08x failed (errno = %d)\n",		    (int) pThread, errNum, 0, 0, 0, 0);    pScsiThread->status = ERROR;    if (pScsiThread->state == SCSI_THREAD_ABORTING)	pScsiThread->errNum = S_scsiLib_ABORTED;    else    	pScsiThread->errNum = errNum;        templateThreadStateSet (pThread, SCSI_THREAD_INACTIVE);    scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);    }    	/******************************************************************************** templateThreadStateSet - set the state of a thread** This is really just a place-holder for debugging and possible future* enhancements such as state-change logging.** RETURNS: N/A*/LOCAL void templateThreadStateSet    (    TEMPLATE_THREAD *   pThread,		/* ptr to thread info */    SCSI_THREAD_STATE state    )    {    SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;        SCSI_DEBUG_MSG ("templateThreadStateSet: thread 0x%08x: %d -> %d\n",		    (int) pThread, pScsiThread->state, state, 0, 0, 0);    pScsiThread->state = state;    }/********************************************************************************* templatePhaseMismatch - recover from a SCSI bus phase mismatch** This routine does whatever is required to keep the pointers, counts, etc.* used by task-level software in step when a SCSI phase mismatch occurs.** The interrupt-level mismatch processing has stored the phase of the* information transfer before the mismatch, and the number of bytes* remaining to be transferred.  See "templateRemainderGet()".** Note that the only phase mismatches supported at this level are:** 1) during data in/out phases - presumably because the target has* transferred as much data as it intends to before sending a message* in (typically DISCONNECT or COMMAND COMPLETE).  Recovery consists* of updating the active data pointer/count according to the number* of data bytes actually transferred before the mismatch.** 2) during a message out phase - presumably because the target does not* understand our outgoing message and is sending a MESSAGE REJECT* message, or similar.  No recovery is needed here - it's all done* when the MESSAGE REJECT message has been received (see routine* "scsiMsgOutReject()").** 3) during a message in phase - presumably because we have asserted ATN* to abort or reject an incoming message.  No recovery is needed here -* it's done by the thread management code, which should have enough* state information to know what to do.** RETURNS: OK, or ERROR for an unsupported or invalid phase** NOMANUAL*/LOCAL STATUS templatePhaseMismatch    (    TEMPLATE_THREAD  * pThread,		/* ptr to thread info           */    int              phase,		/* bus phase before mismatch    */    UINT             remCount		/* # bytes not yet transferred  */    )    {    SCSI_THREAD *pScsiThread = (SCSI_THREAD *) pThread;    UINT xferCount;    /* TODO - compute nbr of bytes actually transferred. */    xferCount = 1024 - remCount; /* DUMMY CODE */    switch (phase)	{	case SCSI_DATA_IN_PHASE:	case SCSI_DATA_OUT_PHASE:	    pScsiThread->activeDataAddress += xferCount;	    pScsiThread->activeDataLength  -= xferCount;	    	    SCSI_DEBUG_MSG ("templatePhaseMismatch: data transfer aborted "			    "(%d bytes transferred).\n",			    xferCount, 0, 0, 0, 0, 0);	    break;	    	case SCSI_MSG_OUT_PHASE:	    SCSI_DEBUG_MSG("templatePhaseMismatch: message out aborted "			   "(%d of %d bytes sent).\n",			   pScsiThread->pScsiCtrl->msgOutLength,			   pScsiThread->pScsiCtrl->msgOutLength - remCount,			   0, 0, 0, 0);	    break;	    	case SCSI_MSG_IN_PHASE:	    SCSI_DEBUG_MSG("templatePhaseMismatch: message in aborted "			   "(%d bytes received).\n",			   pScsiThread->pScsiCtrl->msgInLength,			   0, 0, 0, 0, 0);	    break;	case SCSI_COMMAND_PHASE:	case SCSI_STATUS_PHASE:	    SCSI_ERROR_MSG ("templatePhaseMismatch: unsupported phase (%d).\n",			    phase, 0, 0, 0, 0, 0);	    return (ERROR);	    	default:	    logMsg ("templatePhaseMismatch: invalid phase (%d).\n",		    phase, 0, 0, 0, 0, 0);	    return (ERROR);        }    return (OK);    }/********************************************************************************* templateInitIdentEvent - identification thread event processing ** Parse the event type and handle it accordingly.  This may result in state* changes for the thread, state variables being updated, etc.** RETURNS: N/A*/LOCAL void templateInitIdentEvent    (    TEMPLATE_THREAD * pThread,    TEMPLATE_EVENT *  pEvent    )    {    SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;    SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;    SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;    /* Update controller msg in/out state after script completes */    pScsiCtrl->msgOutState = pThread->nMsgOutState;    pScsiCtrl->msgInState  = pThread->nMsgInState;        /* Parse script exit status; handle as necessary */    switch (pScsiEvent->type)	{	case SCSI_EVENT_RESELECTED:    	    pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;	    bcopy ((char *) pScsiCtrl->identBuf,		   (char *) pScsiThread->identMsg,		   pScsiThread->nBytesIdent);	    templateThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);    	    templateIdentInContinue (pThread);	    break;	case TEMPLATE_MESSAGE_OUT_SENT:	    /*	     *	This will be after we have sent an "ABORT (TAG)" msg.	     *	The target will disconnect any time; it may have already	     *	done so, in which case we won't be able to resume the	     *	thread, but no matter.	     */	    break;	case TEMPLATE_MESSAGE_IN_RECVD:	    /*	     *  Continue parsing the identification message.  It	     *  should by now be complete.	     *	     *	First byte of ident msg is already in ident buffer.	     *	Remaining bytes are in the normal message input buffer.	     *	This should always be a two-byte message (viz. QUEUE TAG);	     *	it would be nicer if there were a way to avoid hard-coding	     *	this.	     */	    bcopy ((char *) pScsiCtrl->msgInBuf,		   (char *) pScsiThread->identMsg + pScsiThread->nBytesIdent,		   2);	        	    pScsiThread->nBytesIdent += 2;    	    templateIdentInContinue (pThread);	    break;	case TEMPLATE_SCRIPT_ABORTED:	    SCSI_DEBUG_MSG ("templateInitIdentEvent: thread 0x%08x: aborted\n",			    (int) pThread, 0, 0, 0, 0, 0);	    break;        case SCSI_EVENT_DISCONNECTED:	    SCSI_DEBUG_MSG ("templateInitIdentEvent: thread 0x%08x:"			    "disconnected\n",			    (int) pThread, 0, 0, 0, 0, 0);	    templateThreadFail (pThread, S_scsiLib_DISCONNECTED);	    break;	    	case SCSI_EVENT_BUS_RESET:    	    SCSI_DEBUG_MSG ("templateInitIdentEvent: thread 0x%08x: bus reset\n",		    	    (int) pThread, 0, 0, 0, 0, 0);	    /* Do not try to resume this thread.  SCSI mgr will tidy up.  */	    templateThreadStateSet (pThread, SCSI_THREAD_INACTIVE);	    break;	case TEMPLATE_UNEXPECTED_DISCON:	    /* not really unexpected after an abort message ... */    	    SCSI_ERROR_MSG ("templateInitIdentEvent: thread 0x%08x: "		    	    "unexpected disconnection\n",		    	    (int) pThread, 0, 0, 0, 0, 0);	    templateThreadFail (pThread, S_scsiLib_DISCONNECTED);	    break;	    	case TEMPLATE_ILLEGAL_PHASE:	    SCSI_ERROR_MSG ("templateInitIdentEvent: thread 0x%08x: "			    "illegal phase requested.\n",			    (int) pThread, 0, 0, 0, 0, 0);	    	    templateThreadFail (pThread, S_scsiLib_INVALID_PHASE);	    break;	default:	    logMsg ("templateInitIdentEvent: invalid event type (%d)\n",		    pScsiEvent->type, 0, 0, 0, 0, 0);	    break;	}    }    /********************************************************************************* templateResume - resume a script corresponding to a suspended thread** NOTE: the script can only be resumed if the controller is currently idle.* To avoid races, interrupts must be locked while this is checked and the* script re-started.** Reasons why the controller might not be idle include SCSI bus reset and* unexpected disconnection, both of which might occur in practice.  Hence* this is not considered to be a major software error.** RETURNS: OK, or ERROR if the controller is in an invalid state (this* should not be treated as a major software failure).*/LOCAL STATUS templateResume    (    SIOP *           pSiop,	/* ptr to controller info          */    TEMPLATE_THREAD* pThread,	/* ptr to thread info              */    TEMPLATE_SCRIPT_ENTRY entryId	/* entry point of script to resume */    )    {    STATUS status;    int    key;    /* Check validity of connection and start script if OK */    key = intLock ();    switch (pSiop->state)	{	case TEMPLATE_STATE_IDLE:	    SCSI_INT_DEBUG_MSG ("templateResume: thread: 0x%08x:"				" state %d -> %d\n",			    	(int) pThread,			    	TEMPLATE_STATE_IDLE, TEMPLATE_STATE_ACTIVE,			    	0, 0, 0);	    templateScriptStart (pSiop, pThread, entryId);	    pSiop->state = TEMPLATE_STATE_ACTIVE;	    status = OK;	    break;	case TEMPLATE_STATE_PASSIVE:	case TEMPLATE_STATE_ACTIVE:	default:	    status = ERROR;	    break;	}    intUnlock (key);    return (status);    }/********************************************************************************* templateIdentInContinue - continue incoming identification** Parse the message built up so far.  If it is not yet complete, do nothing.* If the message is complete, attempt to reconnect the thread it identifies,* and deactivate this thread (the identification thread is no longer active).* Otherwise (identification has failed), abort the identification sequence.** RETURNS: N/A*/LOCAL void templateIdentInContinue    (    TEMPLATE_THREAD * pThread    )    {    SCSI_THREAD *     pNewThread;    SCSI_THREAD *     pScsiThread = (SCSI_THREAD *) pThread;    SCSI_CTRL *       pScsiCtrl   = pScsiThread->pScsiCtrl;    SCSI_IDENT_STATUS status;    SCSI_THREAD_STATE state;    status = scsiIdentMsgParse (pScsiCtrl, pScsiThread->identMsg,			                   pScsiThread->nBytesIdent,			       	          &pScsiThread->pScsiPhysDev,				    	  &pScsiThread->tagNumber);    switch (status)	{	case SCSI_IDENT_INCOMPLETE:	    state = SCSI_THREAD_IDENT_IN;	    break;	case SCSI_IDENT_COMPLETE:	    scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_RECONNECTED);	    if ((pNewThread = scsiMgrPhysDevActiveThreadFind (				    	    	pScsiThread->pScsiPhysDev,				    	    	pScsiThread->tagNumber)) == 0)		{		state = SCSI_THREAD_IDENT_ABORTING;		}	    else		{	    	templateThreadReconnect ((TEMPLATE_THREAD *) pNewThread);	    	state = SCSI_THREAD_INACTIVE;		}	    break;	case SCSI_IDENT_FAILED:	    state = SCSI_THREAD_IDENT_ABORTING;	    break;	default:	    logMsg ("templateIdentInContinue: invalid ident status (%d)\n",    	    	    status, 0, 0, 0, 0, 0);	    state = SCSI_THREAD_INACTIVE;	    break;	}    if (state == SCSI_THREAD_IDENT_ABORTING)	templateThreadAbort ((SIOP *) pScsiCtrl, pThread);    templateThreadStateSet (pThread, state);    }/********************************************************************************* templateThreadReconnect - reconnect a thread** Restore the SCSI pointers for the thread (this really should be in a more* generic section of code - perhaps part of the SCSI manager's thread event* procesing ?).  Update the newly-connected thread's context (including* shared memory area) and resume it.  Set the thread's state to ESTABLISHED.** RETURNS: N/A** NOMANUAL*/LOCAL void templateThreadReconnect    (    TEMPLATE_THREAD * pThread    )    {    SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;    SCSI_CTRL   * pScsiCtrl   = pScsiThread->pScsiCtrl;    SIOP        * pSiop       = (SIOP *) pScsiCtrl;        SCSI_DEBUG_MSG ("templateThreadReconnect: reconnecting thread 0x%08x\n",		    (int) pThread, 0, 0, 0, 0, 0);    pScsiCtrl->pThread = pScsiThread;    /* Implied RESTORE POINTERS action: see "scsiMsgInComplete ()" */    pScsiThread->activeDataAddress = pScsiThread->savedDataAddress;    pScsiThread->activeDataLength  = pScsiThread->savedDataLength;    templateThreadUpdate (pThread);    if (templateResume (pSiop, pThread, TEMPLATE_SCRIPT_INIT_CONTINUE) != OK)	{	SCSI_ERROR_MSG ("templateThreadReconnect: failed to resume thread.\n",			0, 0, 0, 0, 0, 0);	templateThreadFail (pThread, S_scsiLib_DISCONNECTED);	return;	}    templateThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);    }

⌨️ 快捷键说明

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