📄 ncr810lib.c
字号:
* when a wide transfer has been done the next activation causes the * synchronous transfer to be activated. Another possible but more * complicated way to implement this would be to have both wide and * synchronous negotiations in the same activation or thread i.e. * the same SCSI transaction. */ scsiWideXferNegotiate (pScsiCtrl, pScsiTarget, WIDE_XFER_NEW_THREAD); scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD); if (ncr810ThreadParamsSet (pThread, pScsiTarget->xferOffset, pScsiTarget->xferPeriod) != OK) { SCSI_ERROR_MSG ("ncr810ThreadActivate: failed to set thread params.\n", 0, 0, 0, 0, 0, 0); pScsiCtrl->pThread = pOrigThread; return (ERROR); } /* * Concatenate the ident message with a pending 'normal' message out, * if possible. This allows the script to send the first message out * within the same MSG OUT phase as the IDENTIFY message - needed on * some target systems (e.g. DG Clariion RAID) to avoid the message * being rejected(!). */ pSiop->identMsgLength = 0; bcopy ((char *)pScsiThread->identMsg, (char *)pSiop->identMsg, pScsiThread->identMsgLength); pSiop->identMsgLength += pScsiThread->identMsgLength; if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING) { bcopy ((char *)pScsiCtrl->msgOutBuf, (char *)pSiop->identMsg + pSiop->identMsgLength, pScsiCtrl->msgOutLength); pSiop->identMsgLength += pScsiCtrl->msgOutLength; } /* * Update thread context; activate the thread */ ncr810ThreadUpdate (pThread); if (ncr810Activate (pSiop, pThread) != OK) { SCSI_ERROR_MSG ("ncr810ThreadActivate: failed to activate thread.\n", 0, 0, 0, 0, 0, 0); pScsiCtrl->pThread = pOrigThread; return (ERROR); } pScsiCtrl->pThread = pScsiThread; ncr810ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED); return (OK); }/********************************************************************************* 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 != (UINT)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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -