📄 scsictrllib.c
字号:
switch (pEvent->type) { case SCSI_EVENT_CONNECTED: scsiCtrlThreadConnect (pThread, pEvent); break; case SCSI_EVENT_DISCONNECTED: scsiCtrlThreadDisconnect (pThread, pEvent); break; case SCSI_EVENT_SELECTED: case SCSI_EVENT_RESELECTED: scsiCtrlThreadSelect (pThread, pEvent); break; case SCSI_EVENT_XFER_REQUEST: scsiCtrlThreadInfoXfer (pThread, pEvent); break; case SCSI_EVENT_TIMEOUT: scsiCtrlThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT); break; case SCSI_EVENT_PARITY_ERR: errnoSet (S_scsiLib_HARDWARE_ERROR); scsiCtrlThreadFail (pThread, S_scsiLib_HARDWARE_ERROR); break; case SCSI_EVENT_BUS_RESET: /* SCSI manager handles this */ scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE); break; default: logMsg ("scsiCtrlThreadEvent: invalid event type (%d)\n", pEvent->type, 0, 0, 0, 0, 0); break; } switch (pThread->state) { case SCSI_THREAD_ESTABLISHED: /* assert ATN if there is a pending message out */ if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING) { if ((*pScsiCtrl->scsiBusControl) (pScsiCtrl, SCSI_BUS_ASSERT_ATN) != OK) { SCSI_ERROR_MSG ("scsiCtrlEvent: failed to assert ATN.\n", 0, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, errno); } } break; default: break; } } /********************************************************************************* scsiCtrlThreadConnect - thread connection event processing routine** Set transfer parameters for the newly connected thread. Set the thread* state to ESTABLISHED if the whole identification message has been sent,* otherwise set its state to IDENTIFICATION OUT.** RETURNS: N/A*/LOCAL void scsiCtrlThreadConnect ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev; SCSI_TARGET * pScsiTarget = pThread->pScsiTarget; if (pThread->state != SCSI_THREAD_CONNECTING) { logMsg ("scsiCtrlThreadConnect: thread 0x%08x: invalid state (%d)\n", (int) pThread, pThread->state, 0, 0, 0, 0); return; } SCSI_DEBUG_MSG ("scsi: connected to target %d, phys dev = 0x%08x\n", pScsiTarget->scsiDevBusId, (int)pScsiPhysDev, 0, 0, 0, 0); pThread->nBytesIdent = pEvent->nBytesIdent; if (scsiCtrlXferParamsSet (pThread) != OK) { scsiCtrlThreadFail (pThread, errno); return; } if (pThread->nBytesIdent < pThread->identMsgLength) { scsiCtrlThreadStateSet (pThread, SCSI_THREAD_IDENT_OUT); } else { scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED); } }/********************************************************************************* scsiCtrlThreadDisconnect - thread disconnect event processing routine** There are basically three cases:** 1) after a DISCONNECT message has been received: disconnect the thread** 2) after a COMMAND COMPLETE message has been received, or an ABORT* message has been sent, complete the thread normally** 3) otherwise, fail the thread with an "unexpected disconnection" error** RETURNS: N/A*/LOCAL void scsiCtrlThreadDisconnect ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { if (pThread->pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING) { SCSI_DEBUG_MSG ("scsiCtrlThreadDisconnect: thread 0x%08x: " "message out not sent (ignored).\n", (int) pThread, 0, 0, 0, 0, 0); } switch (pThread->state) { case SCSI_THREAD_WAIT_DISCONNECT: scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_DISCONNECTED); scsiCtrlThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED); break; case SCSI_THREAD_WAIT_COMPLETE: scsiCtrlThreadComplete (pThread); break; case SCSI_THREAD_WAIT_ABORT: scsiCtrlThreadComplete (pThread); break; default: SCSI_ERROR_MSG ("scsiCtrlThreadDisconnect: thread 0x%08x: " "unexpected disconnection\n", (int) pThread, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, S_scsiLib_DISCONNECTED); break; } } /********************************************************************************* scsiCtrlThreadSelect - thread selection event processing routine** Forward the event to the proper handler depending on the role played by* the thread.** RETURNS: N/A*/LOCAL void scsiCtrlThreadSelect ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { switch (pThread->state) { case SCSI_THREAD_CONNECTING: scsiCtrlThreadDefer (pThread); break; case SCSI_THREAD_INACTIVE: scsiCtrlIdentInCommence (pThread, pEvent); break; default: logMsg ("scsiCtrlThreadConnect: thread 0x%08x: " "invalid state (%d)\n", (int) pThread, pThread->state, 0, 0, 0, 0); break; } }/********************************************************************************* scsiCtrlThreadInfoXfer - thread info transfer request event processing** Forward the event to the proper handler depending on the thread's current* state.** RETURNS: N/A*/LOCAL void scsiCtrlThreadInfoXfer ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { switch (pThread->state) { case SCSI_THREAD_IDENT_OUT: scsiCtrlIdentOutXfer (pThread, pEvent); break; case SCSI_THREAD_IDENT_IN: scsiCtrlIdentInXfer (pThread, pEvent); break; case SCSI_THREAD_ABORTING: scsiCtrlAbortXfer (pThread, pEvent); break; default: scsiCtrlNormalXfer (pThread, pEvent); break; } } /********************************************************************************* scsiCtrlIdentOutXfer - process info. xfer request during identification out** Check that a message out transfer is being requested: fail the thread if* not. Transfer the remainder of the identification message, including a* queue tag message if applicable. Set the thread state to ESTABLISHED.** This code assumes that the target cannot request a new info transfer phase* until it has read the entire identification sequence (either 1 or 3 bytes).* (This seems to be required by the SCSI standard.)** RETURNS: N/A*/LOCAL void scsiCtrlIdentOutXfer ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; int nBytes; int maxBytes; /* * Check for logical errors */ if (pThread->state != SCSI_THREAD_IDENT_OUT) { logMsg ("scsiCtrlIdentOutXfer: invalid state (%d)\n", pThread->state, 0, 0, 0, 0, 0); return; } if ((maxBytes = pThread->identMsgLength - pThread->nBytesIdent) == 0) { logMsg ("scsiCtrlIdentOutXfer: no identification message!\n", 0, 0, 0, 0, 0, 0); return; } if (pEvent->phase != SCSI_MSG_OUT_PHASE) { SCSI_ERROR_MSG ("scsiCtrlIdentOutXfer: unexpected phase (%d) " "requested during identification out\n", pEvent->phase, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, S_scsiLib_INVALID_PHASE); return; } /* * Transfer the whole remaining identification sequence (in one go) */ nBytes = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_MSG_OUT_PHASE, pThread->identMsg + pThread->nBytesIdent, maxBytes); pThread->nBytesIdent += nBytes; if (nBytes != maxBytes) { /* * The target has most likely requested a new phase. The only * legitimate reason for this is to reject a queue tag message if * it does not support queueing - this should be dealt with by the * normal message reject mechanism. (The thread should be treated * as if it were untagged.) * * Hence, we continue and set the thread established anyway. */ SCSI_DEBUG_MSG ("scsiCtrlIdentOutXfer: identification incomplete - " "%d of %d bytes sent\n", pThread->nBytesIdent, pThread->identMsgLength, 0, 0, 0, 0); } scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED); } /********************************************************************************* scsiCtrlIdentInCommence - commence incoming identification** Copy the identification message read by the driver into the thread's buffer.* Parse the identification message so far (see "scsiCtrlIdentInContinue()").* Acknowledge the last message-in byte read (if any).** RETURNS: N/A*/LOCAL void scsiCtrlIdentInCommence ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { bcopy ((char *)pEvent->identMsg, (char *)pThread->identMsg, pEvent->nBytesIdent); pThread->nBytesIdent = pEvent->nBytesIdent; scsiCtrlIdentInContinue (pThread); if (pThread->nBytesIdent > 0) { scsiCtrlMsgInAck (pThread->pScsiCtrl); } } /********************************************************************************* scsiCtrlIdentInXfer - process info. xfer during incoming identification.** Check that a message in transfer is being requested; if not, fail the* thread (even though, at this stage, it's not a client thread). Transfer* the message byte in, then parse the message so far. Acknowledge the* message in byte.** RETURNS: N/A*/LOCAL void scsiCtrlIdentInXfer ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; if (pThread->state != SCSI_THREAD_IDENT_IN) { logMsg ("scsiCtrlIdentInXfer: invalid state (%d)\n", pThread->state, 0, 0, 0, 0, 0); return; } if (pEvent->phase != SCSI_MSG_IN_PHASE) { SCSI_ERROR_MSG ("scsiCtrlIdentInXfer: unexpected phase (%d) " "requested during identification in\n", pEvent->phase, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, 0); return; } if ((*pScsiCtrl->scsiInfoXfer) (pScsiCtrl, SCSI_MSG_IN_PHASE, pThread->identMsg + pThread->nBytesIdent, 1) != 1) { SCSI_ERROR_MSG ("scsiCtrlIdentInXfer: message in transfer failed\n", 0, 0, 0, 0, 0, 0); scsiCtrlThreadFail (pThread, 0); return; } ++pThread->nBytesIdent; scsiCtrlIdentInContinue (pThread); scsiCtrlMsgInAck (pScsiCtrl); } /********************************************************************************* scsiCtrlIdentInContinue - 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 scsiCtrlIdentInContinue ( SCSI_THREAD * pThread ) { SCSI_THREAD * pNewThread; SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; SCSI_IDENT_STATUS status; SCSI_THREAD_STATE state;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -