📄 ncr810lib.c
字号:
** ncr810ThreadAbort - abort a thread** If the thread is not currently connected, do nothing and return FALSE to* indicate that the SCSI manager should abort the thread.** Otherwise (the thread is active onthe controller), build an ABORT or* ABORT TAG message which will (eventually) be sent, causing the taget to* disconnect. Abort the current script run so that this message can be* sent. Set the state of the thread accordingly, and return TRUE to* indicate that the controller driver will handle the abort process.** RETURNS: TRUE if the thread is being aborted by this driver (i.e. it is* currently active on the controller, else FALSE.** NOMANUAL*/LOCAL BOOL ncr810ThreadAbort ( SIOP * pSiop, /* ptr to controller info */ NCR810_THREAD * pThread /* ptr to thread info */ ) { BOOL tagged; SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SCSI_DEBUG_MSG ("ncr810ThreadAbort: thread 0x%08x (state = %d) aborting\n", (int) pThread, pScsiThread->state, 0, 0, 0, 0); if (pScsiThread != pScsiCtrl->pThread) return (FALSE); switch (pScsiThread->state) { case SCSI_THREAD_INACTIVE: case SCSI_THREAD_WAITING: case SCSI_THREAD_DISCONNECTED: return (FALSE); break; default: /* * Build an ABORT (or ABORT TAG) message. When this has been * sent, the target should disconnect. Mark the thread aborted * and continue until disconnection. */ tagged = (pScsiThread->tagNumber != NONE); pScsiCtrl->msgOutBuf[0] = tagged ? SCSI_MSG_ABORT_TAG : SCSI_MSG_ABORT; pScsiCtrl->msgOutLength = 1; pScsiCtrl->msgOutState = SCSI_MSG_OUT_PENDING; ncr810Abort (pSiop); ncr810ThreadStateSet (pThread, SCSI_THREAD_ABORTING); break; } return (TRUE); }/********************************************************************************* ncr810Event - NCR 53C810 SCSI controller event processing routine** Parse the event type and act accordingly. Controller-level events are* handled within this function, and the event is then passed to the current* thread (if any) for thread-level processing.** Note the special case when (re)selection occurs: if there is a current* thread when the event occurs, it receives the event (and is assumed to* defer itself) before the identification thread is made current. The* event is then forwarded to the identification thread.** RETURNS: N/A*/LOCAL void ncr810Event ( SIOP * pSiop, NCR810_EVENT * pEvent ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_EVENT * pScsiEvent = (SCSI_EVENT *) pEvent; NCR810_THREAD * pThread = (NCR810_THREAD *) pScsiCtrl->pThread; SCSI_DEBUG_MSG ("ncr810Event: received event %d (thread = 0x%08x)\n", pScsiEvent->type, (int) pThread, 0, 0, 0, 0); /* * Do controller-level event processing */ switch (pScsiEvent->type) { case NCR810_SELECTED: case NCR810_RESELECTED: /* * Forward event to current thread, if any (it should defer) * then install a reserved thread for identification purposes. */ if (pThread != 0) ncr810ThreadEvent (pThread, pEvent); pScsiCtrl->peerBusId = pScsiEvent->busId; pScsiCtrl->pThread = pScsiCtrl->pIdentThread; pScsiCtrl->pThread->role = (pScsiEvent->type == NCR810_SELECTED) ? SCSI_ROLE_IDENT_TARG : SCSI_ROLE_IDENT_INIT; pThread = (NCR810_THREAD *) pScsiCtrl->pThread; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED); break; case NCR810_DISCONNECTED: case NCR810_CMD_COMPLETE: case NCR810_UNEXPECTED_DISCON: case NCR810_SCSI_TIMEOUT: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED); break; case NCR810_SCSI_BUS_RESET: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrBusReset (pScsiCtrl); break; default: /* * Any other event type is assumed to be thread-specific. * The thread event handler will report an error if it's * not a valid type. */ if (pThread == 0) { logMsg ("ncr810Event: invalid event type (%d)\n", pScsiEvent->type, 0, 0, 0, 0, 0); } break; } /* * If there's a thread on the controller, forward the event to it */ if (pThread != 0) ncr810ThreadEvent (pThread, pEvent); } /********************************************************************************* ncr810ThreadEvent - NCR 53C810 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** NOMANUAL*/LOCAL void ncr810ThreadEvent ( NCR810_THREAD * pThread, NCR810_EVENT * pEvent ) { SCSI_EVENT * pScsiEvent = (SCSI_EVENT *) pEvent; SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SIOP * pSiop = (SIOP *) pScsiThread->pScsiCtrl; NCR810_SCRIPT_ENTRY entryPt; SCSI_DEBUG_MSG ("ncr810ThreadEvent: thread 0x%08x: received event %d\n", (int) pThread, pScsiEvent->type, 0, 0, 0, 0); switch (pScsiThread->role) { case SCSI_ROLE_INITIATOR: ncr810InitEvent (pThread, pEvent); entryPt = NCR810_SCRIPT_INIT_CONTINUE; break; case SCSI_ROLE_IDENT_INIT: ncr810InitIdentEvent (pThread, pEvent); entryPt = NCR810_SCRIPT_INIT_CONTINUE; break; case SCSI_ROLE_IDENT_TARG: ncr810TargIdentEvent (pThread, pEvent); entryPt = NCR810_SCRIPT_TGT_DISCONNECT; break; case SCSI_ROLE_TARGET: default: logMsg ("ncr810ThreadEvent: thread 0x%08x: invalid role (%d)\n", (int) pThread, pScsiThread->role, 0, 0, 0, 0); entryPt = NCR810_SCRIPT_TGT_DISCONNECT; break; } /* * Resume thread iff it is still connected */ switch (pScsiThread->state) { case SCSI_THREAD_INACTIVE: case SCSI_THREAD_WAITING: case SCSI_THREAD_DISCONNECTED: break; default: ncr810ThreadUpdate (pThread); if (ncr810Resume (pSiop, pThread, entryPt) != OK) { SCSI_ERROR_MSG ("ncr810ThreadEvent: failed to resume thread\n", 0, 0, 0, 0, 0, 0); ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED); } break; } }/********************************************************************************* ncr810InitEvent - NCR 53C810 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** NOMANUAL*/LOCAL void ncr810InitEvent ( NCR810_THREAD * pThread, NCR810_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 NCR810_DISCONNECTED: SCSI_DEBUG_MSG ("DISCONNECT message in\n", 0, 0, 0, 0, 0, 0); scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DISCONNECTED); ncr810ThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED); break; case NCR810_CMD_COMPLETE: SCSI_DEBUG_MSG ("COMMAND COMPLETE message in\n", 0, 0, 0, 0, 0, 0); ncr810ThreadComplete (pThread); break; case NCR810_SELECTED: case NCR810_RESELECTED: SCSI_DEBUG_MSG ("ncr810InitEvent: thread 0x%08x: (re)selection.\n", (int) pThread, 0, 0, 0, 0, 0); ncr810ThreadDefer (pThread); break; case NCR810_MESSAGE_OUT_SENT: (void) scsiMsgOutComplete (pScsiCtrl, pScsiThread); break; case NCR810_MESSAGE_IN_RECVD: (void) scsiMsgInComplete (pScsiCtrl, pScsiThread); break; case NCR810_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 NCR810_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 * "ncr810ThreadUpdate()". */ break; case NCR810_PHASE_MISMATCH: if (ncr810PhaseMismatch (pThread, pThread->nBusPhase, pEvent->remCount) != OK) { ncr810ThreadFail (pThread, errno); } break; case NCR810_SCSI_TIMEOUT: SCSI_ERROR_MSG ("ncr810InitEvent: thread 0x%08x: select timeout.\n", (int) pThread, 0, 0, 0, 0, 0); ncr810ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT); break; case NCR810_SCRIPT_ABORTED: SCSI_DEBUG_MSG ("ncr810InitEvent: thread 0x%08x: aborted\n", (int) pThread, 0, 0, 0, 0, 0); break; case NCR810_SCSI_BUS_RESET: SCSI_DEBUG_MSG ("ncr810InitEvent: 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. */ ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE); break; case NCR810_UNEXPECTED_DISCON: /* not really unexpected after an abort message ... */ SCSI_ERROR_MSG ("ncr810InitEvent: thread 0x%08x: " "unexpected disconnection\n", (int) pThread, 0, 0, 0, 0, 0); ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED); break; case NCR810_ILLEGAL_PHASE: SCSI_ERROR_MSG ("ncr810InitEvent: thread 0x%08x: " "illegal phase requested.\n", (int) pThread, 0, 0, 0, 0, 0); ncr810ThreadFail (pThread, S_scsiLib_INVALID_PHASE); break; default: logMsg ("ncr810InitEvent: invalid event type (%d)\n", pScsiEvent->type, 0, 0, 0, 0, 0); break; } } /********************************************************************************* ncr810InitIdentEvent - NCR 53C810 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** NOMANUAL*/LOCAL void ncr810InitIdentEvent ( NCR810_THREAD * pThread, NCR810_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 NCR810_RESELECTED: pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent; bcopy ((char *) pScsiCtrl->identBuf, (char *) pScsiThread->identMsg, pScsiThread->nBytesIdent); ncr810ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN); ncr810IdentInContinue (pThread); break; case NCR810_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -