?? scsictrllib.c
字號:
/* scsiCtrlLib.c - SCSI thread-level controller library (SCSI-2) *//* Copyright 1989-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01d,28mar97,dds SPR 8220: added check for parity errors.01c,29oct96,dgp doc: editing for newly published SCSI libraries01b,21oct96,dds removed NOMANUAL from functions called by the driver interface.01a,12sep96,dds added the thread-level controller routines from scsi2Lib.c*//*DESCRIPTIONThe purpose of the SCSI controller library is to support basic SCSI controller drivers that rely on a higher level of software in order to manage SCSI transactions. More advanced SCSI I/O processors do not require thisprotocol engine since software support for SCSI transactions is providedat the SCSI I/O processor level.This library provides all the high-level routines that manage the state of the SCSI threads and guide the SCSI I/O transaction through its various stages:.iPselecting a SCSI peripheral device;.iPsending the identify message in order to establish the ITL nexus;.iPcycling through information transfer, message and data, and status phases;.iPhandling bus-initiated reselects..LPThe various stages of the SCSI I/O transaction are reported to the SCSI manageras SCSI events. Event selection and management is handled by routinesin this library. INCLUDE FILESscsiLib.h, scsi2Lib.hSEE ALSO: scsiLib, scsi2Lib, scsiCommonLib, scsiDirectLib, scsiSeqLib,scsiMgrLib,.I "American National Standard for Information Systems - Small Computer".I "System Interface (SCSI-2), ANSI X3T9,".pG "I/O System, Local File Systems"*/#define INCLUDE_SCSI2#include "vxWorks.h"#include "ioLib.h"#include "intLib.h"#include "ctype.h"#include "cacheLib.h"#include "stdlib.h"#include "errnoLib.h"#include "taskLib.h"#include "lstLib.h"#include "logLib.h"#include "msgQLib.h"#include "string.h"#include "stdio.h"#include "sysLib.h"#include "scsiLib.h"#include "wdLib.h"/* global functions */SCSI_THREAD * scsiCtrlIdentThreadCreate (SCSI_CTRL *pScsiCtrl);STATUS scsiCtrlThreadInit (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);STATUS scsiCtrlThreadActivate (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);VOID scsiCtrlEvent (SCSI_CTRL * pScsiCtrl, SCSI_EVENT * pEvent);BOOL scsiCtrlThreadAbort (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);/* Generic thread-level controller driver */LOCAL void scsiCtrlThreadEvent (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlThreadConnect (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlThreadDisconnect (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlThreadSelect (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlThreadInfoXfer (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlIdentOutXfer (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlIdentInCommence (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlIdentInXfer (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlIdentInContinue (SCSI_THREAD * pThread);LOCAL void scsiCtrlThreadReconnect (SCSI_THREAD * pThread);LOCAL void scsiCtrlNormalXfer (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL void scsiCtrlAbortXfer (SCSI_THREAD * pThread, SCSI_EVENT * pEvent);LOCAL STATUS scsiCtrlDataOutAction (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlDataInAction (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlCommandAction (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlStatusAction (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlMsgOutAction (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlMsgInAction (SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlMsgInXfer (SCSI_CTRL * pScsiCtrl);LOCAL STATUS scsiCtrlXferParamsSet (SCSI_THREAD * pThread);LOCAL STATUS scsiCtrlMsgInAck (SCSI_CTRL * pScsiCtrl);LOCAL void scsiCtrlThreadComplete (SCSI_THREAD * pThread);LOCAL void scsiCtrlThreadDefer (SCSI_THREAD * pThread);LOCAL void scsiCtrlThreadFail (SCSI_THREAD * pThread, int errNum);LOCAL void scsiCtrlThreadStateSet (SCSI_THREAD * pThread, SCSI_THREAD_STATE state);/********************************************************************************* scsiCtrlIdentThreadCreate - create thread context for incoming identification** Allocate and initialise a thread context which will be used to read* incoming identification messages. Note that the normal thread allocator* is not used because this thread is somewhat special.** NOTE:* This routine is currently called no matter what type of controller is in* use. In theory, it should be controller-specific.** RETURNS: thread ptr, or 0 if an error occurs** NOMANUAL*/SCSI_THREAD * scsiCtrlIdentThreadCreate ( SCSI_CTRL * pScsiCtrl ) { SCSI_THREAD * pThread; if ((pThread = malloc (pScsiCtrl->threadSize)) == 0) return (NULL); /* * Initialise thread structure (mostly unused) */ bzero ((char *) pThread, pScsiCtrl->threadSize); pThread->pScsiCtrl = pScsiCtrl; pThread->role = SCSI_ROLE_IDENT_INIT; return (pThread); }/********************************************************************************* scsiCtrlThreadActivate - request (re)activation of a thread** Set whatever thread/controller state variables need to be set. Ensure that* all buffers used by the thread are coherent with the contents of the* system caches (if any).** For initiator threads, issue a SELECT command. For target threads, issue a* RESELECT command. Do not wait for it to complete, as this is signalled by* an event which should be one of:** CONNECTED - the connection attempt was successful (thread continues)** TIMEOUT - the connection attempt timed out (thread fails)** (RE)SELECTED - we lost a race against being selected (thread defers)** RETURNS: OK, or ERROR if activation fails** NOMANUAL*/STATUS scsiCtrlThreadActivate ( SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread ) { SCSI_TARGET * pScsiTarget = pThread->pScsiTarget; scsiCacheSynchronize (pThread, SCSI_CACHE_PRE_COMMAND); /* * Reset controller state variables for the new thread */ pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; pScsiCtrl->msgInState = SCSI_MSG_IN_NONE; /* * Initiate synchronous transfer negotiation */ scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD); /* * Initiate (asynchronous) selection of the target */ if ((*pScsiCtrl->scsiDevSelect) (pScsiCtrl, pScsiTarget->scsiDevBusId, pScsiTarget->selTimeOut, pThread->identMsg, pThread->identMsgLength) != OK) { SCSI_DEBUG_MSG ("scsiCtrlThreadActivate: failed to select device.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } pScsiCtrl->pThread = pThread; scsiCtrlThreadStateSet (pThread, SCSI_THREAD_CONNECTING); return (OK); }/********************************************************************************* scsiCtrlThreadAbort - abort the specified 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. 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*/BOOL scsiCtrlThreadAbort ( SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread ) { BOOL tagged; if (pThread != pScsiCtrl->pThread) return (FALSE); switch (pThread->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 save the error code until disconnection. */ tagged = (pThread->tagNumber != NONE); pScsiCtrl->msgOutBuf[0] = tagged ? SCSI_MSG_ABORT_TAG : SCSI_MSG_ABORT; pScsiCtrl->msgOutLength = 1; pScsiCtrl->msgOutState = SCSI_MSG_OUT_PENDING; scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ABORTING); break; } return (TRUE); }/********************************************************************************* scsiCtrlThreadInit - initialise a newly created thread structure** This is a controller-specific function to initialise a thread. For the* generic thread-level controller, a standard (exported) initialisation* function suffices.** RETURNS: OK, or ERROR if initialisation fails** NOMANUAL*/STATUS scsiCtrlThreadInit ( SCSI_CTRL * pScsiCtrl, SCSI_THREAD * pThread ) { return (scsiThreadInit (pThread)); }/********************************************************************************* scsiCtrlEvent - 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** NOMANUAL*/VOID scsiCtrlEvent ( SCSI_CTRL * pScsiCtrl, SCSI_EVENT * pEvent ) { SCSI_THREAD * pThread = pScsiCtrl->pThread; SCSI_DEBUG_MSG ("scsiCtrlEvent: received event %d, thread = 0x%08x\n", pEvent->type, (int) pThread, 0, 0, 0, 0); /* * Do controller-level event processing */ switch (pEvent->type) { case SCSI_EVENT_SELECTED: case SCSI_EVENT_RESELECTED: if (pThread != 0) scsiCtrlThreadEvent (pThread, pEvent); pScsiCtrl->peerBusId = pEvent->busId; pThread = pScsiCtrl->pThread = pScsiCtrl->pIdentThread; pThread->role = (pEvent->type == SCSI_EVENT_SELECTED) ? SCSI_ROLE_IDENT_TARG : SCSI_ROLE_IDENT_INIT; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED); break; case SCSI_EVENT_CONNECTED: pScsiCtrl->peerBusId = pEvent->busId; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED); /* assert (pThread != 0); */ break; case SCSI_EVENT_DISCONNECTED: case SCSI_EVENT_TIMEOUT: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED); /* assert (pThread != 0); */ break; case SCSI_EVENT_XFER_REQUEST: /* assert (pThread != 0); */ break; case SCSI_EVENT_PARITY_ERR: break; case SCSI_EVENT_BUS_RESET: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrBusReset (pScsiCtrl); break; default: logMsg ("scsiCtrlEvent: invalid event type (%d)\n", pEvent->type, 0, 0, 0, 0, 0); break; } /* * If there's a thread on the controller, forward the event to it */ if (pThread != 0) scsiCtrlThreadEvent (pThread, pEvent); } /********************************************************************************* scsiCtrlThreadEvent - SCSI thread event processing routine** Parse the event type and forward it to the appropriate handler. If there* is an established thread, and there is an outgoing message pending,* assert the SCSI ATN signal.** RETURNS: N/A*/LOCAL void scsiCtrlThreadEvent ( SCSI_THREAD * pThread, SCSI_EVENT * pEvent ) { SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl; SCSI_DEBUG_MSG ("scsiCtrlThreadEvent: thread = 0x%08x: received event %d\n", (int) pThread, pEvent->type, 0, 0, 0, 0);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -