scsiCtrlLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:47k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* scsiCtrlLib.c - SCSI thread-level controller library (SCSI-2) */
  2. /* Copyright 1989-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01d,28mar97,dds  SPR 8220: added check for parity errors.
  8. 01c,29oct96,dgp  doc: editing for newly published SCSI libraries
  9. 01b,21oct96,dds removed NOMANUAL from functions called by
  10.                 the driver interface.
  11. 01a,12sep96,dds added the thread-level controller routines from
  12.                 scsi2Lib.c
  13. */
  14. /*
  15. DESCRIPTION
  16. The purpose of the SCSI controller library is to support basic SCSI controller 
  17. drivers that rely on a higher level of software in order to manage 
  18. SCSI transactions. More advanced SCSI I/O processors do not require this
  19. protocol engine since software support for SCSI transactions is provided
  20. at the SCSI I/O processor level.
  21. This library provides all the high-level routines that manage the state of 
  22. the SCSI threads and guide the SCSI I/O transaction through its various stages:
  23. .iP
  24. selecting a SCSI peripheral device;
  25. .iP
  26. sending the identify message in order to establish the ITL nexus;
  27. .iP
  28. cycling through information transfer, message and data, and status phases;
  29. .iP
  30. handling bus-initiated reselects.
  31. .LP
  32. The various stages of the SCSI I/O transaction are reported to the SCSI manager
  33. as SCSI events. Event selection and management is handled by routines
  34. in this library. 
  35. INCLUDE FILES
  36. scsiLib.h, scsi2Lib.h
  37. SEE ALSO: scsiLib, scsi2Lib, scsiCommonLib, scsiDirectLib, scsiSeqLib,
  38. scsiMgrLib,
  39. .I  "American National Standard for Information Systems - Small Computer"
  40. .I  "System Interface (SCSI-2), ANSI X3T9,"
  41. .pG "I/O System, Local File Systems"
  42. */
  43. #define  INCLUDE_SCSI2
  44. #include "vxWorks.h"
  45. #include "ioLib.h"
  46. #include "intLib.h"
  47. #include "ctype.h"
  48. #include "cacheLib.h"
  49. #include "stdlib.h"
  50. #include "errnoLib.h"
  51. #include "taskLib.h"
  52. #include "lstLib.h"
  53. #include "logLib.h"
  54. #include "msgQLib.h"
  55. #include "string.h"
  56. #include "stdio.h"
  57. #include "sysLib.h"
  58. #include "scsiLib.h"
  59. #include "wdLib.h"
  60. /* global functions */
  61. SCSI_THREAD * scsiCtrlIdentThreadCreate (SCSI_CTRL *pScsiCtrl);
  62. STATUS        scsiCtrlThreadInit        (SCSI_CTRL   * pScsiCtrl,
  63.  SCSI_THREAD * pThread);
  64. STATUS        scsiCtrlThreadActivate    (SCSI_CTRL   * pScsiCtrl,
  65.  SCSI_THREAD * pThread);
  66. VOID          scsiCtrlEvent             (SCSI_CTRL   * pScsiCtrl,
  67.  SCSI_EVENT  * pEvent);
  68. BOOL          scsiCtrlThreadAbort       (SCSI_CTRL   * pScsiCtrl,
  69.  SCSI_THREAD * pThread);
  70. /* Generic thread-level controller driver */
  71. LOCAL void          scsiCtrlThreadEvent      (SCSI_THREAD * pThread,
  72.               SCSI_EVENT  * pEvent);
  73. LOCAL void          scsiCtrlThreadConnect    (SCSI_THREAD * pThread,
  74.               SCSI_EVENT  * pEvent);
  75. LOCAL void          scsiCtrlThreadDisconnect (SCSI_THREAD * pThread,
  76.               SCSI_EVENT  * pEvent);
  77. LOCAL void          scsiCtrlThreadSelect     (SCSI_THREAD * pThread,
  78.               SCSI_EVENT  * pEvent);
  79. LOCAL void          scsiCtrlThreadInfoXfer   (SCSI_THREAD * pThread,
  80.               SCSI_EVENT  * pEvent);
  81. LOCAL void          scsiCtrlIdentOutXfer     (SCSI_THREAD * pThread,
  82.               SCSI_EVENT  * pEvent);
  83. LOCAL void          scsiCtrlIdentInCommence  (SCSI_THREAD * pThread,
  84.               SCSI_EVENT  * pEvent);
  85. LOCAL void          scsiCtrlIdentInXfer      (SCSI_THREAD * pThread,
  86.               SCSI_EVENT  * pEvent);
  87. LOCAL void          scsiCtrlIdentInContinue  (SCSI_THREAD * pThread);
  88. LOCAL void          scsiCtrlThreadReconnect  (SCSI_THREAD * pThread);
  89. LOCAL void          scsiCtrlNormalXfer       (SCSI_THREAD * pThread,
  90.               SCSI_EVENT  * pEvent);
  91. LOCAL void          scsiCtrlAbortXfer        (SCSI_THREAD * pThread,
  92.               SCSI_EVENT  * pEvent);
  93. LOCAL STATUS        scsiCtrlDataOutAction (SCSI_CTRL   * pScsiCtrl,
  94.            SCSI_THREAD * pThread);
  95. LOCAL STATUS        scsiCtrlDataInAction  (SCSI_CTRL   * pScsiCtrl,
  96.            SCSI_THREAD * pThread);
  97. LOCAL STATUS        scsiCtrlCommandAction (SCSI_CTRL   * pScsiCtrl,
  98.            SCSI_THREAD * pThread);
  99. LOCAL STATUS        scsiCtrlStatusAction  (SCSI_CTRL   * pScsiCtrl,
  100.            SCSI_THREAD * pThread);
  101. LOCAL STATUS        scsiCtrlMsgOutAction  (SCSI_CTRL   * pScsiCtrl,
  102.            SCSI_THREAD * pThread);
  103. LOCAL STATUS        scsiCtrlMsgInAction   (SCSI_CTRL   * pScsiCtrl,
  104.            SCSI_THREAD * pThread);
  105. LOCAL STATUS        scsiCtrlMsgInXfer     (SCSI_CTRL   * pScsiCtrl);
  106. LOCAL STATUS        scsiCtrlXferParamsSet (SCSI_THREAD * pThread);
  107. LOCAL STATUS        scsiCtrlMsgInAck      (SCSI_CTRL   * pScsiCtrl);
  108. LOCAL void          scsiCtrlThreadComplete (SCSI_THREAD * pThread);
  109. LOCAL void          scsiCtrlThreadDefer    (SCSI_THREAD * pThread);
  110. LOCAL void          scsiCtrlThreadFail     (SCSI_THREAD * pThread, int errNum);
  111. LOCAL void          scsiCtrlThreadStateSet (SCSI_THREAD * pThread, 
  112.             SCSI_THREAD_STATE state);
  113. /*******************************************************************************
  114. *
  115. * scsiCtrlIdentThreadCreate - create thread context for incoming identification
  116. *
  117. * Allocate and initialise a thread context which will be used to read
  118. * incoming identification messages.  Note that the normal thread allocator
  119. * is not used because this thread is somewhat special.
  120. *
  121. * NOTE:
  122. * This routine is currently called no matter what type of controller is in
  123. * use.   In theory, it should be controller-specific.
  124. *
  125. * RETURNS: thread ptr, or 0 if an error occurs
  126. *
  127. * NOMANUAL
  128. */
  129. SCSI_THREAD * scsiCtrlIdentThreadCreate
  130.     (
  131.     SCSI_CTRL * pScsiCtrl
  132.     )
  133.     {
  134.     SCSI_THREAD * pThread;
  135.     if ((pThread = malloc (pScsiCtrl->threadSize)) == 0)
  136. return (NULL);
  137.     /*
  138.      * Initialise thread structure (mostly unused)
  139.      */
  140.     bzero ((char *) pThread, pScsiCtrl->threadSize);
  141.     
  142.     pThread->pScsiCtrl = pScsiCtrl;
  143.     pThread->role      = SCSI_ROLE_IDENT_INIT;
  144.     return (pThread);
  145.     }
  146. /*******************************************************************************
  147. *
  148. * scsiCtrlThreadActivate - request (re)activation of a thread
  149. *
  150. * Set whatever thread/controller state variables need to be set.  Ensure that
  151. * all buffers used by the thread are coherent with the contents of the
  152. * system caches (if any).
  153. *
  154. * For initiator threads, issue a SELECT command.  For target threads, issue a
  155. * RESELECT command.  Do not wait for it to complete, as this is signalled by
  156. * an event which should be one of:
  157. *
  158. *   CONNECTED     - the connection attempt was successful (thread continues)
  159. *
  160. *   TIMEOUT      - the connection attempt timed out     (thread fails)
  161. *
  162. *   (RE)SELECTED    - we lost a race against being selected (thread defers)
  163. *
  164. * RETURNS: OK, or ERROR if activation fails
  165. *
  166. * NOMANUAL
  167. */
  168. STATUS scsiCtrlThreadActivate
  169.     (
  170.     SCSI_CTRL *   pScsiCtrl,
  171.     SCSI_THREAD * pThread
  172.     )
  173.     {
  174.     SCSI_TARGET * pScsiTarget = pThread->pScsiTarget;
  175.     scsiCacheSynchronize (pThread, SCSI_CACHE_PRE_COMMAND);
  176.     /*
  177.      * Reset controller state variables for the new thread
  178.      */
  179.     pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE;
  180.     pScsiCtrl->msgInState  = SCSI_MSG_IN_NONE;
  181.     
  182.     /*
  183.      * Initiate synchronous transfer negotiation
  184.      */
  185.     scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD);
  186.     /*
  187.      * Initiate (asynchronous) selection of the target
  188.      */
  189.     if ((*pScsiCtrl->scsiDevSelect) (pScsiCtrl,
  190.      pScsiTarget->scsiDevBusId,
  191.      pScsiTarget->selTimeOut,
  192.      pThread->identMsg,
  193.      pThread->identMsgLength) != OK)
  194. {
  195. SCSI_DEBUG_MSG ("scsiCtrlThreadActivate: failed to select device.n",
  196. 0, 0, 0, 0, 0, 0);
  197. return (ERROR);
  198. }
  199.     pScsiCtrl->pThread = pThread;
  200.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_CONNECTING);
  201.     return (OK);
  202.     }
  203. /*******************************************************************************
  204. *
  205. * scsiCtrlThreadAbort - abort the specified thread
  206. *
  207. * If the thread is not currently connected, do nothing and return FALSE to
  208. * indicate that the SCSI manager should abort the thread.
  209. *
  210. * Otherwise (the thread is active onthe controller), build an ABORT or
  211. * ABORT TAG message which will (eventually) be sent, causing the taget to
  212. * disconnect.  Set the state of the thread accordingly, and return TRUE to
  213. * indicate that the controller driver will handle the abort process.
  214. *
  215. * RETURNS: TRUE if the thread is being aborted by this driver (i.e. it is
  216. * currently active on the controller, else FALSE.
  217. *
  218. * NOMANUAL
  219. */
  220. BOOL scsiCtrlThreadAbort
  221.     (
  222.     SCSI_CTRL *   pScsiCtrl,
  223.     SCSI_THREAD * pThread
  224.     )
  225.     {
  226.     BOOL  tagged;
  227.     if (pThread != pScsiCtrl->pThread)
  228. return (FALSE);
  229.     
  230.     switch (pThread->state)
  231. {
  232. case SCSI_THREAD_INACTIVE:
  233. case SCSI_THREAD_WAITING:
  234. case SCSI_THREAD_DISCONNECTED:
  235.     return (FALSE);
  236.     break;
  237. default:
  238.     /*
  239.      * Build an ABORT (or ABORT TAG) message.  When this has been
  240.      * sent, the target should disconnect.  Mark the thread aborted
  241.      * and save the error code until disconnection.
  242.      */
  243.     tagged = (pThread->tagNumber != NONE);
  244.     pScsiCtrl->msgOutBuf[0] = tagged ? SCSI_MSG_ABORT_TAG
  245.                     : SCSI_MSG_ABORT;
  246.     pScsiCtrl->msgOutLength = 1;
  247.     pScsiCtrl->msgOutState  = SCSI_MSG_OUT_PENDING;
  248.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ABORTING);
  249.     break;
  250. }
  251.     return (TRUE);
  252.     }
  253. /*******************************************************************************
  254. *
  255. * scsiCtrlThreadInit - initialise a newly created thread structure
  256. *
  257. * This is a controller-specific function to initialise a thread.  For the
  258. * generic thread-level controller, a standard (exported) initialisation
  259. * function suffices.
  260. *
  261. * RETURNS: OK, or ERROR if initialisation fails
  262. *
  263. * NOMANUAL
  264. */
  265. STATUS scsiCtrlThreadInit
  266.     (
  267.     SCSI_CTRL *   pScsiCtrl,
  268.     SCSI_THREAD * pThread
  269.     )
  270.     {
  271.     return (scsiThreadInit (pThread));
  272.     }
  273. /*******************************************************************************
  274. *
  275. * scsiCtrlEvent - SCSI controller event processing routine
  276. *
  277. * Parse the event type and act accordingly.  Controller-level events are
  278. * handled within this function, and the event is then passed to the current
  279. * thread (if any) for thread-level processing.
  280. *
  281. * Note the special case when (re)selection occurs: if there is a current
  282. * thread when the event occurs, it receives the event (and is assumed to
  283. * defer itself) before the identification thread is made current.  The
  284. * event is then forwarded to the identification thread.
  285. *
  286. * RETURNS: N/A
  287. *
  288. * NOMANUAL
  289. */
  290. VOID scsiCtrlEvent
  291.     (
  292.     SCSI_CTRL *  pScsiCtrl,
  293.     SCSI_EVENT * pEvent
  294.     )
  295.     {
  296.     SCSI_THREAD * pThread = pScsiCtrl->pThread;
  297.     
  298.     SCSI_DEBUG_MSG ("scsiCtrlEvent: received event %d, thread = 0x%08xn",
  299.     pEvent->type, (int) pThread, 0, 0, 0, 0);
  300.     /*
  301.      * Do controller-level event processing
  302.      */
  303.     switch (pEvent->type)
  304. {
  305. case SCSI_EVENT_SELECTED:
  306. case SCSI_EVENT_RESELECTED:
  307.          if (pThread != 0)
  308.      scsiCtrlThreadEvent (pThread, pEvent);
  309.          pScsiCtrl->peerBusId = pEvent->busId;
  310.          pThread = pScsiCtrl->pThread = pScsiCtrl->pIdentThread;
  311.     pThread->role = (pEvent->type == SCSI_EVENT_SELECTED)
  312.        ? SCSI_ROLE_IDENT_TARG
  313.   : SCSI_ROLE_IDENT_INIT;
  314.     scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED);
  315.     break;
  316. case SCSI_EVENT_CONNECTED:
  317.          pScsiCtrl->peerBusId = pEvent->busId;
  318.     scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED);
  319.          /* assert (pThread != 0); */
  320.     break;
  321. case SCSI_EVENT_DISCONNECTED:
  322. case SCSI_EVENT_TIMEOUT:
  323.          pScsiCtrl->peerBusId = NONE;
  324.          pScsiCtrl->pThread   = 0;
  325.     scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED);
  326.     
  327.          /* assert (pThread != 0); */
  328.     break;
  329. case SCSI_EVENT_XFER_REQUEST:
  330.          /* assert (pThread != 0); */
  331.     break;
  332.         case SCSI_EVENT_PARITY_ERR:
  333.             break;
  334. case SCSI_EVENT_BUS_RESET:
  335.          pScsiCtrl->peerBusId = NONE;
  336.          pScsiCtrl->pThread   = 0;
  337.          scsiMgrBusReset (pScsiCtrl);
  338.     break;
  339. default:
  340.     logMsg ("scsiCtrlEvent: invalid event type (%d)n",
  341.     pEvent->type, 0, 0, 0, 0, 0);
  342.     break;
  343. }
  344.     /*
  345.      * If there's a thread on the controller, forward the event to it
  346.      */
  347.     if (pThread != 0)
  348. scsiCtrlThreadEvent (pThread, pEvent);
  349.     }
  350.     
  351. /*******************************************************************************
  352. *
  353. * scsiCtrlThreadEvent - SCSI thread event processing routine
  354. *
  355. * Parse the event type and forward it to the appropriate handler.  If there
  356. * is an established thread, and there is an outgoing message pending,
  357. * assert the SCSI ATN signal.
  358. *
  359. * RETURNS: N/A
  360. */
  361. LOCAL void scsiCtrlThreadEvent
  362.     (
  363.     SCSI_THREAD * pThread,
  364.     SCSI_EVENT *  pEvent
  365.     )
  366.     {
  367.     SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;
  368.     SCSI_DEBUG_MSG ("scsiCtrlThreadEvent: thread = 0x%08x: received event %dn",
  369.     (int) pThread, pEvent->type, 0, 0, 0, 0);
  370.     switch (pEvent->type)
  371. {
  372. case SCSI_EVENT_CONNECTED:
  373.          scsiCtrlThreadConnect (pThread, pEvent);
  374.     break;
  375. case SCSI_EVENT_DISCONNECTED:
  376.          scsiCtrlThreadDisconnect (pThread, pEvent);
  377.     break;
  378. case SCSI_EVENT_SELECTED:
  379. case SCSI_EVENT_RESELECTED:
  380.          scsiCtrlThreadSelect (pThread, pEvent);
  381.     break;
  382. case SCSI_EVENT_XFER_REQUEST:
  383.          scsiCtrlThreadInfoXfer (pThread, pEvent);
  384.     break;
  385. case SCSI_EVENT_TIMEOUT:
  386.          scsiCtrlThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
  387.     break;
  388.         case SCSI_EVENT_PARITY_ERR:
  389.     errnoSet (S_scsiLib_HARDWARE_ERROR);
  390.          scsiCtrlThreadFail (pThread, S_scsiLib_HARDWARE_ERROR);
  391.     break;
  392. case SCSI_EVENT_BUS_RESET:
  393.     /* SCSI manager handles this */
  394.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  395.     break;
  396. default:
  397.     logMsg ("scsiCtrlThreadEvent: invalid event type (%d)n",
  398.     pEvent->type, 0, 0, 0, 0, 0);
  399.     break;
  400. }
  401.     switch (pThread->state)
  402. {
  403. case SCSI_THREAD_ESTABLISHED:
  404.     /* assert ATN if there is a pending message out */
  405.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)
  406.      {
  407.      if ((*pScsiCtrl->scsiBusControl) (pScsiCtrl,
  408.          SCSI_BUS_ASSERT_ATN) != OK)
  409.     {
  410.     SCSI_ERROR_MSG ("scsiCtrlEvent: failed to assert ATN.n",
  411.     0, 0, 0, 0, 0, 0);
  412.     scsiCtrlThreadFail (pThread, errno);
  413.     }
  414. }
  415.     break;
  416. default:
  417.     break;
  418. }
  419.     }
  420.     
  421. /*******************************************************************************
  422. *
  423. * scsiCtrlThreadConnect - thread connection event processing routine
  424. *
  425. * Set transfer parameters for the newly connected thread.  Set the thread
  426. * state to ESTABLISHED if the whole identification message has been sent,
  427. * otherwise set its state to IDENTIFICATION OUT.
  428. *
  429. * RETURNS: N/A
  430. */
  431. LOCAL void scsiCtrlThreadConnect
  432.     (
  433.     SCSI_THREAD * pThread,
  434.     SCSI_EVENT *  pEvent
  435.     )
  436.     {
  437.     SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev;
  438.     SCSI_TARGET *   pScsiTarget  = pThread->pScsiTarget;
  439.     
  440.     if (pThread->state != SCSI_THREAD_CONNECTING)
  441. {
  442. logMsg ("scsiCtrlThreadConnect: thread 0x%08x: invalid state (%d)n",
  443. (int) pThread, pThread->state, 0, 0, 0, 0);
  444. return;
  445. }
  446.     SCSI_DEBUG_MSG ("scsi: connected to target %d, phys dev = 0x%08xn",
  447.     pScsiTarget->scsiDevBusId, (int)pScsiPhysDev, 0, 0, 0, 0);
  448.     pThread->nBytesIdent = pEvent->nBytesIdent;
  449.     if (scsiCtrlXferParamsSet (pThread) != OK)
  450. {
  451.         scsiCtrlThreadFail (pThread, errno);
  452. return;
  453. }
  454.     if (pThread->nBytesIdent < pThread->identMsgLength)
  455. {
  456.      scsiCtrlThreadStateSet (pThread, SCSI_THREAD_IDENT_OUT);
  457. }
  458.     else
  459. {
  460. scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  461. }
  462.     }
  463. /*******************************************************************************
  464. *
  465. * scsiCtrlThreadDisconnect - thread disconnect event processing routine
  466. *
  467. * There are basically three cases:
  468. *
  469. *   1) after a DISCONNECT message has been received: disconnect the thread
  470. *
  471. *   2) after a COMMAND COMPLETE message has been received, or an ABORT
  472. *    message has been sent, complete the thread normally
  473. *
  474. *   3) otherwise, fail the thread with an "unexpected disconnection" error
  475. *
  476. * RETURNS: N/A
  477. */
  478. LOCAL void scsiCtrlThreadDisconnect
  479.     (
  480.     SCSI_THREAD * pThread,
  481.     SCSI_EVENT *  pEvent
  482.     )
  483.     {
  484.     if (pThread->pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)
  485. {
  486. SCSI_DEBUG_MSG ("scsiCtrlThreadDisconnect: thread 0x%08x: "
  487. "message out not sent (ignored).n",
  488. (int) pThread, 0, 0, 0, 0, 0);
  489. }
  490.     switch (pThread->state)
  491. {
  492. case SCSI_THREAD_WAIT_DISCONNECT:
  493.          scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_DISCONNECTED);
  494.          scsiCtrlThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED);
  495.     break;
  496. case SCSI_THREAD_WAIT_COMPLETE:
  497.     scsiCtrlThreadComplete (pThread);
  498.     break;
  499. case SCSI_THREAD_WAIT_ABORT:
  500.     scsiCtrlThreadComplete (pThread);
  501.     break;
  502. default:
  503.     SCSI_ERROR_MSG ("scsiCtrlThreadDisconnect: thread 0x%08x: "
  504.     "unexpected disconnectionn",
  505.     (int) pThread, 0, 0, 0, 0, 0);
  506.     scsiCtrlThreadFail (pThread, S_scsiLib_DISCONNECTED);
  507.     break;
  508. }
  509.     }
  510.     
  511. /*******************************************************************************
  512. *
  513. * scsiCtrlThreadSelect - thread selection event processing routine
  514. *
  515. * Forward the event to the proper handler depending on the role played by
  516. * the thread.
  517. *
  518. * RETURNS: N/A
  519. */
  520. LOCAL void scsiCtrlThreadSelect
  521.     (
  522.     SCSI_THREAD * pThread,
  523.     SCSI_EVENT *  pEvent
  524.     )
  525.     {
  526.     switch (pThread->state)
  527. {
  528. case SCSI_THREAD_CONNECTING:
  529.     scsiCtrlThreadDefer (pThread);
  530.     break;
  531. case SCSI_THREAD_INACTIVE:
  532.     scsiCtrlIdentInCommence (pThread, pEvent);
  533.     break;
  534. default:
  535.     logMsg ("scsiCtrlThreadConnect: thread 0x%08x: "
  536.     "invalid state (%d)n",
  537.     (int) pThread, pThread->state, 0, 0, 0, 0);
  538.     break;
  539. }
  540.     }
  541. /*******************************************************************************
  542. *
  543. * scsiCtrlThreadInfoXfer - thread info transfer request event processing
  544. *
  545. * Forward the event to the proper handler depending on the thread's current
  546. * state.
  547. *
  548. * RETURNS: N/A
  549. */
  550. LOCAL void scsiCtrlThreadInfoXfer
  551.     (
  552.     SCSI_THREAD * pThread,
  553.     SCSI_EVENT *  pEvent
  554.     )
  555.     {
  556.     switch (pThread->state)
  557. {
  558. case SCSI_THREAD_IDENT_OUT:
  559.     scsiCtrlIdentOutXfer (pThread, pEvent);
  560.     break;
  561. case SCSI_THREAD_IDENT_IN:
  562.     scsiCtrlIdentInXfer (pThread, pEvent);
  563.     break;
  564. case SCSI_THREAD_ABORTING:
  565.     scsiCtrlAbortXfer (pThread, pEvent);
  566.     break;
  567.     
  568. default:
  569.     scsiCtrlNormalXfer (pThread, pEvent);
  570.     break;
  571. }
  572.     }
  573.     
  574. /*******************************************************************************
  575. *
  576. * scsiCtrlIdentOutXfer - process info. xfer request during identification out
  577. *
  578. * Check that a message out transfer is being requested: fail the thread if
  579. * not.  Transfer the remainder of the identification message, including a
  580. * queue tag message if applicable.  Set the thread state to ESTABLISHED.
  581. *
  582. * This code assumes that the target cannot request a new info transfer phase
  583. * until it has read the entire identification sequence (either 1 or 3 bytes).
  584. * (This seems to be required by the SCSI standard.)
  585. *
  586. * RETURNS: N/A
  587. */
  588. LOCAL void scsiCtrlIdentOutXfer
  589.     (
  590.     SCSI_THREAD * pThread,
  591.     SCSI_EVENT *  pEvent
  592.     )
  593.     {
  594.     SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;
  595.     int         nBytes;
  596.     int         maxBytes;
  597.     /*
  598.      * Check for logical errors
  599.      */
  600.     if (pThread->state != SCSI_THREAD_IDENT_OUT)
  601. {
  602. logMsg ("scsiCtrlIdentOutXfer: invalid state (%d)n",
  603. pThread->state, 0, 0, 0, 0, 0);
  604. return;
  605. }
  606.     
  607.     if ((maxBytes = pThread->identMsgLength - pThread->nBytesIdent) == 0)
  608. {
  609. logMsg ("scsiCtrlIdentOutXfer: no identification message!n",
  610. 0, 0, 0, 0, 0, 0);
  611. return;
  612. }
  613.     
  614.     if (pEvent->phase != SCSI_MSG_OUT_PHASE)
  615. {
  616. SCSI_ERROR_MSG ("scsiCtrlIdentOutXfer: unexpected phase (%d) "
  617. "requested during identification outn",
  618.         pEvent->phase, 0, 0, 0, 0, 0);
  619. scsiCtrlThreadFail (pThread, S_scsiLib_INVALID_PHASE);
  620.         return;
  621. }
  622.     /*
  623.      * Transfer the whole remaining identification sequence (in one go)
  624.      */
  625.     nBytes = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  626.          SCSI_MSG_OUT_PHASE,
  627.                                          pThread->identMsg + pThread->nBytesIdent,
  628.          maxBytes);
  629.     pThread->nBytesIdent += nBytes;
  630.     if (nBytes != maxBytes)
  631.         {
  632. /*
  633.  *  The target has most likely requested a new phase.  The only
  634.  *  legitimate reason for this is to reject a queue tag message if
  635.  *  it does not support queueing - this should be dealt with by the
  636.  *  normal message reject mechanism.  (The thread should be treated
  637.  *  as if it were untagged.)
  638.  *
  639.  *  Hence, we continue and set the thread established anyway.
  640.  */
  641.         SCSI_DEBUG_MSG ("scsiCtrlIdentOutXfer: identification incomplete - "
  642. "%d of %d bytes sentn",
  643. pThread->nBytesIdent, pThread->identMsgLength,
  644.                0, 0, 0, 0);
  645.         }
  646.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  647.     }
  648.     
  649. /*******************************************************************************
  650. *
  651. * scsiCtrlIdentInCommence - commence incoming identification
  652. *
  653. * Copy the identification message read by the driver into the thread's buffer.
  654. * Parse the identification message so far (see "scsiCtrlIdentInContinue()").
  655. * Acknowledge the last message-in byte read (if any).
  656. *
  657. * RETURNS: N/A
  658. */
  659. LOCAL void scsiCtrlIdentInCommence
  660.     (
  661.     SCSI_THREAD * pThread,
  662.     SCSI_EVENT *  pEvent
  663.     )
  664.     {
  665.     bcopy ((char *)pEvent->identMsg, (char *)pThread->identMsg,
  666.    pEvent->nBytesIdent);
  667.     pThread->nBytesIdent = pEvent->nBytesIdent;
  668.     scsiCtrlIdentInContinue (pThread);
  669.     if (pThread->nBytesIdent > 0)
  670. {
  671. scsiCtrlMsgInAck (pThread->pScsiCtrl);
  672. }
  673.     }
  674.     
  675. /*******************************************************************************
  676. *
  677. * scsiCtrlIdentInXfer - process info. xfer during incoming identification.
  678. *
  679. * Check that a message in transfer is being requested; if not, fail the
  680. * thread (even though, at this stage, it's not a client thread).  Transfer
  681. * the message byte in, then parse the message so far.  Acknowledge the
  682. * message in byte.
  683. *
  684. * RETURNS: N/A
  685. */
  686. LOCAL void scsiCtrlIdentInXfer
  687.     (
  688.     SCSI_THREAD * pThread,
  689.     SCSI_EVENT *  pEvent
  690.     )
  691.     {
  692.     SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;
  693.     
  694.     if (pThread->state != SCSI_THREAD_IDENT_IN)
  695. {
  696. logMsg ("scsiCtrlIdentInXfer: invalid state (%d)n",
  697. pThread->state, 0, 0, 0, 0, 0);
  698. return;
  699. }
  700.     
  701.     if (pEvent->phase != SCSI_MSG_IN_PHASE)
  702. {
  703. SCSI_ERROR_MSG ("scsiCtrlIdentInXfer: unexpected phase (%d) "
  704. "requested during identification inn",
  705.         pEvent->phase, 0, 0, 0, 0, 0);
  706. scsiCtrlThreadFail (pThread, 0);
  707.         return;
  708. }
  709.     if ((*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  710.     SCSI_MSG_IN_PHASE,
  711.                                     pThread->identMsg + pThread->nBytesIdent,
  712.     1) != 1)
  713.         {
  714.         SCSI_ERROR_MSG ("scsiCtrlIdentInXfer: message in transfer failedn",
  715. 0, 0, 0, 0, 0, 0);
  716. scsiCtrlThreadFail (pThread, 0);
  717.         return;
  718.         }
  719.     ++pThread->nBytesIdent;
  720.     scsiCtrlIdentInContinue (pThread);
  721.     scsiCtrlMsgInAck (pScsiCtrl);
  722.     }
  723.     
  724. /*******************************************************************************
  725. *
  726. * scsiCtrlIdentInContinue - continue incoming identification
  727. *
  728. * Parse the message built up so far.  If it is not yet complete, do nothing.
  729. * If the message is complete, attempt to reconnect the thread it identifies,
  730. * and deactivate this thread (the identification thread is no longer active).
  731. * Otherwise (identification has failed), abort the identification sequence.
  732. *
  733. * RETURNS: N/A
  734. */
  735. LOCAL void scsiCtrlIdentInContinue
  736.     (
  737.     SCSI_THREAD * pThread
  738.     )
  739.     {
  740.     SCSI_THREAD * pNewThread;
  741.     SCSI_CTRL   * pScsiCtrl  = pThread->pScsiCtrl;
  742.     SCSI_IDENT_STATUS status;
  743.     SCSI_THREAD_STATE state;
  744.     status = scsiIdentMsgParse (pScsiCtrl, pThread->identMsg,
  745.                 pThread->nBytesIdent,
  746.                &pThread->pScsiPhysDev,
  747.                &pThread->tagNumber);
  748.     switch (status)
  749. {
  750. case SCSI_IDENT_INCOMPLETE:
  751.     state = SCSI_THREAD_IDENT_IN;
  752.     break;
  753. case SCSI_IDENT_COMPLETE:
  754.     scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_RECONNECTED);
  755.     if ((pNewThread = scsiMgrPhysDevActiveThreadFind (
  756. pThread->pScsiPhysDev,
  757. pThread->tagNumber)) == 0)
  758. {
  759. state = SCSI_THREAD_IDENT_ABORTING;
  760. }
  761.     else
  762. {
  763.      scsiCtrlThreadReconnect (pNewThread);
  764.      state = SCSI_THREAD_INACTIVE;
  765. }
  766.     break;
  767. case SCSI_IDENT_FAILED:
  768.     state = SCSI_THREAD_IDENT_ABORTING;
  769.     break;
  770. default:
  771.     logMsg ("scsiCtrlIdentInContinue: invalid ident status (%d)n",
  772.               status, 0, 0, 0, 0, 0);
  773.     state = SCSI_THREAD_INACTIVE;
  774.     break;
  775. }
  776.     if (state == SCSI_THREAD_IDENT_ABORTING)
  777. scsiCtrlThreadAbort (pScsiCtrl, pThread);
  778.     scsiCtrlThreadStateSet (pThread, state);
  779.     }
  780.     
  781. /*******************************************************************************
  782. *
  783. * scsiCtrlThreadReconnect - reconnect a thread
  784. *
  785. * Restore the SCSI pointers for the thread (this really should be in a more
  786. * generic section of code - perhaps part of the SCSI manager's thread event
  787. * procesing ?).  Set the controller's transfer parameters for the newly 
  788. * connected thread.  Set the thread's state to ESTABLISHED.
  789. *
  790. * RETURNS: N/A
  791. */
  792. LOCAL void scsiCtrlThreadReconnect
  793.     (
  794.     SCSI_THREAD * pThread
  795.     )
  796.     {
  797.     SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;
  798.     
  799.     SCSI_DEBUG_MSG ("scsiCtrlThreadReconnect: reconnecting thread 0x%08xn",
  800.     (int) pThread, 0, 0, 0, 0, 0);
  801.     pScsiCtrl->pThread = pThread;
  802.     /*
  803.      *  Reset controller state variables for the new thread
  804.      */
  805.     pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE;
  806.     pScsiCtrl->msgInState  = SCSI_MSG_IN_NONE;
  807.     /* Implied RESTORE POINTERS action: see "scsiMsgInComplete ()" */
  808.     pThread->activeDataAddress = pThread->savedDataAddress;
  809.     pThread->activeDataLength  = pThread->savedDataLength;
  810.     if (scsiCtrlXferParamsSet (pThread) != OK)
  811. {
  812. SCSI_ERROR_MSG ("scsiCtrlThreadReconnect: failed to set xfer params.n",
  813. 0, 0, 0, 0, 0, 0);
  814. scsiCtrlThreadFail (pThread, errno);
  815. return;
  816. }
  817.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  818.     }
  819. /*******************************************************************************
  820. *
  821. * scsiCtrlNormalXfer - initiator info transfer request event processing
  822. *
  823. * Check for phase changes during message-in and message-out transfers,
  824. * handling them accordingly (neither is necessarily an error condition).
  825. * Call the appropriate handler routine for the message transfer phase
  826. * requested by the target.
  827. *
  828. * RETURNS: N/A
  829. */
  830. LOCAL void scsiCtrlNormalXfer
  831.     (
  832.     SCSI_THREAD * pThread,
  833.     SCSI_EVENT *  pEvent
  834.     )
  835.     {
  836.     STATUS status;
  837.     SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;
  838.     int         phase     = pEvent->phase;
  839.     switch (pThread->state)
  840. {
  841. case SCSI_THREAD_ESTABLISHED:
  842. case SCSI_THREAD_WAIT_COMPLETE:
  843. case SCSI_THREAD_WAIT_DISCONNECT:
  844. case SCSI_THREAD_WAIT_ABORT:
  845.     break;
  846. default:
  847.     logMsg ("scsiCtrlNormalXfer: thread 0x%08x: invalid state (%d)n",
  848.     (int) pThread, pThread->state, 0, 0, 0, 0);
  849.     return;
  850. }
  851.     
  852.     SCSI_DEBUG_MSG ("scsiCtrlNormalXfer: thread 0x%08x: "
  853.     "target requesting %s phasen",
  854.     (int) pThread, (int) scsiPhaseNameGet (phase),
  855.     0, 0, 0, 0);
  856.     /*
  857.      * Check for phase change during message in handling: this probably
  858.      * results from our having asserted ATN in order to send a message out.
  859.      * This would occur if we reject a partially read incoming message.
  860.      *
  861.      * Reset the message-in state in this case.
  862.      */
  863.     if (phase != SCSI_MSG_IN_PHASE)
  864. {
  865.      switch (pScsiCtrl->msgInState)
  866.     {
  867.     case SCSI_MSG_IN_NONE:
  868.      break;
  869.     default:
  870.              SCSI_DEBUG_MSG ("scsiCtrlNormalXfer: phase change "
  871. "during msg inn",
  872.      0, 0, 0, 0, 0, 0);
  873.      pScsiCtrl->msgInState = SCSI_MSG_IN_NONE;
  874.     break;
  875.     }
  876. }
  877.     /*
  878.      * Check for phase change during (immediately after) message out.
  879.      *
  880.      * If this happens while there is a pending message out, there are
  881.      * two possibilities.  Either the target has not yet noticed our ATN
  882.      * (i.e., no message data has yet been transferred) or it has changed
  883.      * phase in mid-transfer (probably to reject the message we're sending).
  884.      * In either case, the message state is left pending so that it will be
  885.      * (re-)sent or rejected as appropriate.
  886.      *
  887.      * If it happens just after a message out has been sent, it means the
  888.      * target has accepted the message.  In this case the message out state
  889.      * is reset, and the message out completion routine is called.
  890.      */
  891.     if (phase != SCSI_MSG_OUT_PHASE)
  892. {
  893.      switch (pScsiCtrl->msgOutState)
  894.     {
  895.     case SCSI_MSG_OUT_NONE:
  896.     case SCSI_MSG_OUT_PENDING:
  897.      break;
  898.     case SCSI_MSG_OUT_SENT:
  899.      pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE;
  900.      (void) scsiMsgOutComplete (pScsiCtrl, pThread);
  901.      break;
  902.             default:
  903.         break;
  904.     }
  905. }
  906.     
  907.     /*
  908.      * Perform information transfer requested by target
  909.      */
  910.     switch (phase)
  911. {
  912. case SCSI_DATA_OUT_PHASE:
  913.     status = scsiCtrlDataOutAction (pScsiCtrl, pThread);
  914.     break;
  915.     
  916. case SCSI_DATA_IN_PHASE:
  917.     status = scsiCtrlDataInAction (pScsiCtrl, pThread);
  918.     break;
  919.     
  920. case SCSI_COMMAND_PHASE:
  921.     status = scsiCtrlCommandAction (pScsiCtrl, pThread);
  922.     break;
  923.     
  924. case SCSI_STATUS_PHASE:
  925.     status = scsiCtrlStatusAction (pScsiCtrl, pThread);
  926.     break;
  927.     
  928. case SCSI_MSG_OUT_PHASE:
  929.     status = scsiCtrlMsgOutAction (pScsiCtrl, pThread);
  930.     break;
  931.     
  932. case SCSI_MSG_IN_PHASE:
  933.     status = scsiCtrlMsgInAction (pScsiCtrl, pThread);
  934.     break;
  935.     
  936. default:
  937.     SCSI_ERROR_MSG ("scsiCtrlNormalXfer: invalid phase (%d)n",
  938.            phase, 0, 0, 0, 0, 0);
  939.     scsiCtrlThreadFail (pThread, S_scsiLib_INVALID_PHASE);
  940.     return;
  941. }
  942.     if (status != OK)
  943.         {
  944.         SCSI_ERROR_MSG ("scsiCtrlNormalXfer: transfer failedn",
  945. 0, 0, 0, 0, 0, 0);
  946. scsiCtrlThreadFail (pThread, errno);
  947.         }
  948.     }
  949.     
  950. /*******************************************************************************
  951. *
  952. * scsiCtrlAbortXfer - process info. xfer request for an aborting thread
  953. *
  954. * Check that the phase requested is message out.  Transfer the single-byte
  955. * message out.  Set the thread's state to indicate that it's waiting for the
  956. * target to disconnect after an abort message.
  957. *
  958. * RETURNS: N/A
  959. */
  960. LOCAL void scsiCtrlAbortXfer
  961.     (
  962.     SCSI_THREAD * pThread,
  963.     SCSI_EVENT *  pEvent
  964.     )
  965.     {
  966.     SCSI_CTRL * pScsiCtrl = pThread->pScsiCtrl;
  967.     
  968.     if (pThread->state != SCSI_THREAD_ABORTING)
  969. {
  970. logMsg ("scsiCtrlAbortXfer: invalid state (%d)n",
  971. pThread->state, 0, 0, 0, 0, 0);
  972. return;
  973. }
  974.     
  975.     if (pEvent->phase != SCSI_MSG_OUT_PHASE)
  976. {
  977. SCSI_ERROR_MSG ("scsiCtrlAbortXfer: unexpected phase (%d) "
  978. "requested during thread abortn",
  979.         pEvent->phase, 0, 0, 0, 0, 0);
  980.         return;
  981. }
  982.     if ((*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  983.     SCSI_MSG_OUT_PHASE,
  984.                                     pScsiCtrl->msgOutBuf,
  985.     1) != 1)
  986.         {
  987.         SCSI_ERROR_MSG ("scsiCtrlAbortXfer: message out transfer failedn",
  988. 0, 0, 0, 0, 0, 0);
  989.         return;
  990.         }
  991.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_WAIT_ABORT);
  992.     }
  993.     
  994. /******************************************************************************
  995. *
  996. * scsiCtrlDataOutAction - handle DATA OUT information transfer phase
  997. *
  998. * Transfer out the remaining data count or the maximum possible for the
  999. * controller, whichever is the smaller.  Update the active data pointer
  1000. * and count to reflect the number of bytes transferred - this may be fewer
  1001. * than requested, e.g. if the target requests a different phase.
  1002. *
  1003. * RETURNS: OK, or ERROR if transfer fails.
  1004. */
  1005. LOCAL STATUS scsiCtrlDataOutAction
  1006.     (
  1007.     SCSI_CTRL   *pScsiCtrl, /* ptr to SCSI controller info */
  1008.     SCSI_THREAD *pThread /* ptr to thread info */
  1009.     )
  1010.     {
  1011.     UINT xferCount; /* number of bytes transferred */
  1012.     UINT maxBytes; /* max number of bytes to send */
  1013.     maxBytes = min (pThread->activeDataLength, pScsiCtrl->maxBytesPerXfer);
  1014.     
  1015.     xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  1016.     SCSI_DATA_OUT_PHASE,
  1017.                                             pThread->activeDataAddress,
  1018.                                             maxBytes);
  1019.     if (xferCount == ERROR)
  1020.      return (ERROR);
  1021.     pThread->activeDataAddress += xferCount;
  1022.     pThread->activeDataLength  -= xferCount;
  1023.     return (OK);
  1024.     }
  1025. /******************************************************************************
  1026. *
  1027. * scsiCtrlDataInAction - handle DATA IN information transfer phase
  1028. *
  1029. * Transfer in the remaining data count or the maximum possible for the
  1030. * controller, whichever is the smaller.  Update the active data pointer
  1031. * and count to reflect the number of bytes transferred - this may be fewer
  1032. * than requested, e.g. if the target requests a different phase.
  1033. *
  1034. * NOTE: the "additional length byte" handling done in previous versions of
  1035. * the SCSI library is unnecessary when disconnect/reconnect is supported.
  1036. *
  1037. * SCSI requires the target to honour the initiator's maximum allocation
  1038. * length, so there can never be more incoming data than was requested.
  1039. * Conversely, if the target has less data to send than the initiator
  1040. * expects, it will simply terminate the DATA IN transfer phase early.
  1041. *
  1042. * Unfortunately the currently defined SCSI transaction interface does not
  1043. * allow the client task to find out how many data bytes were actually
  1044. * received in either case.
  1045. * RETURNS: OK, or ERROR if transfer fails.
  1046. */
  1047. LOCAL STATUS scsiCtrlDataInAction
  1048.     (
  1049.     SCSI_CTRL   *pScsiCtrl, /* ptr to SCSI controller info */
  1050.     SCSI_THREAD *pThread /* ptr to thread info */
  1051.     )
  1052.     {
  1053.     UINT xferCount; /* number of bytes transferred */
  1054.     UINT maxBytes; /* max number of bytes to recv */
  1055.     maxBytes = min (pThread->activeDataLength, pScsiCtrl->maxBytesPerXfer);
  1056.     
  1057.     xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  1058.     SCSI_DATA_IN_PHASE,
  1059.                                             pThread->activeDataAddress,
  1060.                                             maxBytes);
  1061.     if (xferCount == ERROR)
  1062.      return (ERROR);
  1063.     pThread->activeDataAddress += xferCount;
  1064.     pThread->activeDataLength  -= xferCount;
  1065.     return (OK);
  1066.     }
  1067. /******************************************************************************
  1068. *
  1069. * scsiCtrlCommandAction - handle COMMAND information transfer phase
  1070. *
  1071. * Note: it is assumed that a command transfer must be completed fully, i.e.
  1072. * the target cannot disconnect.  It is also assumed that the length of a
  1073. * command transfer never exceeds the maximum byte count the controller can
  1074. * handle.
  1075. *
  1076. * RETURNS: OK, or ERROR if transfer fails.
  1077. */
  1078. LOCAL STATUS scsiCtrlCommandAction
  1079.     (
  1080.     SCSI_CTRL   *pScsiCtrl, /* ptr to SCSI controller info */
  1081.     SCSI_THREAD *pThread /* ptr to thread info */
  1082.     )
  1083.     {
  1084.     UINT xferCount; /* number of bytes transferred */
  1085.     xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  1086.     SCSI_COMMAND_PHASE,
  1087.                                             pThread->cmdAddress,
  1088.                                             pThread->cmdLength);
  1089.     return ((xferCount == pThread->cmdLength) ? OK : ERROR);
  1090.     }
  1091. /******************************************************************************
  1092. *
  1093. * scsiCtrlStatusAction - handle STATUS information transfer phase
  1094. *
  1095. * Note: it is assumed that a status transfer must be completed fully, i.e.
  1096. * the target cannot disconnect.  It is also assumed that the length of a
  1097. * status transfer never exceeds the maximum byte count the controller can
  1098. * handle.
  1099. *
  1100. * RETURNS: OK, or ERROR if transfer fails.
  1101. */
  1102. LOCAL STATUS scsiCtrlStatusAction
  1103.     (
  1104.     SCSI_CTRL   *pScsiCtrl, /* ptr to SCSI controller info */
  1105.     SCSI_THREAD *pThread /* ptr to thread info */
  1106.     )
  1107.     {
  1108.     UINT xferCount; /* number of bytes transferred */
  1109.     xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  1110.     SCSI_STATUS_PHASE,
  1111.                                             pThread->statusAddress,
  1112.                                             pThread->statusLength);
  1113.     return ((xferCount == pThread->statusLength) ? OK : ERROR);
  1114.     }
  1115. /******************************************************************************
  1116. *
  1117. * scsiCtrlMsgOutAction - respond to a request to send a SCSI message
  1118. *
  1119. * This routine handles a SCSI message out transfer request.  If there is no
  1120. * message available to send to the target, a SCSI NO-OP message is sent.
  1121. * If there is a message which has already been sent, ATN is asserted (this is
  1122. * a requirement imposed by the SCSI specification).
  1123. *
  1124. * Data is output from the message-out buffer in a single transfer.  The
  1125. * controller hardware must keep ATN asserted until just before ACK is
  1126. * asserted during the last byte of the outgoing message, per SCSI 5.2.1.
  1127. *
  1128. * Assuming the information transfer does not fail altogether, there are two
  1129. * "successful" outcomes:
  1130. *
  1131. * 1)    the entire message is transferred - in this case the message state
  1132. *    is set to SENT.  However, the target is not deemed to have accepted
  1133. *    the message until it requests a different phase - this is detected
  1134. *    and acted upon in "scsiCtrlNormalXfer()".  (If the target continues
  1135. *    to request a MSG OUT transfer, it wants the current message to be
  1136. *    re-sent.)
  1137. *
  1138. * 2) the message is only partially transferred - most likely because the
  1139. *    target has changed phase (e.g., to send a Reject message) before
  1140. *    all the message out bytes have been transferred.  In this case the
  1141. *    message state remains PENDING.  If the target is about to reject it,
  1142. *    the state will be reset then, otherwise we will try to send it again
  1143. *    when the target next requests a message out transfer.
  1144. *
  1145. * Note: it is assumed that the length of the message never exceeds the
  1146. * maximum byte count the controller can handle.
  1147. *
  1148. * RETURNS: OK, or ERROR if information transfer phase fails.
  1149. */
  1150. LOCAL STATUS scsiCtrlMsgOutAction
  1151.     (
  1152.     SCSI_CTRL   *pScsiCtrl, /* ptr to SCSI controller info */
  1153.     SCSI_THREAD *pThread /* ptr to thread info */
  1154.     )
  1155.     {
  1156.     UINT xferCount; /* number of bytes transferred */
  1157.     
  1158.     if ((pScsiCtrl->msgOutState == SCSI_MSG_OUT_SENT) &&
  1159. (pScsiCtrl->msgOutLength > 1))
  1160. {
  1161. /* target is retrying: need to assert ATN (SCSI 5.1.9.2) */
  1162. if ((*pScsiCtrl->scsiBusControl) (pScsiCtrl,
  1163.           SCSI_BUS_ASSERT_ATN) != OK)
  1164.     {
  1165.     SCSI_ERROR_MSG ("scsiCtrlMsgOutAction: can't assert ATN.n",
  1166.     0, 0, 0, 0, 0, 0);
  1167.     return (ERROR);
  1168.     }
  1169. }
  1170.     
  1171.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_NONE)
  1172. {
  1173. pScsiCtrl->msgOutBuf[0] = SCSI_MSG_NO_OP;
  1174. pScsiCtrl->msgOutLength = 1;
  1175. }
  1176.     xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  1177.     SCSI_MSG_OUT_PHASE,
  1178.                                             pScsiCtrl->msgOutBuf,
  1179.                                             pScsiCtrl->msgOutLength);
  1180.     if (xferCount == ERROR)
  1181. return (ERROR);
  1182.     if (xferCount == pScsiCtrl->msgOutLength)
  1183. pScsiCtrl->msgOutState =  SCSI_MSG_OUT_SENT;
  1184.     return (OK);
  1185.     }
  1186. /******************************************************************************
  1187. *
  1188. * scsiCtrlMsgInAction - respond to an incoming SCSI message
  1189. *
  1190. * Read and handle an incoming message from the target.
  1191. *
  1192. * Note that if the incoming message is a SCSI Extended Message, it needs to
  1193. * be read in three chunks (the message type, the additional length and the
  1194. * extended message itself).  This is achieved by using a finite state machine
  1195. * which cycles through the chunks, returning to the phase sequencing code
  1196. * until the message is complete.
  1197. *
  1198. * RETURNS: OK, or ERROR if information transfer phase fails.
  1199. */
  1200. LOCAL STATUS scsiCtrlMsgInAction
  1201.     (
  1202.     SCSI_CTRL   *pScsiCtrl, /* ptr to SCSI controller info */
  1203.     SCSI_THREAD *pThread /* ptr to thread info */
  1204.     )
  1205.     {
  1206.     /*
  1207.      * Handle (possibly partial) message transfer
  1208.      */
  1209.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)
  1210. SCSI_DEBUG_MSG ("scsiCtrlMsgInAction: msg in while msg out pendingn",
  1211. 0, 0, 0, 0, 0, 0);
  1212.     if (scsiCtrlMsgInXfer (pScsiCtrl) != OK)
  1213. return (ERROR);
  1214.     /*
  1215.      *  If we have a complete message, parse it and respond appropriately
  1216.      */
  1217.     if (pScsiCtrl->msgInState == SCSI_MSG_IN_NONE)
  1218.         (void) scsiMsgInComplete (pScsiCtrl, pThread);
  1219.     /*
  1220.      * Negate ACK to allow target to continue; if rejecting message,
  1221.      * also assert ATN.
  1222.      */
  1223.     if (scsiCtrlMsgInAck (pScsiCtrl) != OK)
  1224. {
  1225. SCSI_ERROR_MSG ("scsiCtrlMsgInAction: scsiCtrlMsgInAck failed.n",
  1226. 0, 0, 0, 0, 0, 0);
  1227. return (ERROR);
  1228. }
  1229.     return (OK);
  1230.     }
  1231. /******************************************************************************
  1232. *
  1233. * scsiCtrlMsgInXfer - handle MSG IN information transfer
  1234. *
  1235. * Note: does not necessarily read a complete message.
  1236. *
  1237. * Note: it is assumed that a message in transfer must be completed fully, i.e.
  1238. * the target cannot disconnect.  It is also assumed that the length of the
  1239. * message (fragment) does not exceed the maximum byte count the controller
  1240. * can handle.
  1241. *
  1242. * RETURNS: OK, or ERROR if transfer fails.
  1243. */
  1244. LOCAL STATUS scsiCtrlMsgInXfer
  1245.     (
  1246.     SCSI_CTRL *pScsiCtrl /* ptr to SCSI controller info */
  1247.     )
  1248.     {
  1249.     UINT xferCount; /* number of bytes transferred */
  1250.     UINT maxBytes; /* max number of bytes to read */
  1251.     SCSI_MSG_IN_STATE state = pScsiCtrl->msgInState;
  1252.     switch (state)
  1253.         {
  1254.      case SCSI_MSG_IN_NONE:
  1255.     pScsiCtrl->msgInLength = 0;
  1256.     maxBytes = 1;
  1257.     break;
  1258. case SCSI_MSG_IN_SECOND_BYTE:
  1259.     maxBytes = 1;
  1260.     break;
  1261.     
  1262. case SCSI_MSG_IN_EXT_MSG_LEN:
  1263.     maxBytes = 1;
  1264.     break;
  1265. case SCSI_MSG_IN_EXT_MSG_DATA:
  1266.     if ((maxBytes = pScsiCtrl->msgInBuf[SCSI_EXT_MSG_LENGTH_BYTE]) == 0)
  1267. maxBytes = SCSI_EXT_MSG_MAX_LENGTH;
  1268.     break;
  1269. default:
  1270.             SCSI_MSG ("scsiCtrlMsgInXfer: invalid state (%d)n", state,
  1271.       0, 0, 0, 0, 0);
  1272.     pScsiCtrl->msgInState = SCSI_MSG_IN_NONE;
  1273.             return (ERROR);
  1274. }
  1275.     
  1276.     xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,
  1277.     SCSI_MSG_IN_PHASE,
  1278.     pScsiCtrl->msgInBuf +
  1279.         pScsiCtrl->msgInLength,
  1280.     maxBytes);
  1281.     
  1282.     if (xferCount != maxBytes)
  1283. {
  1284. SCSI_ERROR_MSG ("scsiCtrlMsgInXfer: transfer failedn",
  1285. 0, 0, 0, 0, 0, 0);
  1286. if (xferCount != ERROR)
  1287.     errnoSet (S_scsiLib_HARDWARE_ERROR);
  1288. return (ERROR);
  1289. }
  1290.     switch (state)
  1291. {
  1292.         case SCSI_MSG_IN_NONE:
  1293.             if (pScsiCtrl->msgInBuf[0] == SCSI_MSG_EXTENDED_MESSAGE)
  1294.                 state = SCSI_MSG_IN_EXT_MSG_LEN;
  1295.     else if (SCSI_IS_TWO_BYTE_MSG (pScsiCtrl->msgInBuf[0]))
  1296. state = SCSI_MSG_IN_SECOND_BYTE;
  1297.     else
  1298.                 state = SCSI_MSG_IN_NONE;
  1299.             break;
  1300. case SCSI_MSG_IN_SECOND_BYTE:
  1301.     state = SCSI_MSG_IN_NONE;
  1302.     break;
  1303.         case SCSI_MSG_IN_EXT_MSG_LEN:
  1304.             state = SCSI_MSG_IN_EXT_MSG_DATA;
  1305.             break;
  1306.         case SCSI_MSG_IN_EXT_MSG_DATA:
  1307.             state = SCSI_MSG_IN_NONE;
  1308.             break;
  1309.         default:
  1310.             SCSI_MSG ("scsiCtrlMsgInXfer: invalid state (%d)n", state,
  1311.       0, 0, 0, 0, 0);
  1312.     pScsiCtrl->msgInState = SCSI_MSG_IN_NONE;
  1313.             return (ERROR);
  1314.         }
  1315.     pScsiCtrl->msgInState   = state;
  1316.     pScsiCtrl->msgInLength += xferCount;
  1317.     
  1318.     return (OK);
  1319.     }
  1320. /*******************************************************************************
  1321. *
  1322. * scsiCtrlThreadComplete - complete execution of a client thread
  1323. *
  1324. * Set the thread status and errno appropriately, depending on whether or
  1325. * not the thread has been aborted.  Set the thread inactive, and notify
  1326. * the SCSI manager of the completion.
  1327. *
  1328. * RETURNS: N/A
  1329. */
  1330. LOCAL void scsiCtrlThreadComplete
  1331.     (
  1332.     SCSI_THREAD * pThread
  1333.     )
  1334.     {
  1335.     SCSI_DEBUG_MSG ("scsiCtrlThreadComplete: thread 0x%08x completedn",
  1336.     (int) pThread, 0, 0, 0, 0, 0);
  1337.     if (pThread->state == SCSI_THREAD_WAIT_ABORT)
  1338. {
  1339. pThread->status = ERROR;
  1340. pThread->errNum = S_scsiLib_ABORTED;
  1341. }
  1342.     else
  1343. {
  1344.      pThread->status = OK;
  1345.      pThread->errNum = 0;
  1346.      }
  1347.     
  1348.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1349.     scsiCacheSynchronize (pThread, SCSI_CACHE_POST_COMMAND);
  1350.     scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_COMPLETED);
  1351.     }
  1352. /*******************************************************************************
  1353. *
  1354. * scsiCtrlThreadDefer - defer execution of a thread
  1355. *
  1356. * Set the thread's state to INACTIVE and notify the SCSI manager of the
  1357. * deferral event.
  1358. *
  1359. * RETURNS: N/A
  1360. */
  1361. LOCAL void scsiCtrlThreadDefer
  1362.     (
  1363.     SCSI_THREAD * pThread
  1364.     )
  1365.     {
  1366.     SCSI_DEBUG_MSG ("scsiCtrlThreadDefer: thread 0x%08x deferredn",
  1367.     (int) pThread, 0, 0, 0, 0, 0);
  1368.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1369.     scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_DEFERRED);
  1370.     }
  1371.     
  1372. /*******************************************************************************
  1373. *
  1374. * scsiCtrlThreadFail - complete execution of a thread, with error status
  1375. *
  1376. * Set the thread's status and errno according to the type of error.  Set
  1377. * the thread's state to INACTIVE, and notify the SCSI manager of the
  1378. * completion event.
  1379. *
  1380. * RETURNS: N/A
  1381. */
  1382. LOCAL void scsiCtrlThreadFail
  1383.     (
  1384.     SCSI_THREAD * pThread,
  1385.     int           errNum
  1386.     )
  1387.     {
  1388.     SCSI_DEBUG_MSG ("scsiCtrlThreadFail: thread 0x%08x failed (errno = %d)n",
  1389.     (int) pThread, errNum, 0, 0, 0, 0);
  1390.     pThread->status = ERROR;
  1391.     if (pThread->state == SCSI_THREAD_WAIT_ABORT)
  1392. pThread->errNum = S_scsiLib_ABORTED;
  1393.     else
  1394.      pThread->errNum = errNum;
  1395.     
  1396.     scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1397.     scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_COMPLETED);
  1398.     }
  1399.     
  1400. /*******************************************************************************
  1401. *
  1402. * scsiCtrlThreadStateSet - set the state of a thread
  1403. *
  1404. * This is really just a place-holder for debugging and possible future
  1405. * enhancements such as state-change logging.
  1406. *
  1407. * RETURNS: N/A
  1408. */
  1409. LOCAL void scsiCtrlThreadStateSet
  1410.     (
  1411.     SCSI_THREAD *     pThread, /* ptr to thread info */
  1412.     SCSI_THREAD_STATE state
  1413.     )
  1414.     {
  1415.     SCSI_DEBUG_MSG ("scsiCtrlThreadStateSet: thread 0x%08x: %d -> %dn",
  1416.     (int) pThread, pThread->state, state, 0, 0, 0);
  1417.     pThread->state = state;
  1418.     }
  1419. /*******************************************************************************
  1420. *
  1421. * scsiCtrlXferParamsSet - set transfer parameters for a thread
  1422. *
  1423. * Call the controller-specific routine to set transfer parameters to the
  1424. * values required by this thread's target device.
  1425. *
  1426. * RETURNS: OK, or ERROR if transfer parameters cannot be set
  1427. */
  1428. LOCAL STATUS scsiCtrlXferParamsSet
  1429.     (
  1430.     SCSI_THREAD * pThread
  1431.     )
  1432.     {
  1433.     SCSI_TARGET * pScsiTarget = pThread->pScsiTarget;
  1434.     SCSI_CTRL *   pScsiCtrl   = pThread->pScsiCtrl;
  1435.     
  1436.     /*
  1437.      * Set transfer parameters for thread's target device
  1438.      */
  1439.     if ((*pScsiCtrl->scsiXferParamsSet) (pScsiCtrl,
  1440.  pScsiTarget->xferOffset,
  1441.  pScsiTarget->xferPeriod) != OK)
  1442. {
  1443. SCSI_ERROR_MSG ("scsiCtrlXferParamsSet: can't set transfer parameters.n",
  1444. 0, 0, 0, 0, 0, 0);
  1445. return (ERROR);
  1446. }
  1447.     return (OK);
  1448.     }
  1449. /*******************************************************************************
  1450. *
  1451. * scsiCtrlMsgInAck - acknowledge an incoming message byte
  1452. *
  1453. * Call the controller-specific routine to negate the SCSI ACK signal, and
  1454. * assert the ATN signal if there is a pending message out.  Note that the
  1455. * controller driver must ensure that ATN is asserted, if necessary, before
  1456. * ACK is negated.
  1457. *
  1458. * RETURNS: OK, or ERROR if the signals could not be driven as required
  1459. */
  1460. LOCAL STATUS scsiCtrlMsgInAck
  1461.     (
  1462.     SCSI_CTRL * pScsiCtrl
  1463.     )
  1464.     {
  1465.     UINT busCommand = SCSI_BUS_NEGATE_ACK;
  1466.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)
  1467. {
  1468. busCommand |= SCSI_BUS_ASSERT_ATN;
  1469. }
  1470.     
  1471.     if ((*pScsiCtrl->scsiBusControl) (pScsiCtrl, busCommand) != OK)
  1472. {
  1473. SCSI_ERROR_MSG ("scsiCtrlMsgInAck: scsiBusControl failed.n",
  1474. 0, 0, 0, 0, 0, 0);
  1475. return (ERROR);
  1476. }
  1477.     return (OK);
  1478.     }