📄 scsictrllib.c
字号:
status = scsiIdentMsgParse (pScsiCtrl, pThread->identMsg, pThread->nBytesIdent, &pThread->pScsiPhysDev, &pThread->tagNumber); switch (status) { case SCSI_IDENT_INCOMPLETE: state = SCSI_THREAD_IDENT_IN; break; case SCSI_IDENT_COMPLETE: scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_RECONNECTED); if ((pNewThread = scsiMgrPhysDevActiveThreadFind ( pThread->pScsiPhysDev, pThread->tagNumber)) == 0) { state = SCSI_THREAD_IDENT_ABORTING; } else { scsiCtrlThreadReconnect (pNewThread); state = SCSI_THREAD_INACTIVE; } break; case SCSI_IDENT_FAILED: state = SCSI_THREAD_IDENT_ABORTING; break; default: logMsg ("scsiCtrlIdentInContinue: invalid ident status (%d)\n", status, 0, 0, 0, 0, 0); state = SCSI_THREAD_INACTIVE; break; } if (state == SCSI_THREAD_IDENT_ABORTING) scsiCtrlThreadAbort (pScsiCtrl, pThread); scsiCtrlThreadStateSet (pThread, state); } /********************************************************************************* scsiCtrlThreadReconnect - 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 ?). Set the controller's transfer parameters for the newly * connected thread. Set the thread's state to ESTABLISHED.** RETURNS: N/A*/LOCAL void scsiCtrlThreadReconnect ( SCSI_THREAD * pThread ) { SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; SCSI_DEBUG_MSG ("scsiCtrlThreadReconnect: reconnecting thread 0x%08x\n", (int) pThread, 0, 0, 0, 0, 0); pScsiCtrl->pThread = pThread; /* * Reset controller state variables for the new thread */ pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; pScsiCtrl->msgInState = SCSI_MSG_IN_NONE; /* Implied RESTORE POINTERS action: see "scsiMsgInComplete ()" */ pThread->activeDataAddress = pThread->savedDataAddress; pThread->activeDataLength = pThread->savedDataLength; if (scsiCtrlXferParamsSet (pThread) != OK) { SCSI_ERROR_MSG ("scsiCtrlThreadReconnect: failed to set xfer params.\n", 0, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, errno); return; } scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED); }/********************************************************************************* scsiCtrlNormalXfer - initiator info transfer request event processing** Check for phase changes during message-in and message-out transfers,* handling them accordingly (neither is necessarily an error condition).* Call the appropriate handler routine for the message transfer phase* requested by the target.** RETURNS: N/A*/LOCAL void scsiCtrlNormalXfer ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { STATUS status; SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; int phase = pEvent->phase; switch (pThread->state) { case SCSI_THREAD_ESTABLISHED: case SCSI_THREAD_WAIT_COMPLETE: case SCSI_THREAD_WAIT_DISCONNECT: case SCSI_THREAD_WAIT_ABORT: break; default: logMsg ("scsiCtrlNormalXfer: thread 0x%08x: invalid state (%d)\n", (int) pThread, pThread->state, 0, 0, 0, 0); return; } SCSI_DEBUG_MSG ("scsiCtrlNormalXfer: thread 0x%08x: " "target requesting %s phase\n", (int) pThread, (int) scsiPhaseNameGet (phase), 0, 0, 0, 0); /* * Check for phase change during message in handling: this probably * results from our having asserted ATN in order to send a message out. * This would occur if we reject a partially read incoming message. * * Reset the message-in state in this case. */ if (phase != SCSI_MSG_IN_PHASE) { switch (pScsiCtrl->msgInState) { case SCSI_MSG_IN_NONE: break; default: SCSI_DEBUG_MSG ("scsiCtrlNormalXfer: phase change " "during msg in\n", 0, 0, 0, 0, 0, 0); pScsiCtrl->msgInState = SCSI_MSG_IN_NONE; break; } } /* * Check for phase change during (immediately after) message out. * * If this happens while there is a pending message out, there are * two possibilities. Either the target has not yet noticed our ATN * (i.e., no message data has yet been transferred) or it has changed * phase in mid-transfer (probably to reject the message we're sending). * In either case, the message state is left pending so that it will be * (re-)sent or rejected as appropriate. * * If it happens just after a message out has been sent, it means the * target has accepted the message. In this case the message out state * is reset, and the message out completion routine is called. */ if (phase != SCSI_MSG_OUT_PHASE) { switch (pScsiCtrl->msgOutState) { case SCSI_MSG_OUT_NONE: case SCSI_MSG_OUT_PENDING: break; case SCSI_MSG_OUT_SENT: pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; (void) scsiMsgOutComplete (pScsiCtrl, pThread); break; default: break; } } /* * Perform information transfer requested by target */ switch (phase) { case SCSI_DATA_OUT_PHASE: status = scsiCtrlDataOutAction (pScsiCtrl, pThread); break; case SCSI_DATA_IN_PHASE: status = scsiCtrlDataInAction (pScsiCtrl, pThread); break; case SCSI_COMMAND_PHASE: status = scsiCtrlCommandAction (pScsiCtrl, pThread); break; case SCSI_STATUS_PHASE: status = scsiCtrlStatusAction (pScsiCtrl, pThread); break; case SCSI_MSG_OUT_PHASE: status = scsiCtrlMsgOutAction (pScsiCtrl, pThread); break; case SCSI_MSG_IN_PHASE: status = scsiCtrlMsgInAction (pScsiCtrl, pThread); break; default: SCSI_ERROR_MSG ("scsiCtrlNormalXfer: invalid phase (%d)\n", phase, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, S_scsiLib_INVALID_PHASE); return; } if (status != OK) { SCSI_ERROR_MSG ("scsiCtrlNormalXfer: transfer failed\n", 0, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, errno); } } /********************************************************************************* scsiCtrlAbortXfer - process info. xfer request for an aborting thread** Check that the phase requested is message out. Transfer the single-byte* message out. Set the thread's state to indicate that it's waiting for the* target to disconnect after an abort message.** RETURNS: N/A*/LOCAL void scsiCtrlAbortXfer ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; if (pThread->state != SCSI_THREAD_ABORTING) { logMsg ("scsiCtrlAbortXfer: invalid state (%d)\n", pThread->state, 0, 0, 0, 0, 0); return; } if (pEvent->phase != SCSI_MSG_OUT_PHASE) { SCSI_ERROR_MSG ("scsiCtrlAbortXfer: unexpected phase (%d) " "requested during thread abort\n", pEvent->phase, 0, 0, 0, 0, 0); return; } if ((*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_MSG_OUT_PHASE, pScsiCtrl->msgOutBuf, 1) != 1) { SCSI_ERROR_MSG ("scsiCtrlAbortXfer: message out transfer failed\n", 0, 0, 0, 0, 0, 0); return; } scsiCtrlThreadStateSet (pThread, SCSI_THREAD_WAIT_ABORT); } /******************************************************************************** scsiCtrlDataOutAction - handle DATA OUT information transfer phase** Transfer out the remaining data count or the maximum possible for the* controller, whichever is the smaller. Update the active data pointer* and count to reflect the number of bytes transferred - this may be fewer* than requested, e.g. if the target requests a different phase.** RETURNS: OK, or ERROR if transfer fails.*/LOCAL STATUS scsiCtrlDataOutAction ( SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ SCSI_THREAD *pThread /* ptr to thread info */ ) { UINT xferCount; /* number of bytes transferred */ UINT maxBytes; /* max number of bytes to send */ maxBytes = min (pThread->activeDataLength, pScsiCtrl->maxBytesPerXfer); xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_DATA_OUT_PHASE, pThread->activeDataAddress, maxBytes); if (xferCount == ERROR) return (ERROR); pThread->activeDataAddress += xferCount; pThread->activeDataLength -= xferCount; return (OK); }/******************************************************************************** scsiCtrlDataInAction - handle DATA IN information transfer phase** Transfer in the remaining data count or the maximum possible for the* controller, whichever is the smaller. Update the active data pointer* and count to reflect the number of bytes transferred - this may be fewer* than requested, e.g. if the target requests a different phase.** NOTE: the "additional length byte" handling done in previous versions of* the SCSI library is unnecessary when disconnect/reconnect is supported.** SCSI requires the target to honour the initiator's maximum allocation* length, so there can never be more incoming data than was requested.* Conversely, if the target has less data to send than the initiator* expects, it will simply terminate the DATA IN transfer phase early.** Unfortunately the currently defined SCSI transaction interface does not* allow the client task to find out how many data bytes were actually* received in either case.* * RETURNS: OK, or ERROR if transfer fails.*/LOCAL STATUS scsiCtrlDataInAction ( SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ SCSI_THREAD *pThread /* ptr to thread info */ ) { UINT xferCount; /* number of bytes transferred */ UINT maxBytes; /* max number of bytes to recv */ maxBytes = min (pThread->activeDataLength, pScsiCtrl->maxBytesPerXfer); xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_DATA_IN_PHASE, pThread->activeDataAddress, maxBytes); if (xferCount == ERROR) return (ERROR); pThread->activeDataAddress += xferCount; pThread->activeDataLength -= xferCount; return (OK); }/******************************************************************************** scsiCtrlCommandAction - handle COMMAND information transfer phase** Note: it is assumed that a command transfer must be completed fully, i.e.* the target cannot disconnect. It is also assumed that the length of a* command transfer never exceeds the maximum byte count the controller can* handle.** RETURNS: OK, or ERROR if transfer fails.*/LOCAL STATUS scsiCtrlCommandAction ( SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ SCSI_THREAD *pThread /* ptr to thread info */ ) { UINT xferCount; /* number of bytes transferred */ xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_COMMAND_PHASE, pThread->cmdAddress, pThread->cmdLength); return ((xferCount == pThread->cmdLength) ? OK : ERROR); }/******************************************************************************** scsiCtrlStatusAction - handle STATUS information transfer phase** Note: it is assumed that a status transfer must be completed fully, i.e.* the target cannot disconnect. It is also assumed that the length of a* status transfer never exceeds the maximum byte count the controller can* handle.** RETURNS: OK, or ERROR if transfer fails.*/LOCAL STATUS scsiCtrlStatusAction ( SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ SCSI_THREAD *pThread /* ptr to thread info */ ) { UINT xferCount; /* number of bytes transferred */ xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_STATUS_PHASE, pThread->statusAddress, pThread->statusLength);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -