📄 templatescsi2.c
字号:
SCSI_INT_DEBUG_MSG ("templateEventTypeGet: SCSI bus reset.\n", 0, 0, 0, 0, 0, 0); /* TODO - clear FIFOs, etc. */ return (SCSI_EVENT_BUS_RESET); } if (0) /* TODO - check for unexpected disconnect */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: unexpected disconnection.\n", 0, 0, 0, 0, 0, 0); /* TODO - clear FIFOs, etc. */ return (TEMPLATE_UNEXPECTED_DISCON); } if (0) /* TODO - check for scsi bus timeout */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: SCSI bus timeout.\n", 0, 0, 0, 0, 0, 0); /* TODO - clear FIFOs, etc. */ return (TEMPLATE_SCSI_TIMEOUT); } if (0) /* TODO - check for SCSI handshake timeout */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: SCSI handshake timeout.\n", 0, 0, 0, 0, 0, 0); /* TODO - clear FIFOs, etc. */ return (TEMPLATE_HANDSHAKE_TIMEOUT); } if (0) /* TODO - check for phase mismatch condition */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: phase mismatch.\n", 0, 0, 0, 0, 0, 0); return (TEMPLATE_PHASE_MISMATCH); } if (0) /* TODO - check for a script abort */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: script aborted.\n", 0, 0, 0, 0, 0, 0); return (TEMPLATE_SCRIPT_ABORTED); } if (0) /* TODO - check for normal script completion */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: script completed.\n", 0, 0, 0, 0, 0, 0); return (TEMPLATE_SCSI_COMPLETE); } if (0) /* TODO - check for a single step event */ { SCSI_INT_DEBUG_MSG ("templateEventTypeGet: single-step.\n", 0, 0, 0, 0, 0, 0); return (TEMPLATE_SINGLE_STEP); } /* No reason for the interrupt ! */ return (TEMPLATE_FATAL_ERROR); }/********************************************************************************* templateThreadEvent - SCSI Controller thread event processing routine** Forward the event to the proper handler for the thread's current role.** If the thread is still active, update the thread context (including* shared memory area) and resume the thread.** RETURNS: N/A*/LOCAL void templateThreadEvent ( TEMPLATE_THREAD * pThread, TEMPLATE_EVENT * pEvent ) { SCSI_EVENT * pScsiEvent = &pEvent->scsiEvent; SCSI_THREAD * pScsiThread = &pThread->scsiThread; SIOP * pSiop = (SIOP *) pScsiThread->pScsiCtrl; TEMPLATE_SCRIPT_ENTRY entryPt; SCSI_DEBUG_MSG ("templateThreadEvent: thread 0x%08x: received event %d\n", (int) pThread, pScsiEvent->type, 0, 0, 0, 0); switch (pScsiThread->role) { case SCSI_ROLE_INITIATOR: templateInitEvent (pThread, pEvent); entryPt = TEMPLATE_SCRIPT_INIT_CONTINUE; break; case SCSI_ROLE_IDENT_INIT: templateInitIdentEvent (pThread, pEvent); entryPt = TEMPLATE_SCRIPT_INIT_CONTINUE; break; case SCSI_ROLE_TARGET: default: logMsg ("templateThreadEvent: thread 0x%08x: invalid role (%d)\n", (int) pThread, pScsiThread->role, 0, 0, 0, 0); entryPt = TEMPLATE_SCRIPT_TGT_DISCONNECT; break; } /* Resume thread if it is still connected */ switch (pScsiThread->state) { case SCSI_THREAD_INACTIVE: case SCSI_THREAD_WAITING: case SCSI_THREAD_DISCONNECTED: break; default: templateThreadUpdate (pThread); if (templateResume (pSiop, pThread, entryPt) != OK) { SCSI_ERROR_MSG("templateThreadEvent: failed to resume thread\n", 0, 0, 0, 0, 0, 0); templateThreadFail (pThread, S_scsiLib_DISCONNECTED); } break; } }/********************************************************************************* templateInitEvent - device initiator thread event processing routine** 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 templateInitEvent ( TEMPLATE_THREAD * pThread, TEMPLATE_EVENT * pEvent ) { SCSI_EVENT * pScsiEvent = &pEvent->scsiEvent; SCSI_THREAD * pScsiThread = &pThread->scsiThread; 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_DISCONNECTED: SCSI_DEBUG_MSG ("DISCONNECT message in\n", 0, 0, 0, 0, 0, 0); scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DISCONNECTED); templateThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED); break; case TEMPLATE_SCSI_COMPLETE: SCSI_DEBUG_MSG ("COMMAND COMPLETE message in\n", 0, 0, 0, 0, 0, 0); templateThreadComplete (pThread); break; case SCSI_EVENT_SELECTED: case SCSI_EVENT_RESELECTED: SCSI_DEBUG_MSG ("templateInitEvent: thread 0x%08x: (re)selection.\n", (int) pThread, 0, 0, 0, 0, 0); templateThreadDefer (pThread); break; case TEMPLATE_MESSAGE_OUT_SENT: (void) scsiMsgOutComplete (pScsiCtrl, pScsiThread); break; case TEMPLATE_MESSAGE_IN_RECVD: (void) scsiMsgInComplete (pScsiCtrl, pScsiThread); break; case TEMPLATE_NO_MSG_OUT: /* * The target has requested a message out when there is none * pending. Set up a NO-OP message to be sent when thread is * resumed. * * The script could handle this on its own, but arguably the * host should be involved as it may represent an error. */ pScsiCtrl->msgOutBuf[0] = SCSI_MSG_NO_OP; pScsiCtrl->msgOutLength = 1; pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; /* sic */ break; case TEMPLATE_EXT_MESSAGE_SIZE: /* * The SIOP has just read the length byte for an extended * message in. The shared memory area is updated with the * appropriate length just before the thread is resumed (see * "templateThreadUpdate()". */ break; case TEMPLATE_PHASE_MISMATCH: if (templatePhaseMismatch (pThread, pThread->nBusPhase, pEvent->remCount) != OK) { templateThreadFail (pThread, errno); } break; case TEMPLATE_SCSI_TIMEOUT: SCSI_ERROR_MSG ("templateInitEvent: thread 0x%08x: " \ "select timeout.\n", (int) pThread, 0, 0, 0, 0, 0); templateThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT); break; case TEMPLATE_SCRIPT_ABORTED: SCSI_DEBUG_MSG ("templateInitEvent: thread 0x%08x: aborted\n", (int) pThread, 0, 0, 0, 0, 0); break; case SCSI_EVENT_BUS_RESET: SCSI_DEBUG_MSG ("templateInitEvent: 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 ("templateInitEvent: 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 ("templateInitEvent: thread 0x%08x: " "illegal phase requested.\n", (int) pThread, 0, 0, 0, 0, 0); templateThreadFail (pThread, S_scsiLib_INVALID_PHASE); break; default: logMsg ("templateInitEvent: invalid event type (%d)\n", pScsiEvent->type, 0, 0, 0, 0, 0); break; } }/******************************************************************************** templateActivate - activate a script corresponding to a new thread** Request activation of (the script for) a new thread, if possible; do not* wait for the script to complete (or even start) executing. Activation* is requested by signalling the controller, which causes an interrupt.* The script is started by the ISR in response to this event.** NOTE: Interrupt locking is required to ensure that the correct action* is taken once the controller state has been checked.** RETURNS: OK, or ERROR if the controller is in an invalid state (this* indicates a major software failure).*/LOCAL STATUS templateActivate ( SIOP * pSiop, TEMPLATE_THREAD * pThread ) { STATUS status = OK; int key; key = intLock (); /* TODO - Activate Controller for the current thread */ intUnlock (key); return (status); }/********************************************************************************* templateAbort - abort the active script corresponding to the current thread** Check that there is currently an active script running. If so, set the* SCSI Controller Abort flag which will halt the script and cause an interrupt.** RETURNS: N/A*/LOCAL void templateAbort ( SIOP* pSiop /* ptr to controller info */ ) { int key; key = intLock (); /* TODO - Abort the active script corresponding to the current thread */ intUnlock (key); }/********************************************************************************* templateScriptStart - start the SCSI Controller executing a script** Restore the SCSI Controller register context, including the shared memory* area, from the thread context. Put the address of the script entry point* into the DSP register. If not in single-step mode, start the script.** RETURNS: N/A*/LOCAL void templateScriptStart ( SIOP* pSiop, /* pointer to SCSI Controller info */ TEMPLATE_THREAD* pThread, /* ncr thread info */ TEMPLATE_SCRIPT_ENTRY entryId /* routine address entry point */ ) { IMPORT ULONG templateWait[]; /* DUMMY entries to scripts */ IMPORT ULONG templateInitStart[]; IMPORT ULONG templateInitContinue[]; IMPORT ULONG templateTgtDisconnect[]; int key; static ULONG * templateScriptEntry [] = { templateWait, /* wait for re-select or host cmd */ templateInitStart, /* start an initiator thread */ templateInitContinue, /* continue an initiator thread */ templateTgtDisconnect, /* disconnect a target thread */ }; key = intLock (); /* TODO - Restore the SCSI Controller register context for this thread. */ /* * TODO - Set the shared data address, load the script start address, * then start the SCSI Controller unless it's in single-step mode. */ /* DUMMY CMD */ TEMPLATE_REG_WRITE (pSiop, pCmd, (int)templateScriptEntry[entryId]); intUnlock (key); }/********************************************************************************* templateThreadUpdate - update the thread structure for a current SCSI command** Update the dynamic data (e.g. data pointers, transfer parameters) in* the thread to reflect the latest state of the corresponding physical device.** RETURNS: N/A** NOMANUAL*/LOCAL void templateThreadUpdate ( TEMPLATE_THREAD * pThread /* thread info */ ) { SCSI_THREAD * pScsiThread = &pThread->scsiThread; SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl; UINT msgOutSize; UINT msgInSize; /* * If there is an identification message, ensure ATN is asserted * during (re)selection. */ /* TODO - update device specific info in the thread structure */ /* Update dynamic message in/out sizes */ if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_NONE) msgOutSize = 0; else msgOutSize = pScsiCtrl->msgOutLength; if (pScsiCtrl->msgInState != SCSI_MSG_IN_EXT_MSG_DATA) msgInSize = 0; else if ((msgInSize = pScsiCtrl->msgInBuf[SCSI_EXT_MSG_LENGTH_BYTE]) == 0) msgInSize = SCSI_EXT_MSG_MAX_LENGTH; /* TODO - Update commands in shared memory area */ }/********************************************************************************* templateThreadComplete - successfully complete execution of a client thread** Set the thread status and errno appropriately, depending on whether or* not the thread has been aborted. Set the thread inactive, and notify* the SCSI manager of the completion.** RETURNS: N/A*/LOCAL void templateThreadComplete ( TEMPLATE_THREAD * pThread ) { SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SCSI_DEBUG_MSG ("templateThreadComplete: thread 0x%08x completed\n", (int) pThread, 0, 0, 0, 0, 0); if (pScsiThread->state == SCSI_THREAD_ABORTING) { pScsiThread->status = ERROR; pScsiThread->errNum = S_scsiLib_ABORTED; } else { pScsiThread->status = OK; pScsiThread->errNum = 0; } templateThreadStateSet (pThread, SCSI_THREAD_INACTIVE); scsiCacheSynchronize (pScsiThread, SCSI_CACHE_POST_COMMAND); scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED); }/*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -