sym895Lib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:160k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if ISTAT:ABRT bit is set, reset before reading the DMA status reg */
  2. if (intrStatus & SYM895_ISTAT_ABRT)
  3.       SYM895_REG8_WRITE(pSiop, SYM895_OFF_ISTAT, 0x00);
  4.         if ((intrStatus & SYM895_ISTAT_SIP) && (intrStatus & SYM895_ISTAT_DIP))
  5.             SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet:  
  6.                    Both DMA and SCSI Interrupts n", 0, 0, 0, 0, 0, 0);
  7.         /* 
  8.          * Read the interrupt status registers if that type of 
  9.          * interrupt occurs 
  10.          */
  11.         
  12.         CACHE_PIPE_FLUSH();  
  13. if (intrStatus & SYM895_ISTAT_DIP)
  14.       {
  15.             dmaStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);
  16.             sym895Delay ();
  17.             }
  18.      
  19.         CACHE_PIPE_FLUSH();
  20.         if (intrStatus & SYM895_ISTAT_SIP)
  21.             {
  22.             scsiStatus_0 = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0);
  23.             sym895Delay ();
  24.             scsiStatus_1 = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1);
  25.             }
  26.       intUnlock (key);
  27. }
  28.     else
  29. {
  30. intUnlock (key);
  31. return (ERROR);
  32. }
  33.     SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet: ISTAT : 0x%02x SIST0 : 0x%02x 
  34.               SIST1 : 0x%02x DSTAT : 0x%02x nn", intrStatus, scsiStatus_0,
  35.               scsiStatus_1,dmaStatus,0,0);
  36.     /* Now start checking for the source of interrupts */
  37.     /* Fatal conditions first !! */
  38.     if (scsiStatus_0 & SYM895_B_SGE)
  39. {
  40. SCSI_MSG ("sym895EventTypeGet: SCSI Gross Errorn ", 0, 0, 0, 0, 0, 0);
  41. return (SYM895_FATAL_ERROR);
  42. }
  43.     if (scsiStatus_0 & SYM895_B_PAR)
  44. {
  45. SCSI_MSG ("sym895EventTypeGet: SCSI Parity Errorn", 0, 0, 0, 0, 0, 0);
  46. return (SYM895_FATAL_ERROR);
  47. }
  48.     if (dmaStatus & SYM895_B_IID)
  49. {
  50. SCSI_MSG ("sym895EventTypeGet : IIlegal Instruction detectedn ",
  51.    SYM895_REG32_READ (pSiop,SYM895_OFF_DSP), 0, 0, 0, 0, 0);
  52. return (SYM895_FATAL_ERROR);
  53. }
  54.     if (dmaStatus & SYM895_B_BF)
  55. {
  56. SCSI_MSG ("sym895EventTypeGet : SCSI Bus Faultn",
  57. SYM895_REG32_READ (pSiop,SYM895_OFF_DSP),
  58. SYM895_REG32_READ (pSiop,SYM895_OFF_DBC) & 0xffffff, 0, 0, 0, 0);
  59. return (SYM895_FATAL_ERROR);
  60. }
  61.     /* Now, non-fatal error checking: The order of checking can be important */
  62.     if (scsiStatus_0 & SYM895_B_RST)
  63. {
  64. SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : BusReset n", 
  65.                                0, 0, 0, 0, 0, 0);
  66. /* Clear DMA FIFO */
  67. SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
  68.            SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) | 
  69.                            SYM895_CTEST3_CLF);
  70. return (SYM895_SCSI_BUS_RESET);
  71. }
  72.     if (scsiStatus_0 & SYM895_B_UDC)
  73. {
  74.         SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Unexpected Disconnection n",
  75.                   0, 0, 0, 0, 0, 0);
  76.         /* Clear DMA FIFO */
  77. SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
  78.                    SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) | 
  79.                            SYM895_CTEST3_CLF);
  80.         return (SYM895_UNEXPECTED_DISCON);
  81.         }
  82.     if (scsiStatus_1 & SYM895_B_STO)
  83. {
  84. SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Bus Timeout n", 
  85.                                0, 0, 0, 0, 0, 0);
  86. /* Clear DMA FIFO */
  87. SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
  88.                    SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) | 
  89.                            SYM895_CTEST3_CLF);
  90.         return (SYM895_SCSI_TIMEOUT);
  91.         }
  92.     if (scsiStatus_1 &SYM895_B_HTH)
  93.         {
  94.         SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Bus handshake Timeout n",
  95.                   0, 0, 0, 0, 0, 0);
  96. /* Clear DMA FIFO */
  97. SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
  98.    SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) | 
  99.                            SYM895_CTEST3_CLF);
  100.         return (SYM895_HANDSHAKE_TIMEOUT);
  101.         }
  102.     if (scsiStatus_1 & SYM895_B_SBMC)
  103.         {
  104. SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Bus Mode Change Detected n",
  105.                   0, 0, 0, 0, 0, 0);
  106.         return (SYM895_BUSMODE_CHANGED);
  107. }
  108.     if (scsiStatus_1 & SYM895_B_GEN)
  109. {
  110. SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : General Timer Expired n",
  111.                   0, 0, 0, 0, 0, 0);
  112. return (SYM895_GEN_TIMER_EXPIRED);
  113. }
  114.     if (scsiStatus_0 & SYM895_B_MA)
  115. {
  116. /* 
  117.          * This is a Phase Misatch interrupt when in Initiator mode and 
  118.  * signals arrertion of ATN in Target Mode.
  119.  */
  120. /* 
  121.          * if in Target mode..Fatal error as this intr is supposed to be 
  122.  * disabled earlier. 
  123.  */
  124. if (SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL0) & SYM895_SCNTL0_TRG)
  125.             {
  126.             SCSI_MSG (" sym895EventTypeGet : ATN intr. in target mode n",
  127.                       0, 0, 0, 0, 0, 0);
  128.             return (SYM895_FATAL_ERROR);
  129.             }
  130. else
  131.     {
  132.     /* Initiator mode */
  133.             SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Phase Mismatch n",
  134.                       0, 0, 0, 0, 0, 0);
  135.             return (SYM895_PHASE_MISMATCH);
  136.             }
  137. }
  138.     if (dmaStatus & SYM895_B_ABT)
  139. {
  140. SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Script Aborted n",
  141.                   0, 0, 0, 0, 0, 0);
  142. return (SYM895_SCRIPT_ABORTED);
  143. }
  144.     if (dmaStatus & SYM895_B_SIR)
  145. {
  146. SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Script Interrupt n",
  147.                   0, 0, 0, 0, 0, 0);
  148. /* return the stored interrupt vector */
  149. return SYM895_REG32_READ (pSiop,SYM895_OFF_DSPS);
  150. }
  151.     if (dmaStatus & SYM895_B_SSI)
  152. {
  153. SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Single Step Interrupt n",
  154.                   0, 0, 0, 0, 0, 0);
  155. return (SYM895_SINGLE_STEP);
  156. }
  157.     /* No reason for the interrupt ! */
  158.     SCSI_MSG (" sym895EventTypeGet : Spurious Interrupt n",
  159.               0, 0, 0, 0, 0, 0);
  160.     
  161.     return (SYM895_FATAL_ERROR);
  162.     }
  163. /******************************************************************************
  164. *
  165. * sym895ThreadEvent - SCSI Controller thread event processing routine
  166. *
  167. * Forward the event to the proper handler for the thread's current role.
  168. *
  169. * If the thread is still active, update the thread context (including
  170. * shared memory area) and resume the thread.
  171. *
  172. * RETURNS N/A
  173. */
  174. LOCAL void sym895ThreadEvent
  175.     (
  176.     SYM895_THREAD * pThread,
  177.     SYM895_EVENT *  pEvent
  178.     )
  179.     {
  180.     SCSI_EVENT *  pScsiEvent  = &pEvent->scsiEvent;
  181.     SCSI_THREAD * pScsiThread = &pThread->scsiThread;
  182.     SIOP *        pSiop       = (SIOP *) pScsiThread->pScsiCtrl;
  183.     SYM895_SCRIPT_ENTRY entryPt;
  184.     
  185.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadEvent thread 0x%08x received event %dn",
  186.               (int) pThread, pScsiEvent->type, 0, 0, 0, 0);
  187.     switch (pScsiThread->role)
  188. {
  189. case SCSI_ROLE_INITIATOR:
  190.          
  191.             sym895InitEvent (pThread, pEvent);
  192.     entryPt = SYM895_SCRIPT_INIT_CONTINUE;
  193.             break;
  194.     
  195. case SCSI_ROLE_IDENT_INIT:
  196.             sym895InitIdentEvent (pThread, pEvent);
  197.     entryPt = SYM895_SCRIPT_INIT_CONTINUE;
  198.     break;
  199.  
  200.         case SCSI_ROLE_IDENT_TARG:
  201.     sym895TargIdentEvent (pThread, pEvent);
  202.     entryPt = SYM895_SCRIPT_TGT_DISCONNECT;
  203.     break;
  204. case SCSI_ROLE_TARGET:
  205. default:
  206.             SCSI_MSG ("sym895ThreadEvent thread 0x%08x invalid role (%d)n",
  207.                       (int) pThread, pScsiThread->role, 0, 0, 0, 0);
  208.             entryPt = SYM895_SCRIPT_TGT_DISCONNECT;
  209.             break;
  210. }
  211.     /* Resume thread if it is still connected */
  212.     switch (pScsiThread->state)
  213. {
  214. case SCSI_THREAD_INACTIVE :
  215. case SCSI_THREAD_WAITING :
  216. case SCSI_THREAD_DISCONNECTED :
  217.     break;
  218. default:
  219.          sym895ThreadUpdate (pThread);
  220.     if (sym895Resume (pSiop, pThread, entryPt) != OK)
  221.      {
  222.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadEvent failed to 
  223.                                        resume threadn",
  224.                     0, 0, 0, 0, 0, 0);
  225. sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  226.      }
  227.     break;
  228. }
  229.     }
  230. /******************************************************************************
  231. *
  232. * sym895InitEvent - device initiator thread event processing routine
  233. *
  234. * Parse the event type and handle it accordingly.  This may result in state
  235. * changes for the thread, state variables being updated, etc.
  236. *
  237. * RETURNS N/A
  238. */
  239. LOCAL void sym895InitEvent
  240.     (
  241.     SYM895_THREAD * pThread,
  242.     SYM895_EVENT  *  pEvent
  243.     )
  244.     {
  245.     SCSI_EVENT *  pScsiEvent  = &pEvent->scsiEvent;
  246.     SCSI_THREAD * pScsiThread = &pThread->scsiThread;
  247.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  248.     /* Update controller msg in/out state after script completes */
  249.     pScsiCtrl->msgOutState = pThread->msgOutStatus;
  250.     pScsiCtrl->msgInState  = pThread->msgInStatus;
  251.     
  252.     /* Parse script exit status; handle as necessary */
  253.     switch (pScsiEvent->type)
  254. {
  255. case SYM895_DISCONNECTED:
  256.       SYM895_SCSI_DEBUG_MSG ("DISCONNECT message inn", 0, 0, 0, 0, 0, 0);
  257.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DISCONNECTED);
  258.     sym895ThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED);
  259.     break;
  260. case SYM895_CMD_COMPLETE:
  261.     SYM895_SCSI_DEBUG_MSG ("COMMAND COMPLETE message inn", 
  262.                                    0, 0, 0, 0, 0, 0);
  263.     sym895ThreadComplete (pThread);
  264.     break;
  265. case SYM895_SELECTED:
  266. case SYM895_RESELECTED:
  267.     
  268.     SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x 
  269.                            (re)selection.n", (int) pThread, 0, 0, 0, 0, 0);
  270.       sym895ThreadDefer (pThread);
  271.          break;
  272.      case SYM895_MESSAGE_OUT_SENT:
  273.     (void) scsiMsgOutComplete (pScsiCtrl, pScsiThread);
  274.     break;
  275.     
  276. case SYM895_MESSAGE_IN_RECVD:
  277.     (void) scsiMsgInComplete (pScsiCtrl, pScsiThread);
  278.     break;
  279.    
  280. case SYM895_NO_MSG_OUT:
  281.     /*
  282.      * The target has requested a message out when there is none
  283.        * pending.  Set up a NO-OP message to be sent when thread is
  284.         *  resumed.
  285.              *
  286.              * The script could handle this on its own, but arguably the
  287.              * host should be involved as it may represent an error.
  288.              */
  289.     pScsiCtrl->msgOutBuf[0] = SCSI_MSG_NO_OP;
  290.     pScsiCtrl->msgOutLength = 1;
  291.       pScsiCtrl->msgOutState  = SCSI_MSG_OUT_NONE;    /* sic */
  292.        break;
  293.     
  294. case SYM895_EXT_MESSAGE_SIZE:
  295.             /*
  296.            *  The SIOP has just read the length byte for an extended
  297.              *  message in.  The shared memory area is updated with the
  298.              * appropriate length just before the thread is resumed (see
  299.              * "sym895ThreadUpdate()".
  300.              */
  301.              break;
  302.     
  303. case SYM895_PHASE_MISMATCH:
  304.             if (sym895PhaseMismatch (pThread, pThread->busPhase,
  305.      pEvent->remCount) != OK)
  306. {
  307. sym895ThreadFail (pThread, errno);
  308. }  
  309.      break;
  310. case SYM895_SCSI_TIMEOUT:
  311.     SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x 
  312.                        select timeout.n", (int) pThread, 0, 0, 0, 0, 0);
  313.       sym895ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
  314.        break;
  315.         /* 
  316.          * There is no error no. equivalent to this timeout. 
  317.          * So S_scsiLib_SELECT_TIMEOUT is used.
  318.          */
  319. case SYM895_HANDSHAKE_TIMEOUT:
  320.    
  321.             SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x  
  322.                       Bus Handshake timeout.n", (int) pThread, 0, 0, 0, 0, 0);
  323.       sym895ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
  324.        break;
  325. case SYM895_SCRIPT_ABORTED:
  326.     SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x abortedn",
  327.     (int) pThread, 0, 0, 0, 0, 0);
  328.     break;
  329. case SYM895_NO_IDENTIFY:
  330.    
  331.             SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x  
  332.                       No Identify message.n", (int) pThread, 0, 0, 0, 0, 0);
  333.             /* 
  334.              * There should be an ErrorNumber for this event. Scsi2Lib.h
  335.              * does'nt define any number for this. So use this for the moment.
  336.              */
  337.       sym895ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
  338.        break;
  339.     
  340. case SCSI_EVENT_BUS_RESET:
  341.          SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x bus resetn",
  342.          (int) pThread, 0, 0, 0, 0, 0);
  343.          /* Do not try to resume this thread.  SCSI mgr will tidy up. */
  344.             sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  345.             break;
  346. case SYM895_UNEXPECTED_DISCON:
  347.     /* not really unexpected after an abort message ... */
  348.          SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x 
  349.                                    unexpected disconnectionn",
  350.                                    (int) pThread, 0, 0, 0, 0, 0);
  351.             sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  352.             break;
  353.     
  354. case SYM895_ILLEGAL_PHASE:
  355.             SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x illegal phase 
  356.                             requested.n", (int) pThread, 0, 0, 0, 0, 0);
  357.             sym895ThreadFail (pThread, S_scsiLib_INVALID_PHASE);
  358.     break;
  359. default:
  360.     SCSI_MSG ("sym895InitEvent invalid event type (%d)n",
  361.       pScsiEvent->type, 0, 0, 0, 0, 0);
  362.    break;
  363. }
  364.     }
  365. /******************************************************************************
  366. *
  367. * sym895Activate - activate a script corresponding to a new thread
  368. *
  369. * Request activation of (the script for) a new thread, if possible; do not
  370. * wait for the script to complete (or even start) executing.  Activation
  371. * is requested by signalling the controller, which causes an interrupt.
  372. * The script is started by the ISR in response to this event.
  373. *
  374. * There is a race condition inherent in SCSI between the synchronous
  375. * activation of a thread (i.e., execution of this routine) and asynchronous
  376. * activation of a thread as a result of selection or reselection.  The SCSI
  377. * manager is designed to take account of this, and assumes that either the
  378. * new thread has been successfully activated or a (re)selection has taken
  379. * place, as determined by the next event it receives.  In the case when
  380. * (re)selection occurs, the current activation request is deferred and
  381. * retried later.
  382. *
  383. * Therefore, an activation request is lodged only if the controller is
  384. * currently PASSIVE (waiting for (re)selection or a host command).  If the
  385. * controller is IDLE, (re)selection is assumed to have already occurred.
  386. * Note that this is not an error condition; there is no way for the
  387. * caller to distinguish the two cases, because even if the thread appears
  388. * to have been activated it may yet be "pre-empted" by (re)selection.
  389. *
  390. * The controller should never be ACTIVE.  If it is, the SCSI manager has
  391. * tried to activate multiple concurrent threads on the controller, which
  392. * indicates a major (software) disaster.
  393. *
  394. * NOTE Interrupt locking is required to ensure that the correct action
  395. * is taken once the controller state has been checked.
  396. *
  397. * RETURNS OK, or ERROR if the controller is in an invalid state (this
  398. * indicates a major software failure).
  399. */
  400. LOCAL STATUS sym895Activate
  401.     (
  402.     SIOP *          pSiop,     /* pointer to SIOP structure   */
  403.     SYM895_THREAD * pThread    /* pointer to thread structure */
  404.     )
  405.     {
  406.     STATUS status = OK;
  407.     int key;
  408.     if (pSiop->isCmdPending)
  409.         {
  410. SCSI_MSG ("sym895Activate: activation request already pending !n",
  411.                   0, 0, 0, 0, 0, 0);
  412.      return (ERROR);
  413.      }
  414.     /* 
  415.      * Check Controller state, set a new command pending and signal it 
  416.      * if necessary.
  417.      */
  418.     key = intLock ();
  419.     /* 
  420.      * If the SIOP is connected and it is in the passive state, means that an 
  421.      * asynchronous bus event like a select or reselect just occurred. This 
  422.      * event has priority over this thread, therefore change the state of
  423.      * the controller to ACTIVE.
  424.      */
  425.     if ((pSiop->state == SYM895_STATE_PASSIVE) && 
  426. (SYM895_REG8_READ (pSiop,SYM895_OFF_ISTAT) & SYM895_ISTAT_CON))
  427.         pSiop->state = SYM895_STATE_IDLE;
  428.     switch (pSiop->state)
  429. {
  430. case SYM895_STATE_IDLE:
  431.             status = OK;
  432.        break;
  433. case SYM895_STATE_PASSIVE:  /* do nothing */
  434.     pSiop->pNewThread = pThread;
  435.     pSiop->isCmdPending = TRUE;
  436.             /* 
  437.            * Signal the wait for (re) select script which then jumps to
  438.      * the relative alternate address. 
  439.      */
  440.          SYM895_REG8_WRITE (pSiop, SYM895_OFF_ISTAT, 
  441.                               (SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) | 
  442.                                SYM895_ISTAT_SIGP));
  443.             status = OK;
  444.             break;
  445.     
  446.   case SYM895_STATE_ACTIVE:
  447. default:
  448.     status = ERROR;
  449.     break;
  450. }
  451.     intUnlock (key);
  452.     if (status != OK)
  453. {
  454.      SCSI_MSG ("sym895Activate: invalid controller state. n",
  455.                  pSiop->state, 0, 0, 0, 0, 0);
  456.      errnoSet (S_scsiLib_SOFTWARE_ERROR);
  457.      }
  458.     return (status);
  459.     }
  460. /******************************************************************************
  461. *
  462. * sym895Abort - abort the active script corresponding to the current thread
  463. *
  464. * Check that there is currently an active script running.  If so, set the
  465. * SCSI Controller Abort flag which will halt the script and cause an interrupt.
  466. *
  467. * RETURNS N/A
  468. */
  469. LOCAL void sym895Abort
  470.     (
  471.     SIOP * pSiop /* pointer to controller structure */
  472.     )
  473.     {
  474.     int    key;
  475.     STATUS status;
  476.     key = intLock ();
  477.     switch (pSiop->state)
  478.       {
  479.       case SYM895_STATE_IDLE:
  480.       case SYM895_STATE_PASSIVE:
  481.            status = OK;
  482.            break;
  483.   
  484.       case SYM895_STATE_ACTIVE:
  485.            SYM895_REG8_WRITE(pSiop, SYM895_OFF_ISTAT, 
  486.                              (SYM895_REG8_READ (pSiop,SYM895_OFF_ISTAT) | 
  487.                              SYM895_ISTAT_ABRT));
  488.            status = OK;
  489.            break;
  490.       default:
  491.            status = ERROR;
  492.            break;
  493.       }
  494.       
  495.     intUnlock (key);
  496.     if (status != OK)
  497.       {
  498.       SCSI_MSG("sym895Abort: thread = 0x%0xx: invalid state (%d) n",
  499.        pSiop->state, 0, 0, 0, 0, 0);
  500.       }
  501.     }
  502. /******************************************************************************
  503. *
  504. * sym895ScriptStart - start the SCSI Controller executing a script
  505. *
  506. * Restore the SCSI Controller register context, including the shared memory
  507. * area, from the thread context.  Put the address of the script entry point
  508. * into the DSP register.  If not in single-step mode, start the script.
  509. *
  510. * RETURNS N/A
  511. */
  512. LOCAL void sym895ScriptStart
  513.     (
  514.     SIOP *             pSiop, /* pointer to  SCSI Controller info */
  515.     SYM895_THREAD * pThread, /* SM895 thread info */
  516.     SYM895_SCRIPT_ENTRY entryId /* routine address entry point */
  517.     )
  518.     {
  519.     int key;
  520.     BOOL isManualMode;
  521.     SYM895_SCSI_DEBUG_MSG ("sym895ScriptStart: %x    %d n",
  522.               (UINT32)pThread, (UINT32)entryId, 0, 0, 0, 0);
  523.     key = intLock ();
  524.     /* Set the Current Thread Pointer */
  525.     pSiop->pCurThread = pThread;
  526.     /* Restore the SCSI Controller  register context for this thread. */
  527.     
  528.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA0, pThread->nHostFlags);
  529.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA1, pThread->msgOutStatus);
  530.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA2, pThread->msgInStatus);
  531.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA3, pThread->targetId); 
  532.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA3, pThread->busPhase); 
  533.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SXFER, pThread->sxfer);
  534.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL3, pThread->scntl3);   
  535.     /* 
  536.      * Scatter Gather operations have to be initiated by Scsi Manager task.
  537.      * As of now, this feature is only implemented, but not tested. The 
  538.      * SCSI Scripts include BlockMOVE instructions to perform these operations.
  539.      */           
  540.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHC0, pThread->isScatTransfer);
  541.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHC1, pThread->totalScatElements);
  542.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHC2, pThread->noRemaining);
  543.     
  544.     /*
  545.      * Set the shared data address, load the script start address,
  546.      * then start the SCSI Controller unless it's in single-step mode.
  547.      */
  548.     SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSA, 
  549.        (UINT32)SYM895_VIRT_TO_PHYS (pThread->pShMem));
  550.     /* 
  551.      * check if the SCRIPT DMA fetch is manual. If manual, scripts will not 
  552.      * start until DMA start bit in DCNTL register is set
  553.      */
  554.     isManualMode = ((SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) & 
  555.                      SYM895_DMODE_MAN) == SYM895_DMODE_MAN) ? TRUE : FALSE;
  556.  
  557.     SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSP, 
  558.         (UINT32)SYM895_VIRT_TO_PHYS (
  559.                         (UINT32)sym895ScriptEntry [entryId]));
  560.     /* 
  561.      * Check if Single stepping is enabled. Otherwise issue the START SCRIPTS
  562.      * command by writing the DMA start bit in DCNTL register.
  563.      */
  564.     if (pSiop->isSingleStep)
  565. {
  566. SCSI_MSG ("sym895ScriptStart: Single Step required to start script.n",
  567.  0, 0, 0, 0, 0, 0);
  568. }
  569.     else
  570. {
  571.         CACHE_PIPE_FLUSH(); 
  572.          
  573. if (isManualMode)
  574.     {
  575.     /* Write the DMA Start bit */
  576.             SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  577.        SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) | 
  578.                                SYM895_DCNTL_STD);
  579.             /*
  580.              * vxEieio() is a PPC family specific routine that makes sure that
  581.              * the SCSI registers written above are executed in order and 
  582.              * completely before continuing on. In the case of the faster PPC 
  583.              * processors, it has been found that without this flushing of the 
  584.              * pipes the processor is much faster than the SIOP, and causes 
  585.              * erratic behaviour like bus errors and invalid events.
  586.              */
  587.             CACHE_PIPE_FLUSH();
  588.             sym895Delay (); /* XXX - needs to be tuned better for fast PPCs */
  589.     CACHE_PIPE_FLUSH();
  590.             }
  591. }
  592.     intUnlock (key);
  593.     CACHE_PIPE_FLUSH();
  594.     }
  595. /*******************************************************************************
  596. *
  597. * sym895ThreadUpdate - update the thread structure for a current SCSI command
  598. *
  599. * Update the dynamic data (e.g. data pointers, transfer parameters) in
  600. * the thread to reflect the latest state of the corresponding physical device.
  601. *
  602. * RETURNS N/A
  603. *
  604. * NOMANUAL
  605. */
  606. LOCAL void sym895ThreadUpdate
  607.     (
  608.     SYM895_THREAD * pThread /* pointer thread structure */
  609.     )
  610.     {
  611.     SCSI_THREAD *   pScsiThread = &pThread->scsiThread;
  612.     SCSI_CTRL   *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  613.     SYM895_SHARED * pShMem      = pThread->pShMem; 
  614.     UINT            msgOutSize;
  615.     UINT            msgInSize;
  616.     UINT            flags = 0;
  617.     SIOP  *         pSiop       = (SIOP *) pScsiCtrl;
  618. #ifdef SCATTER_GATHER
  619.     UINT count;
  620. #endif
  621.     /*
  622.      *  If there is an identification message, ensure ATN is asserted
  623.      * during (re)selection.
  624.      */
  625.      if (pScsiThread->identMsgLength != 0)
  626.          flags |= SYM895_FLAGS_IDENTIFY;
  627.     /* update SIOP register context */
  628.      pThread->nHostFlags = flags;
  629.      pThread->msgOutStatus = pScsiCtrl->msgOutState;
  630.      pThread->msgInStatus  = pScsiCtrl->msgInState;
  631.     /* Update dynamic message in/out sizes */
  632.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_NONE)
  633. msgOutSize = 0;
  634.     else
  635. msgOutSize = pScsiCtrl->msgOutLength;
  636.     if (pScsiCtrl->msgInState != SCSI_MSG_IN_EXT_MSG_DATA)
  637. msgInSize = 0;
  638.     
  639.     else if ((msgInSize = pScsiCtrl->msgInBuf [SCSI_EXT_MSG_LENGTH_BYTE]) == 0)
  640. msgInSize = SCSI_EXT_MSG_MAX_LENGTH;
  641.     /* Update commands in shared memory area */
  642.     pShMem->command.size = SYM895_SWAP_32 (pScsiThread->cmdLength);
  643.     pShMem->command.addr = (UINT8 *) SYM895_SWAP_32 
  644.                                      (
  645.                                        (UINT32) SYM895_VIRT_TO_PHYS
  646.                                        ((UINT) pScsiThread->cmdAddress)
  647.                                      );
  648. #ifdef SCATTER_GATHER /*  scatter gather memory support */
  649.     
  650.     /* 
  651.      * For Scatter-Gather moves across SCSI Bus, a series of addresses and
  652.      * byte counts from these addresses are needed. Addresses indicate from
  653.      * where all in memory, data is to be transferred. Byte counts indicate
  654.      * the amount of data to be transferred from individual addresses. These 
  655.      * addresses and byte counts are assumed to be residing in contiguous 
  656.      * memory. We assume support from SCSI Manager, to provide with the above
  657.      * addresses & counts.Also, the structure elements "activeDataElements" is
  658.      * assumed to be part of SCSI_THREAD structure (which is not as of now).
  659.      */
  660.     /* 
  661.      * "activeDataElements" is assumed to be in SCSI_THREAD and is supposed 
  662.      * to hold the number of scattered locations from where the data is to 
  663.      * be transferred. Its responsibilty of SCSI Manager to initialise this 
  664.      * once this is part of SCSI_THREAD.
  665.      */
  666.      pShMem->scatData.noElems = pScsiThread->activeDataElements;  
  667.     /* 
  668.      * Now initialise the pointers from where data is to transferred.
  669.      * These are set of addresses, which are assumed to contain the 
  670.      * data locations. They do not exist now. Compiling this will
  671.      * result in error. 
  672.      */
  673.     for (count = 0; count < pShMem->scatData.noElems; count++ )
  674.         {
  675.         pShMem->scatData.Elements[count].size=
  676.                          (UINT8 *) SYM895_SWAP_32 
  677.                          (
  678.                          (UINT32) SYM895_VIRT_TO_PHYS
  679.                          ((UINT)  pScsiThread->activeDataLength[count])
  680.                          );
  681.         pShMem->scatData.Elements[count].addr=
  682.                          (UINT8 *) SYM895_SWAP_32 
  683.                          (
  684.                          (UINT32) SYM895_VIRT_TO_PHYS
  685.                          ((UINT)  pScsiThread->activeDataAddress[count])
  686.                          );
  687.         }
  688.     /* 
  689.      * The way this feature was tested with out any support from SCSI lib...
  690.      * For any data transfer across scsi BUS, the current thread structure
  691.      * contains a pointer and count of the data to be transferred. To emulate
  692.      * scattered operation, the data is split in to 2 parts. Now the byte
  693.      * count will be half of the number as passed by library. The pointers to
  694.      * the data can be obtained by adding the byte count to the pointer 
  695.      * initially passed. In SCRIPTS assembly. when it comes to the DATA OUT
  696.      * phase, check whether scattered data transfer is requested or not 
  697.      * by checking the value passed in SCRATCHC0. If yes, the SCRIPTS will 
  698.      * transfer data from various locations (though contiguous but not 
  699.      * scattered).
  700.      */  
  701. #if 0
  702.     pShMem->scatData.noElems = 2;
  703.     pShMem->scatData.Elements[0].size = (SYM895_SWAP_32 
  704.                                         (pScsiThread->activeDataLength))/2;
  705.     pShMem->scatData.Elements[0].addr = (UINT8 *) SYM895_SWAP_32 
  706.                                       (
  707.                                        (UINT32) SYM895_VIRT_TO_PHYS
  708.                                        ((UINT) pScsiThread->activeDataAddress)
  709.                                       );
  710.     pShMem->scatData.Elements[1].size = (SYM895_SWAP_32 
  711.                                        (pScsiThread->activeDataLength))/2;
  712.     pShMem->scatData.Elements[1].addr = (UINT8 *) SYM895_SWAP_32 
  713.                                       (
  714.                                        (UINT32) SYM895_VIRT_TO_PHYS
  715.                                        ((UINT)(pScsiThread->activeDataAddress +
  716.                                         (pScsiThread->activeDataLength)/2))
  717.                                       );
  718. #endif
  719.   
  720.     /* Tell scripts that now it is scattered data to be transferred.. */
  721.     pThread->isScatTransfer = TRUE;
  722.     pThread->totalScatElements = pShMem->scatData.noElems;
  723.     pThread->noRemaining = pShMem->scatData.noElems;
  724.  
  725. #else
  726.     pShMem->dataOut.size    = SYM895_SWAP_32 (pScsiThread->activeDataLength);
  727.     pShMem->dataOut.addr    = (UINT8 *) SYM895_SWAP_32 
  728.                                      (
  729.                                        (UINT32) SYM895_VIRT_TO_PHYS
  730.                                        ((UINT) pScsiThread->activeDataAddress)
  731.                                      );
  732.     pThread->isScatTransfer = FALSE;
  733.     pThread->totalScatElements = 0;
  734.     pThread->noRemaining = 0; 
  735. #endif  /* SCATTER_GATHER */
  736.     pShMem->dataIn.size    = SYM895_SWAP_32 (pScsiThread->activeDataLength);
  737.     pShMem->dataIn.addr    = (UINT8 *) SYM895_SWAP_32 
  738.                                      (
  739.                                        (UINT32) SYM895_VIRT_TO_PHYS
  740.                                        ((UINT) pScsiThread->activeDataAddress)
  741.                                      );
  742.     
  743.     pShMem->status.size  = SYM895_SWAP_32 (pScsiThread->statusLength);
  744.     pShMem->status.addr  = (UINT8 *) SYM895_SWAP_32
  745.                                      (
  746.                                        (UINT32) SYM895_VIRT_TO_PHYS
  747.                                        ((UINT) pScsiThread->statusAddress)
  748.                                      );
  749.    /* 
  750.     * The identOut pointer and buffer are initialised to the buffer allocated
  751.     * in the pSiop structure. These used to be intialised to
  752.     * pScsiThread->identMsg/identMsgLength. To suppport Wide/Sync. transfers
  753.     * the MAX message length is increased. Ideally, this should have been taken
  754.     * in Scsi2Lib.h where the MAX Message length is defined. 
  755.     */
  756.     pShMem->identOut.size = SYM895_SWAP_32 (pSiop->identMsgLength);
  757.     pShMem->identOut.addr = (UINT8 *) SYM895_SWAP_32
  758.                                       (
  759.                                         (UINT32) SYM895_VIRT_TO_PHYS
  760.                                         ((UINT) pSiop->identMsg)
  761.                                       );
  762.     pShMem->msgOut.size    =  SYM895_SWAP_32 (msgOutSize);
  763.     pShMem->msgInRest.size =  SYM895_SWAP_32 (msgInSize);
  764.                                                    
  765.     }
  766. /******************************************************************************
  767. *
  768. * sym895ThreadComplete - successfully complete execution of a client thread
  769. *
  770. * Set the thread status and errno appropriately, depending on whether or
  771. * not the thread has been aborted.  Set the thread inactive, and notify
  772. * the SCSI manager of the completion.
  773. *
  774. * RETURNS N/A
  775. */
  776. LOCAL void sym895ThreadComplete
  777.     (
  778.     SYM895_THREAD * pThread
  779.     )
  780.     {
  781.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  782.     
  783.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadComplete thread 0x%08x completedn",
  784.     (int) pThread, 0, 0, 0, 0, 0);
  785.     if (pScsiThread->state == SCSI_THREAD_ABORTING)
  786. {
  787. pScsiThread->status = ERROR;
  788. pScsiThread->errNum = S_scsiLib_ABORTED;
  789. }
  790.     else
  791. {
  792.      pScsiThread->status = OK;
  793.      pScsiThread->errNum = 0;
  794.      }
  795.     
  796.     sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  797.     scsiCacheSynchronize (pScsiThread, SCSI_CACHE_POST_COMMAND);
  798.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);
  799.     }
  800. /******************************************************************************
  801. *
  802. * sym895ThreadDefer - defer execution of a thread
  803. *
  804. * Set the thread's state to INACTIVE and notify the SCSI manager of the
  805. * deferral event.
  806. *
  807. * This routine is invoked when a re-selection event occurs.
  808. *
  809. * RETURNS N/A
  810. */
  811. LOCAL void sym895ThreadDefer
  812.     (
  813.     SYM895_THREAD * pThread
  814.     )
  815.     {
  816.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  817.     
  818.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadDefer thread 0x%08x deferredn",
  819.     (int) pThread, 0, 0, 0, 0, 0);
  820.     sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  821.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DEFERRED);
  822.     }
  823.     
  824. /******************************************************************************
  825. *
  826. * sym895ThreadFail - complete execution of a thread, with error status
  827. *
  828. * Set the thread's status and errno according to the type of error.  Set
  829. * the thread's state to INACTIVE, and notify the SCSI manager of the
  830. * completion event.
  831. *
  832. * RETURNS N/A
  833. */
  834. LOCAL void sym895ThreadFail
  835.     (
  836.     SYM895_THREAD * pThread,
  837.     int             errNum
  838.     )
  839.     {
  840.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  841.     
  842.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadFail thread 0x%08x failed (errno = %d)n",
  843.     (int) pThread, errNum, 0, 0, 0, 0);
  844.     pScsiThread->status = ERROR;
  845.     if (pScsiThread->state == SCSI_THREAD_ABORTING)
  846. pScsiThread->errNum = S_scsiLib_ABORTED;
  847.     else
  848.      pScsiThread->errNum = errNum;
  849.     
  850.     sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  851.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);
  852.     }
  853.     
  854. /******************************************************************************
  855. *
  856. * sym895ThreadStateSet - set the state of a thread
  857. *
  858. * This is really just a place-holder for debugging and possible future
  859. * enhancements such as state-change logging.
  860. *
  861. * RETURNS N/A
  862. */
  863. LOCAL void sym895ThreadStateSet
  864.     (
  865.     SYM895_THREAD *   pThread, /* pointer to thread structure */
  866.     SCSI_THREAD_STATE state
  867.     )
  868.     {
  869.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  870.     
  871.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadStateSet: thread 0x%08x %d -> %dn",
  872.       (int) pThread, pScsiThread->state, state, 0, 0, 0);
  873.     pScsiThread->state = state;
  874.     }
  875. /******************************************************************************
  876. *
  877. * sym895PhaseMismatch - recover from a SCSI bus phase mismatch
  878. *
  879. * This routine does whatever is required to keep the pointers, counts, etc.
  880. * used by task-level software in step when a SCSI phase mismatch occurs.
  881. *
  882. * The interrupt-level mismatch processing has stored the phase of the
  883. * information transfer before the mismatch, and the number of bytes
  884. * remaining to be transferred.  See "sym895RemainderGet()".
  885. *
  886. * Note that the only phase mismatches supported at this level are
  887. *
  888. * 1) during data in/out phases - presumably because the target has
  889. * transferred as much data as it intends to before sending a message
  890. * in (typically DISCONNECT or COMMAND COMPLETE).  Recovery consists
  891. * of updating the active data pointer/count according to the number
  892. * of data bytes actually transferred before the mismatch.
  893. *
  894. * 2) during a message out phase - presumably because the target does not
  895. * understand our outgoing message and is sending a MESSAGE REJECT
  896. * message, or similar.  No recovery is needed here - it's all done
  897. * when the MESSAGE REJECT message has been received (see routine
  898. * "scsiMsgOutReject()").
  899. *
  900. * 3) during a message in phase - presumably because ATN is asserted
  901. * to abort or reject an incoming message.  No recovery is needed here -
  902. * it's done by the thread management code, which should have enough
  903. * state information to know what to do.
  904. *
  905. * RETURNS OK, or ERROR for an unsupported or invalid phase
  906. *
  907. * NOMANUAL
  908. */
  909. LOCAL STATUS sym895PhaseMismatch
  910.     (
  911.     SYM895_THREAD * pThread, /* pointer to thread structure  */
  912.     int             phase, /* bus phase before mismatch    */
  913.     UINT            remCount /* # bytes not yet transferred  */
  914.     )
  915.     {
  916.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  917.     UINT xferCount;
  918.     
  919.     switch (phase)
  920. {
  921. case SCSI_DATA_IN_PHASE:
  922.             xferCount = SYM895_SWAP_32(pThread->pShMem->dataIn.size) - remCount;
  923.     pScsiThread->activeDataAddress += xferCount;
  924.     pScsiThread->activeDataLength  -= xferCount;
  925.     
  926.     SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch data transfer aborted 
  927.            (%d bytes transferred).n",
  928.            xferCount, 0, 0, 0, 0, 0);
  929.     break;
  930. case SCSI_DATA_OUT_PHASE:
  931.             xferCount = SYM895_SWAP_32(pThread->pShMem->dataOut.size) - remCount;
  932.     pScsiThread->activeDataAddress += xferCount;
  933.     pScsiThread->activeDataLength  -= xferCount;
  934.     
  935.     SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch data transfer aborted 
  936.            (%d bytes transferred).n",
  937.            xferCount, 0, 0, 0, 0, 0);
  938.     break;
  939.     
  940. case SCSI_MSG_OUT_PHASE:
  941.          SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch message out aborted "
  942.            "(%d of %d bytes sent).n",
  943.        pScsiThread->pScsiCtrl->msgOutLength,
  944.    pScsiThread->pScsiCtrl->msgOutLength - remCount,
  945.        0, 0, 0, 0);
  946.     break;
  947.     
  948. case SCSI_MSG_IN_PHASE:
  949.             SYM895_SCSI_DEBUG_MSG("sym895PhaseMismatch message in aborted "
  950.           "(%d bytes received).n",
  951.           pScsiThread->pScsiCtrl->msgInLength,
  952.           0, 0, 0, 0, 0);
  953.             break;
  954. case SCSI_COMMAND_PHASE:
  955. case SCSI_STATUS_PHASE:
  956.     SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch unsupported 
  957.                                    phase (%d).n", phase, 0, 0, 0, 0, 0);
  958.     return (ERROR);
  959.     
  960. default:
  961.     SCSI_MSG ("sym895PhaseMismatch invalid phase (%d).n",
  962.                       phase, 0, 0, 0, 0, 0);
  963.             return (ERROR);
  964.         }
  965.     return (OK);
  966.     }
  967. /******************************************************************************
  968. *
  969. * sym895InitIdentEvent - identification thread event processing 
  970. *
  971. * Parse the event type and handle it accordingly.  This may result in state
  972. * changes for the thread, state variables being updated, etc.
  973. *
  974. * RETURNS N/A
  975. */
  976. LOCAL void sym895InitIdentEvent
  977.     (
  978.     SYM895_THREAD * pThread,
  979.     SYM895_EVENT *  pEvent
  980.     )
  981.     {
  982.     SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;
  983.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  984.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  985.     /* Update controller msg in/out state after script completes */
  986.     pScsiCtrl->msgOutState = pThread->msgOutStatus;
  987.     pScsiCtrl->msgInState  = pThread->msgInStatus;
  988.     
  989.     /* Parse script exit status; handle as necessary */
  990.     switch (pScsiEvent->type)
  991. {
  992. case SYM895_RESELECTED:
  993.             pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;
  994.             bcopy ((char *) pScsiCtrl->identBuf,
  995.                    (char *) pScsiThread->identMsg,
  996.                    pScsiThread->nBytesIdent);
  997.             sym895ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);
  998.          sym895IdentInContinue (pThread);
  999.     break;
  1000. case SYM895_MESSAGE_OUT_SENT:
  1001.             /*
  1002.              * This will be after "ABORT (TAG)" msg has sent.
  1003.            * The target will disconnect any time; it may have already
  1004.      * done so, in which case we won't be able to resume the
  1005.      *  thread, but no matter.
  1006.      */
  1007.     break;
  1008. case SYM895_MESSAGE_IN_RECVD:
  1009.     /*
  1010.      *  Continue parsing the identification message.  It
  1011.              *  should by now be complete.
  1012.              *
  1013.      * First byte of ident msg is already in ident buffer.
  1014.      * Remaining bytes are in the normal message input buffer.
  1015.      * This should always be a two-byte message (viz. QUEUE TAG);
  1016.      * it would be nicer if there were a way to avoid hard-coding
  1017.      * this.
  1018.      */
  1019.             bcopy ((char *) pScsiCtrl->msgInBuf,
  1020.        (char *) pScsiThread->identMsg + pScsiThread->nBytesIdent,2);
  1021.     
  1022.          pScsiThread->nBytesIdent += 2;
  1023.          sym895IdentInContinue (pThread);
  1024.     break;
  1025. case SYM895_SCRIPT_ABORTED:
  1026.     SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x 
  1027.                                    abortedn", (int) pThread, 0, 0, 0, 0, 0);
  1028.     break;
  1029.         case SYM895_DISCONNECTED:
  1030.     SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x"
  1031.              "disconnectedn",
  1032.            (int) pThread, 0, 0, 0, 0, 0);
  1033.     sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1034.     break;
  1035.    
  1036. case SYM895_SCSI_BUS_RESET:
  1037.          SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x bus 
  1038.                                    resetn", (int) pThread, 0, 0, 0, 0, 0);
  1039.          /* Do not try to resume this thread.  SCSI mgr will tidy up.  */
  1040.     sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1041.     break;
  1042. case SYM895_UNEXPECTED_DISCON:
  1043.     /* not really unexpected after an abort message ... */
  1044.          SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x "
  1045.                       "unexpected disconnectionn",
  1046.                       (int) pThread, 0, 0, 0, 0, 0);
  1047.     sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1048.     break;
  1049.     
  1050. case SYM895_ILLEGAL_PHASE:
  1051.     SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x "
  1052.                       "illegal phase requested.n",
  1053.                       (int) pThread, 0, 0, 0, 0, 0);
  1054.     
  1055.          sym895ThreadFail (pThread, S_scsiLib_INVALID_PHASE);
  1056.          break;
  1057. default:
  1058.        SCSI_MSG ("sym895InitIdentEvent invalid event type (%d)n",
  1059.     pScsiEvent->type, 0, 0, 0, 0, 0);
  1060.     break;
  1061. }
  1062.   
  1063.   }
  1064. /******************************************************************************
  1065. *
  1066. * sym895TargIdentEvent - SYM 53C895 identification thread event processing 
  1067. *
  1068. * Parse the event type and handle it accordingly.  This may result in state
  1069. * changes for the thread, state variables being updated, etc.
  1070. *
  1071. * RETURNS: N/A
  1072. *
  1073. * NOMANUAL
  1074. */
  1075. LOCAL void sym895TargIdentEvent
  1076.     (
  1077.     SYM895_THREAD * pThread,
  1078.     SYM895_EVENT *  pEvent
  1079.     )
  1080.     {
  1081.     SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;
  1082.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1083.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  1084.     /*
  1085.      *  Update controller msg in/out state after script completes
  1086.      */
  1087.     pScsiCtrl->msgOutState = pThread->msgOutStatus;
  1088.     pScsiCtrl->msgInState  = pThread->msgOutStatus;
  1089.     
  1090.     /*
  1091.      * Parse script exit status; handle as necessary
  1092.      */
  1093.     switch (pScsiEvent->type)
  1094. {
  1095. case SYM895_SELECTED:
  1096.       pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;
  1097.     bcopy ((char *) pScsiCtrl->identBuf,
  1098.    (char *) pScsiThread->identMsg,
  1099.    pScsiThread->nBytesIdent);
  1100.          sym895ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);
  1101.          break;
  1102.     
  1103.         case SYM895_DISCONNECTED:
  1104.            SYM895_SCSI_DEBUG_MSG ("sym895TargIdentEvent: thread 0x%08x:"
  1105.             " disconnectedn",
  1106.     (int) pThread, 0, 0, 0, 0, 0);
  1107.        sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1108. break;
  1109.     
  1110. case SYM895_SCSI_BUS_RESET:
  1111.  
  1112.           SYM895_SCSI_DEBUG_MSG ("sym895TargIdentEvent: thread 0x%08x: 
  1113.                                    bus resetn",(int) pThread, 0, 0, 0, 0, 0);
  1114.     
  1115.             /* Do not try to resume this thread.  SCSI mgr will tidy up. */
  1116.     sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1117.     break;
  1118. case SYM895_UNEXPECTED_DISCON:
  1119.          SYM895_SCSI_DEBUG_MSG ("sym895TargIdentEvent: thread 0x%08x: "
  1120.          "unexpected disconnectionn",
  1121.          (int) pThread, 0, 0, 0, 0, 0);
  1122.     sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1123.     break;
  1124.     
  1125. default:
  1126.       SCSI_MSG ("sym895TargIdentEvent: invalid event type (%d)n",
  1127.      pScsiEvent->type, 0, 0, 0, 0, 0);
  1128.     break;
  1129. }
  1130.     }
  1131.     
  1132. /******************************************************************************
  1133. *
  1134. * sym895Resume - resume a script corresponding to a suspended thread
  1135. *
  1136. * NOTE the script can only be resumed if the controller is currently idle.
  1137. * To avoid races, interrupts must be locked while this is checked and the
  1138. * script re-started.
  1139. *
  1140. * Reasons why the controller might not be idle include SCSI bus reset and
  1141. * unexpected disconnection, both of which might occur in practice.  Hence
  1142. * this is not considered to be a major software error.
  1143. *
  1144. * RETURNS OK, or ERROR if the controller is in an invalid state (this
  1145. * should not be treated as a major software failure).
  1146. */
  1147. LOCAL STATUS sym895Resume
  1148.     (
  1149.     SIOP *           pSiop, /* pointer to controller structure */
  1150.     SYM895_THREAD *  pThread, /* pointer to thread structure     */
  1151.     SYM895_SCRIPT_ENTRY entryId /* entry point of script to resume */
  1152.     )
  1153.     {
  1154.     STATUS status;
  1155.     int    key;
  1156.     /* Check validity of connection and start script if OK */
  1157.     key = intLock ();
  1158.     switch (pSiop->state)
  1159. {
  1160. case SYM895_STATE_IDLE:
  1161.     SYM895_SCSI_DEBUG_MSG ("sym895Resume thread 0x%08x"
  1162.    " state %d -> %dn",
  1163.           (int) pThread,
  1164.         SYM895_STATE_IDLE, SYM895_STATE_ACTIVE,
  1165.         0, 0, 0);
  1166.       sym895ScriptStart (pSiop, pThread, entryId);
  1167.     pSiop->state = SYM895_STATE_ACTIVE;
  1168.     status = OK;
  1169.       break;
  1170. case SYM895_STATE_PASSIVE:
  1171. case SYM895_STATE_ACTIVE:
  1172. default:
  1173.       status = ERROR;
  1174.     break;
  1175. }
  1176.     intUnlock (key);
  1177.     return (status);
  1178.     }
  1179. /******************************************************************************
  1180. *
  1181. * sym895IdentInContinue - continue incoming identification
  1182. *
  1183. * Parse the message built up so far.  If it is not yet complete, do nothing.
  1184. * If the message is complete, attempt to reconnect the thread it identifies,
  1185. * and deactivate this thread (the identification thread is no longer active).
  1186. * Otherwise (identification has failed), abort the identification sequence.
  1187. *
  1188. * RETURNS N/A
  1189. */
  1190. LOCAL void sym895IdentInContinue
  1191.     (
  1192.     SYM895_THREAD * pThread
  1193.     )
  1194.     {
  1195.     SCSI_THREAD *     pNewThread;
  1196.     SCSI_THREAD *     pScsiThread = (SCSI_THREAD *) pThread;
  1197.     SCSI_CTRL *       pScsiCtrl   = pScsiThread->pScsiCtrl;
  1198.     SCSI_IDENT_STATUS status;
  1199.     SCSI_THREAD_STATE state;
  1200.     status = scsiIdentMsgParse (pScsiCtrl, pScsiThread->identMsg,
  1201.                    pScsiThread->nBytesIdent,
  1202.                   &pScsiThread->pScsiPhysDev,
  1203.        &pScsiThread->tagNumber);
  1204.     switch (status)
  1205. {
  1206. case SCSI_IDENT_INCOMPLETE:
  1207.              state = SCSI_THREAD_IDENT_IN;
  1208.      break;
  1209. case SCSI_IDENT_COMPLETE:
  1210.              scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_RECONNECTED);
  1211.              if ((pNewThread = scsiMgrPhysDevActiveThreadFind (
  1212.       pScsiThread->pScsiPhysDev,
  1213.       pScsiThread->tagNumber)) == 0)
  1214.  {
  1215.  state = SCSI_THREAD_IDENT_ABORTING;
  1216.  }
  1217.              else
  1218.                  {
  1219.                  sym895ThreadReconnect ((SYM895_THREAD *) pNewThread);
  1220.                  state = SCSI_THREAD_INACTIVE;
  1221.                  }
  1222.              break;
  1223. case SCSI_IDENT_FAILED:
  1224.              state = SCSI_THREAD_IDENT_ABORTING;
  1225.        break;
  1226. default:
  1227.           SCSI_MSG ("sym895IdentInContinue invalid ident status (%d)n",
  1228.                     status, 0, 0, 0, 0, 0);
  1229.           state = SCSI_THREAD_INACTIVE;
  1230.      break;
  1231. }
  1232.     if (state == SCSI_THREAD_IDENT_ABORTING)
  1233. sym895ThreadAbort ((SIOP *) pScsiCtrl, pThread);
  1234.     sym895ThreadStateSet (pThread, state);
  1235.     }
  1236. /******************************************************************************
  1237. *
  1238. * sym895ThreadReconnect - reconnect a thread
  1239. *
  1240. * Restore the SCSI pointers for the thread (this really should be in a more
  1241. * generic section of code - perhaps part of the SCSI manager's thread event
  1242. * procesing ?).  Update the newly-connected thread's context (including
  1243. * shared memory area) and resume it.  Set the thread's state to ESTABLISHED.
  1244. *
  1245. * RETURNS N/A
  1246. *
  1247. * NOMANUAL
  1248. */
  1249. LOCAL void sym895ThreadReconnect
  1250.     (
  1251.     SYM895_THREAD * pThread
  1252.     )
  1253.     {
  1254.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1255.     SCSI_CTRL   * pScsiCtrl   = pScsiThread->pScsiCtrl;
  1256.     SIOP        * pSiop       = (SIOP *) pScsiCtrl;
  1257.     
  1258.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadReconnect reconnecting thread 0x%08xn",
  1259.                            (int) pThread, 0, 0, 0, 0, 0);
  1260.     pScsiCtrl->pThread = pScsiThread;
  1261.     /* Implied RESTORE POINTERS action see "scsiMsgInComplete ()" */
  1262.     pScsiThread->activeDataAddress = pScsiThread->savedDataAddress;
  1263.     pScsiThread->activeDataLength  = pScsiThread->savedDataLength;
  1264.     sym895ThreadUpdate (pThread);
  1265.     if (sym895Resume (pSiop, pThread, SYM895_SCRIPT_INIT_CONTINUE) != OK)
  1266.         {
  1267. SYM895_SCSI_DEBUG_MSG ("sym895ThreadReconnect failed to resume thread.n",
  1268.                   0, 0, 0, 0, 0, 0);
  1269. sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1270. return;
  1271. }
  1272.     sym895ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  1273.     }
  1274. /******************************************************************************
  1275. *
  1276. * sym895StepEnable - Enable/disable script single step 
  1277. *
  1278. * Enable/disable single step facility on SYM895 chip.  Also, unmask/mask single 
  1279. * step interrupt in Dien register. Before any SCSI execution you just have to 
  1280. * use sym895StepEnable (pSiop, TRUE) to run in single step mode.  
  1281. *
  1282. * To run a script step use sym895SingleStep(pSiop).
  1283. * To disable use sym895StepEnable (pSiop, FALSE).
  1284. * RETURNS: N/A
  1285. *
  1286. * NOMANUAL
  1287. */
  1288. void sym895StepEnable 
  1289.     (
  1290.     SIOP * pSiop, /* pointer to SIOP info       */
  1291.     BOOL   enable /* TRUE => enable single-step */
  1292.     )
  1293.     {
  1294.     if (enable)
  1295. {
  1296. /* enable single-step interrupt */
  1297. SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN, 
  1298.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN) | 
  1299.                            SYM895_B_SSI));
  1300. /* set single-step mode */
  1301. SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1302.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) | 
  1303.                            SYM895_DCNTL_SSM));
  1304. /* disable manual Start */
  1305. SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE, 
  1306.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) & 
  1307.                            ~SYM895_DMODE_MAN)); 
  1308. }
  1309.     else 
  1310. {
  1311. /* unset single-step mode */
  1312. SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1313.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) & 
  1314.                            ~SYM895_DCNTL_SSM));
  1315. /* disable single-step interrupt */
  1316. SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN, 
  1317.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN) & 
  1318.                            ~SYM895_B_SSI));
  1319. /* enable manual Start */
  1320. SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE, 
  1321.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) | 
  1322.                            SYM895_DMODE_MAN));
  1323.       }
  1324.     pSiop->isSingleStep = enable;
  1325.     }
  1326. /******************************************************************************
  1327. *
  1328. * sym895SingleStep - Perform a single step 
  1329. *
  1330. * Perform a single step by writing the STD bit in the DCNTL register.
  1331. * The parameter is a pointer to the SIOP information. 
  1332. * RETURNS: N/A
  1333. * NOMANUAL
  1334. */
  1335. void sym895SingleStep
  1336.     (
  1337.     SIOP * pSiop,  /* pointer to SIOP info */ 
  1338.     BOOL   verbose /* show all registers   */
  1339.     )
  1340.     {
  1341.     UINT * siopPc;
  1342.     /*
  1343.      * Start the SIOP: if not in single-step mode it will then continue
  1344.      * the normal instruction sequence.  If in single-step mode, wait
  1345.      * until one instruction has been executed.
  1346.      */
  1347.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1348.                        (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
  1349.        SYM895_DCNTL_STD));
  1350.     if (!pSiop->isSingleStep)
  1351. return;
  1352.     semTake (pSiop->singleStepSem, WAIT_FOREVER);
  1353.     /*
  1354.      * Allow any tasks using SCSI to get a look-in - they may change the
  1355.      * controller state, in which case we'd like to see that change now
  1356.      * rather than next time.
  1357.      */
  1358.     taskDelay (sysClkRateGet()/ 20); /* this needs to be tuned */
  1359.     /* Show what the SIOP is about to do */ 
  1360.     if (pSiop->state == SYM895_STATE_IDLE)
  1361. SCSI_MSG("SYM895 is idle.nn", 0, 0, 0, 0, 0, 0);
  1362.     else
  1363. {
  1364. siopPc = (UINT *)SYM895_REG32_READ (pSiop, SYM895_OFF_DSP);
  1365.   /* mask PCI's view of memory */ 
  1366. siopPc = (UINT *)((UINT) siopPc & 0x7fffffff);
  1367. printf ("SYM895 [%d] Next Opcode (0x%08x) => 0x%08x 0x%08xnn",
  1368. pSiop->state, (int) siopPc, SYM895_SWAP_32(siopPc[0]), 
  1369.     SYM895_SWAP_32(siopPc[1]) );
  1370. }
  1371.     
  1372.     /* Dump the SIOP registers, if in verbose mode */
  1373.     if (verbose)
  1374.      sym895Show (pSiop);
  1375.     }
  1376. /******************************************************************************
  1377. *
  1378. * sym895Show - display values of all readable SYM 53C8xx SIOP registers.
  1379. *
  1380. * This routine displays the state of the SIOP registers in a user-friendly way.
  1381. * It is useful primarily for debugging. The input parameter is the pointer to 
  1382. * the SIOP information structure returned by the sym895CtrlCreate() call.
  1383. *
  1384. * NOTE
  1385. * The only readable register during a script execution is the Istat register. 
  1386. * If you use this routine during the execution of a SCSI command, the result 
  1387. * could be unpredictable.
  1388. *
  1389. * EXAMPLE:
  1390. * .CS
  1391. * -> sym895Show
  1392. *SYM895 Registers 
  1393. *---------------- 
  1394. * Scntl0   = 0xd0 Scntl1   = 0x00 Scntl2   = 0x00 Scntl3   = 0x00
  1395. * Scid     = 0x67 Sxfer    = 0x00 Sdid     = 0x00 Gpreg    = 0x0f
  1396. * Sfbr     = 0x0f Socl     = 0x00 Ssid     = 0x00 Sbcl     = 0x00
  1397. * Dstat    = 0x80 Sstat0   = 0x00 Sstat1   = 0x0f Sstat2   = 0x02
  1398. * Dsa      = 0x07ea9538
  1399. * Istat    = 0x00
  1400. * Ctest0   = 0x00 Ctest1   = 0xf0 Ctest2   = 0x35 Ctest3   = 0x10
  1401. * Temp     = 0x001d0c54
  1402. * Dfifo    = 0x00
  1403. * Dbc0:23-Dcmd24:31  = 0x54000000
  1404. * Dnad     = 0x001d0c5c
  1405. * Dsp      = 0x001d0c5c
  1406. * Dsps     = 0x000000a0
  1407. * Scratch0  = 0x01 Scratch1  = 0x00 Scratch2  = 0x00 Scratch3  = 0x00
  1408. * Dmode    = 0x81 Dien     = 0x35 Dwt      = 0x00 Dcntl    = 0x01
  1409. * Sien0    = 0x0f Sien1    = 0x17 Sist0    = 0x00 Sist1    = 0x00
  1410. * Slpar    = 0x4c Swide    = 0x00 Macntl   = 0xd0 Gpcntl   = 0x0f
  1411. * Stime0   = 0x00 Stime1   = 0x00 Respid0  = 0x80 Respid1  = 0x00 
  1412. * Stest0   = 0x07 Stest1   = 0x00 Stest2   = 0x00 Stest3   = 0x80
  1413. * Sidl     = 0x0000 Sodl     = 0x0000 Sbdl     = 0x0000
  1414. * Scratchb = 0x00000200
  1415. * value = 0 = 0x0
  1416. * .CE
  1417. *
  1418. * RETURNS: OK, or ERROR if <pScsiCtrl> and <pSysScsiCtrl> are both NULL.
  1419. *
  1420. * SEE ALSO: sym895CtrlCreate()
  1421. */
  1422. STATUS sym895Show 
  1423.     (
  1424.     SIOP * pSiop  /* pointer to SCSI controller */
  1425.     )
  1426.     {
  1427.    
  1428.     if (pSiop == NULL)
  1429. {
  1430. SCSI_MSG (" Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
  1431. return (ERROR);
  1432. }
  1433.     printf ("SYM895 Registers n");
  1434.     printf ("---------------- n");
  1435.     printf ("Scntl0   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL0)); 
  1436.     printf ("Scntl1   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL1)); 
  1437.     printf ("Scntl2   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL2)); 
  1438.     printf ("Scntl3   = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3)); 
  1439.     printf ("Scid     = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SCID)); 
  1440.     printf ("Sxfer    = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SXFER)); 
  1441.     printf ("Sdid     = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SDID)); 
  1442.     printf ("Gpreg    = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_GPREG)); 
  1443.     printf ("Sfbr     = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SFBR)); 
  1444.     printf ("Socl     = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL)); 
  1445.     printf ("Ssid     = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SSID)); 
  1446.     printf ("Sbcl     = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL)); 
  1447.     /* Reading this register clears the interrupts */
  1448.     printf ("Dstat    = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT)); 
  1449.     printf ("Sstat0   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT0)); 
  1450.     printf ("Sstat1   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT1)); 
  1451.     printf ("Sstat2   = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2)); 
  1452.     printf ("Dsa      = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop,  
  1453.                                                               SYM895_OFF_DSA)); 
  1454.     printf ("Istat    = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT));
  1455.     printf ("Ctest0   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST0));
  1456.     printf ("Ctest1   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST1));
  1457.     printf ("Ctest2   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST2));
  1458.     printf ("Ctest3   = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST3));
  1459.     
  1460.     printf ("Temp     = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop, 
  1461.                                                               SYM895_OFF_TEMP)); 
  1462.     printf ("Dfifo    = 0x%02xn", SYM895_REG8_READ(pSiop, SYM895_OFF_DFIFO)); 
  1463.     printf ("Dbc0:23-Dcmd24:31  = 0x%08xn", 
  1464.             (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DBC)); 
  1465.     printf ("Dnad     = 0x%08xn", 
  1466.             (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DNAD)); 
  1467.     printf ("Dsp      = 0x%08xn", 
  1468.             (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DSP)); 
  1469.     printf ("Dsps     = 0x%08xn", 
  1470.             (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DSPS)); 
  1471.     printf ("Scratch0  = 0x%02x ",  SYM895_REG8_READ (pSiop, 
  1472.                                                       SYM895_OFF_SCRATCHA0)); 
  1473.     printf ("Scratch1  = 0x%02x ",  SYM895_REG8_READ (pSiop, 
  1474.                                                       SYM895_OFF_SCRATCHA1)); 
  1475.     printf ("Scratch2  = 0x%02x ",  SYM895_REG8_READ (pSiop, 
  1476.                                                       SYM895_OFF_SCRATCHA2)); 
  1477.     printf ("Scratch3  = 0x%02xn", SYM895_REG8_READ (pSiop, 
  1478.                                                       SYM895_OFF_SCRATCHA3)); 
  1479.     printf ("Dmode    = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE));
  1480.     printf ("Dien     = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN));
  1481.     printf ("Dwt      = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_DWT));
  1482.     printf ("Dcntl    = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL));
  1483.     printf ("Sien0    = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN0)); 
  1484.     printf ("Sien1    = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN1)); 
  1485.     /* Reading these registers clears the interrupts */
  1486.     printf ("Sist0    = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0)); 
  1487.     printf ("Sist1    = 0x%02x",  SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1)); 
  1488.     printf ("n");
  1489.     printf ("Slpar    = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SLPAR)); 
  1490.     printf ("Swide    = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SWIDE)); 
  1491.     printf ("Macntl   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_MACNTL)); 
  1492.     printf ("Gpcntl   = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_GPCNTL)); 
  1493.     printf ("Stime0   = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STIME0)); 
  1494.     printf ("Stime1   = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STIME1)); 
  1495.     printf ("Respid0  = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_RESPID0)); 
  1496.     printf ("Respid1  = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_RESPID1)); 
  1497.     printf ("n");
  1498.     printf ("Stest0   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_STEST0)); 
  1499.     printf ("Stest1   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_STEST1)); 
  1500.     printf ("Stest2   = 0x%02x ",  SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2)); 
  1501.     printf ("Stest3   = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_STEST3)); 
  1502.     printf ("Sidl     = 0x%04x ",  SYM895_REG16_READ (pSiop, SYM895_OFF_SIDL)); 
  1503.     printf ("Sodl   = 0x%04x ",  SYM895_REG16_READ (pSiop, SYM895_OFF_SODL)); 
  1504.     printf ("Sbdl   = 0x%04xn", SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL)); 
  1505.     printf ("Scratchb = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop, 
  1506.                                                       SYM895_OFF_SCRATCHB0)); 
  1507.     printf ("Scratchc = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop, 
  1508.                                                       SYM895_OFF_SCRATCHC0));
  1509.     printf ("Scratchd = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop, 
  1510.                                                       SYM895_OFF_SCRATCHD));
  1511.     return (OK);
  1512.     }
  1513. /*******************************************************************************
  1514. *
  1515. * sym895Delay - Delays the execution for a predefined period;
  1516. *
  1517. * This delay is required for successive reads from the SCSI and DMA status
  1518. * registers. The data manual recommends a delay of 12 SCLK between such 
  1519. * successive reads. We are trying to emulate the 12 SCLKs by this routine
  1520. *
  1521. * NOMANUAL
  1522. */
  1523. LOCAL void sym895Delay()
  1524.     {
  1525.     volatile int i = 0;
  1526.     for (i=0; i<sym895DelayCount; i++)
  1527.         ;
  1528.     }
  1529. /*******************************************************************************
  1530. *
  1531. * sym895GPIOConfig - configures general purpose pins GPIO 0-4.
  1532. *
  1533. * This routine uses the GPCNTL register to configure the general purpose pins 
  1534. * available on Sym895 chip.  Bits 0-4 of GPCNTL register map to GPIO 0-4 pins. 
  1535. * A bit set in GPCNTL configures corresponding pin as input and a bit reset 
  1536. * configures the pins as output.
  1537. *
  1538. * .IP <pSiop>
  1539. *  pointer to the SIOP structure.
  1540. *
  1541. * .IP <ioEnable>
  1542. *  bits 0-4 of this parameter configure GPIO 0-4 pins.  1 => input, 0 => output.   
  1543. *
  1544. * .IP <mask>
  1545. *  bits 0-4 of this parameter identify valid bits in <ioEnable> parameter. Only
  1546. *  those pins are configured, which have a corresonding bit set in this parameter. 
  1547. */
  1548. STATUS sym895GPIOConfig
  1549.     (
  1550.     SIOP * pSiop,      /* pointer to SIOP structure   */
  1551.     UINT8 ioEnable,    /* bits indicate input/output  */
  1552.     UINT8 mask         /* mask for ioEnable parameter */
  1553.     )
  1554.     {
  1555.     if (pSiop == NULL)
  1556. {
  1557. SCSI_MSG (" Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
  1558. return (ERROR);
  1559. }
  1560.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_GPCNTL, 
  1561.                        ((SYM895_REG8_READ(pSiop,SYM895_OFF_GPCNTL) & ~mask) | 
  1562.                         ioEnable)); 
  1563.     return (OK);
  1564.     }
  1565. /*******************************************************************************
  1566. *
  1567. * sym895GPIOCtrl - controls general purpose pins GPIO 0-4.
  1568. *
  1569. * This routine uses the GPREG register to set/reset of the general purpose 
  1570. * pins available on Sym895 chip.
  1571. *
  1572. * .IP <pSiop>
  1573. *  pointer to the SIOP structure.
  1574. *
  1575. * .IP <ioState>
  1576. *  bits 0-4 of this parameter controls GPIO 0-4 pins.  1 => set, 0 => reset.   
  1577. *
  1578. * .IP <mask>
  1579. *  bits 0-4 of this parameter identify valid bits in <ioState> parameter. Only
  1580. *  those pins are activated, which have a corresonding bit set in this parameter. 
  1581. */
  1582. STATUS sym895GPIOCtrl
  1583.     (
  1584.     SIOP * pSiop,      /* pointer to SIOP structure   */
  1585.     UINT8  ioState,    /* bits indicate set/reset */
  1586.     UINT8  mask        /* mask for ioState parameter */
  1587.     )
  1588.     {
  1589.     if (pSiop == NULL)
  1590. {
  1591. SCSI_MSG (" Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
  1592. return (ERROR);
  1593. }
  1594.     SYM895_REG8_WRITE(pSiop, SYM895_OFF_GPREG, 
  1595.                       ((SYM895_REG8_READ(pSiop, SYM895_OFF_GPREG) & ~mask) | 
  1596.                                          ioState));
  1597.     return (OK);    
  1598.     }
  1599. /******************************************************************************
  1600. *
  1601. * sym895Loopback - This routine performs loopback diagnotics on 895 chip.
  1602. *
  1603. * Loopback mode allows 895 chip to control all signals, regardless of whether
  1604. * it is in initiator or target role. This mode insures proper SCRIPTS instruction
  1605. * fetches and data paths.  SYM895 executes initiator instructions through the
  1606. * SCRIPTS, and this routine implements the target role by asserting and polling
  1607. * the appropriate SCSI signals in the SOCL, SODL, SBCL, and SBDL registers.
  1608. * To configure 895 in loopback mode,
  1609. *
  1610. * (1) Bits 3 and 4 of STEST2 should be set to put SCSI pins in High-Impedance 
  1611. *     mode, so that signals are not asserted on to the SCSI bus.
  1612. *
  1613. * (2) Bit 4 of DCNTL should be set to turn on single step mode.  This allows the
  1614. *     target program (this routine) to monitor when an initiator SCRIPTS   
  1615. *     instruction has completed.
  1616. *
  1617. * In this routine, SELECTION, MSG_OUT and DATA_OUT phases are checked. This will  
  1618. * ensure that data and control paths are proper.
  1619. */
  1620. STATUS sym895Loopback
  1621.     (
  1622.     SIOP * pSiop   /* pointer to SIOP controller structure */
  1623.     )
  1624.     {
  1625.  
  1626.     UINT8  stest2;  /* store for existing STEST2 value */ 
  1627.     UINT8  dcntl ;  
  1628.     UINT8  sien0 ;  
  1629.     UINT8  sien1 ;
  1630.     UINT8  dien  ;
  1631.     UINT8  temp;
  1632.     int    msgInData;
  1633.     UINT8  msgBuf   = LOOPBACK_MSG_BYTE;
  1634.     UINT16 dataBuf  = LOOPBACK_DATA;
  1635.     STATUS retVal   = ERROR;    
  1636.     SYM895_LOOPBACK  loopback;
  1637.     SCSI_CTRL *  pScsiCtrl = &(pSiop->scsiCtrl);
  1638.  
  1639.     if (pSiop == NULL)
  1640. {
  1641. SCSI_MSG ("Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
  1642. return (ERROR);
  1643. }
  1644.     /* 
  1645.      * Initialise the addresss space from where the "sym895Diag" Scripts  
  1646.      * fetches the table indirect information. This scripts routine selects
  1647.      * 895 in loopback mode and then sends out IDENTIFY message.
  1648.      */
  1649.     loopback.device = SYM895_SWAP_32(
  1650.                       (SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) << 24) | 
  1651.                       ((SYM895_REG8_READ (pSiop, SYM895_OFF_SCID) 
  1652.                        & SYM895_SCID_ENC_MASK) << 16) |
  1653.                       (SYM895_REG8_READ (pSiop, SYM895_OFF_SXFER) << 8));  
  1654.     loopback.identOut.size = SYM895_SWAP_32(0x01);
  1655.     loopback.identOut.addr = (UINT8 *) SYM895_SWAP_32
  1656.                              ((UINT32)SYM895_VIRT_TO_PHYS(&msgBuf));
  1657.     loopback.dataOut.size = SYM895_SWAP_32(0x02);
  1658.     loopback.dataOut.addr = (UINT8 *) SYM895_SWAP_32
  1659.                              ((UINT32)SYM895_VIRT_TO_PHYS(&dataBuf));
  1660.     stest2 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2);
  1661.     dcntl  = SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL);
  1662.     sien0  = SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN0);
  1663.     sien1  = SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN1);
  1664.     dien   = SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN);
  1665.     
  1666.     /* Configure 895 chip in loop back mode */
  1667.    
  1668.     /* 
  1669.      * First, disable all interrupts. DSTAT & SIST0,1 are polled as and when
  1670.      * needed determine the possible event. This insures that no interrupts
  1671.      * are routed to the sym895 handler and no events get notified to scsi 
  1672.      * manager.
  1673.      */ 
  1674.       
  1675.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN,  0x00);
  1676.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN0, 0x00);     
  1677.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN1, 0x00);
  1678.     /* 
  1679.      * Abort any SCRIPT currently running, to run diagnostic SCRIPTS
  1680.      * If the diagnostic SCRIPTS are run once on POR before other scripts are 
  1681.      * run, then aborting is not needed.
  1682.      */
  1683.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_ISTAT, 
  1684.                        SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) | 
  1685.                                          SYM895_ISTAT_ABRT);
  1686.     while ((SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) & 
  1687.                               (SYM895_ISTAT_SIP | SYM895_ISTAT_DIP)) == 0)
  1688.         ;
  1689.     if (SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) & (SYM895_ISTAT_DIP) )
  1690.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_ISTAT,0x00);
  1691.     temp = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT); 
  1692.  
  1693.     /* Set the STEST2 register loopback mode bits. */
  1694.   
  1695.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2, 
  1696.                        SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2) |
  1697.                        (SYM895_STEST2_SCE | SYM895_STEST2_SLB | 
  1698.                         SYM895_STEST2_SZM));
  1699.     /* Set Sym895 in Single-Step Mode */ 
  1700.   
  1701.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1702.                        SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
  1703.                                          SYM895_DCNTL_SSM);     
  1704.     /* disable manual Start */
  1705.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE, 
  1706.                        (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) & 
  1707.                                           ~SYM895_DMODE_MAN)); 
  1708.     /* 
  1709.      * By now, the SCSI pins are in High-Impedance mode. Start with SELECTION
  1710.      * in loopback mode. This is initiated by a SCRIPT instruction.SYM895 chip 
  1711.      * selects itself. The target functionality is implemented here.
  1712.      */ 
  1713.     /*
  1714.      * Set the shared data address, load the script start address,
  1715.      * then start the SCSI Controller unless it's in single-step mode.
  1716.      */
  1717.     SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSA, 
  1718.                         (UINT32)SYM895_VIRT_TO_PHYS (&loopback));
  1719.     SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSP, 
  1720.         (UINT32)SYM895_VIRT_TO_PHYS (
  1721.                         (UINT32)sym895ScriptEntry [SYM895_SCRIPT_DIAG]));
  1722.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1723.                        (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
  1724.        SYM895_DCNTL_STD));
  1725.     /* 
  1726.      * Wait till the above SCRIPTS instruction is fetched, and host bus is free. 
  1727.      * This delay is system-dependent because of chip clock speed, host
  1728.      * arbitration times.
  1729.      */            
  1730.     
  1731.     CACHE_PIPE_FLUSH();
  1732.     taskDelay (sysClkRateGet()/ 10000); /* This needs to be tuned - now 100us */  
  1733.     CACHE_PIPE_FLUSH();
  1734.     /* 
  1735.      * Wait for the SEL signal to go HIGH and BSY to go LOW. The above SELECT
  1736.      * instruction asserts SEL signal after succeeding in arbitration. It then
  1737.      * asserts data lines corresponding to sym895's SCSI ID and the ID of target 
  1738.      * (which in this case are 7).Then initiator (SELECT instruction) releases
  1739.      * the BSY signal. 
  1740.      */      
  1741.     temp = 0;
  1742.     while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & 
  1743.           (SYM895_SBCL_BSY | SYM895_SBCL_SEL)) != 0x10) 
  1744.         {      
  1745.         temp++;
  1746.         if ( temp == 0)
  1747.             {
  1748.             SCSI_MSG ("selection timeoutn", 0, 0, 0, 0, 0, 0);
  1749.             retVal = ERROR;
  1750.             goto despatch;
  1751.             }
  1752.         }
  1753.  
  1754.     SCSI_MSG ("sym895Loopback: Selecting target ID = %xn", 
  1755.                SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL), 0, 0, 0, 0, 0); 
  1756.     /* 
  1757.      * Check whether correct bits are driven on the SCSI data bus during 
  1758.      * selection. 
  1759.      */
  1760.     if ( SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL) != 
  1761.          SYM895_REG16_READ (pSiop, SYM895_OFF_RESPID0))
  1762.         {
  1763.         SCSI_MSG ("sym895LoopBack: Error in Data Paths n",
  1764.                    0, 0, 0, 0, 0, 0);
  1765.         retVal = ERROR;
  1766.         goto despatch;
  1767.         }
  1768.  
  1769.     /* Now to respond to selection, BSY signal should be asserted */
  1770.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL, 
  1771.                        (SYM895_REG8_READ(pSiop,SYM895_OFF_SOCL) | 
  1772.                                          SYM895_SOCL_BSY));
  1773.     /* 
  1774.      * Once BSY is asserted, the initiator confirms its selection by releasing
  1775.      * SEL signal. Wait for SEL to be deasserted.
  1776.      */
  1777.     temp =0;
  1778.     while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_SEL) != 0)
  1779.         {
  1780.         temp++;
  1781.         if ( temp == 0)
  1782.             {
  1783.             SCSI_MSG ("selection timeoutn", 0, 0, 0, 0, 0, 0);
  1784.             retVal = ERROR;
  1785.             goto despatch;
  1786.             }
  1787.         }  
  1788.     /* 
  1789.      * if the initiator has asserted ATN while selecting, assert BSY and
  1790.      * MSG_OUT phase. If not ATN, Selection phase is complete.
  1791.      */
  1792.     if ( SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_ATN )
  1793.         { 
  1794.         SCSI_MSG ("sym895Loopback: Changing phase to MSG_OUTn",
  1795.                   0, 0, 0, 0, 0, 0);
  1796.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
  1797.                            SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) |  
  1798.                            (SYM895_SOCL_BSY | SYM895_SOCL_MSG | SYM895_SOCL_CD)
  1799.                           );    
  1800.   
  1801.         /* Selection Phase (with ATN) is now complete */     
  1802.     
  1803.         /* 
  1804.          * Wait for the Single-step status bit to set in DSTAT. This bit is set
  1805.          * after successful execution of each SCRIPTS instruction. 
  1806.          */
  1807.       
  1808.         while ((SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT) & SYM895_B_SSI) == 0)
  1809.             SCSI_MSG ("Sym895Loopback: Waiting for completion of SCRIPT 
  1810.                       Instruction 1n", 0, 0, 0, 0, 0, 0);
  1811.      
  1812.         /* 
  1813.          * Clear all interrupts just in case. Any pending interrupts whether
  1814.          * valid or stray will inhibit the execution of further SCRIPTS 
  1815.          * instruction.
  1816.          */
  1817.         temp = SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT);  
  1818.         sym895Delay();
  1819.         CACHE_PIPE_FLUSH();
  1820.         temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0);    
  1821.         sym895Delay();
  1822.         CACHE_PIPE_FLUSH();
  1823.         temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1); 
  1824.         sym895Delay();
  1825.         CACHE_PIPE_FLUSH();
  1826.         temp = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);  
  1827.        
  1828.         /* 
  1829.          * Set the Start DMA bit in DCNTL register. This restarts execution
  1830.          * of SCRIPTS. Now that SELECT instruction is successfully completed 
  1831.          * and SCSI phase is MSG_OUT, the next SCRIPT instruction sends the
  1832.          * IDENTIFY message to target.
  1833.          * 
  1834.          * MOVE FROM IDENT_BUF, WHEN MSG_OUT
  1835.          */
  1836.         SCSI_MSG ("sym895Loopback: Sending 8-bit Message 0x%xn",
  1837.                   msgBuf, 0, 0, 0, 0, 0);
  1838.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1839.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
  1840.                            SYM895_DCNTL_STD));
  1841.         /* Wait for the SCRIPT instruction to finish using the host bus */
  1842.         CACHE_PIPE_FLUSH();        
  1843.         taskDelay (sysClkRateGet()/ 1000); /* This needs to be tuned */ 
  1844.                                             /* now 100us */           
  1845.         CACHE_PIPE_FLUSH();
  1846.     
  1847.         /* 
  1848.          * The MOVE instruction waits for a phase change indicated by 
  1849.          * asserting of SREQ signal by the target. So assert SREQ.
  1850.          */
  1851.     
  1852.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,0xae); /* Hard code */
  1853.        
  1854.         /* Wait for the ACK to be set by the initiator */
  1855.         temp = 0;
  1856.         while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_ACK) == 0) 
  1857.             {
  1858.             temp++;
  1859.             if ( temp == 0)
  1860.                 {
  1861.                 SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
  1862.                 retVal = ERROR;
  1863.                 goto despatch;
  1864.                 }
  1865.             }
  1866.         msgInData = SYM895_REG8_READ (pSiop, SYM895_OFF_SBDL); /* read data */ 
  1867.        
  1868.         /* Deassert SREQ signal */
  1869.  
  1870.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL, 
  1871.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) & 
  1872.                            ~SYM895_SOCL_REQ));
  1873.         /* Wait for the ACK signal to be deasserted by initiator */
  1874.  
  1875.         temp = 0; 
  1876.         while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_ACK) != 0)
  1877.             {
  1878.             temp++;
  1879.             if ( temp == 0)
  1880.                 {
  1881.                 SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
  1882.                 retVal = ERROR;
  1883.                 goto despatch;
  1884.                 }
  1885.             }
  1886.         SCSI_MSG ("sym895Loopback: Received Message In data = 0x%xn",
  1887.                   msgInData, 0, 0, 0, 0, 0);
  1888.        
  1889.         if ( msgInData != msgBuf)
  1890.             {                 
  1891.             SCSI_MSG ("sym895Loopback: Error reading SCSI D0-D7 data busn",
  1892.                       0, 0, 0, 0, 0, 0);
  1893.             retVal = ERROR;
  1894.             goto despatch;
  1895.             }
  1896.         while ((SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT) & SYM895_B_SSI) == 0)
  1897.             logMsg("Sym895Loopback: Waiting for completion of SCRIPT 
  1898.                    Instruction 2n", 0, 0, 0, 0, 0, 0);
  1899.         SCSI_MSG ("sym895Loopback: Changing phase to DATA_OUTn",
  1900.                   0, 0, 0, 0, 0, 0);
  1901.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL, 
  1902.                            SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) &
  1903.                            ~(SYM895_SOCL_MSG | SYM895_SOCL_CD |
  1904.                            SYM895_SOCL_IO) ); 
  1905.         /* 
  1906.          * Set the Start DMA bit in DCNTL register. This restarts execution
  1907.          * of SCRIPTS. Now that SELECT instruction is successfully completed 
  1908.          * and SCSI phase is MSG_OUT, the next SCRIPT instruction sends the
  1909.          * 16-bit Data to target . 
  1910.          * 
  1911.          * MOVE FROM DATA_BUF, WHEN DATA_OUT
  1912.          */
  1913.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL3, 
  1914.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) | 
  1915.                            SYM895_SCNTL3_EWS));
  1916.         SCSI_MSG ("sym895Loopback: Sending 16-bit Data 0x%xn",
  1917.                   dataBuf, 0, 0, 0, 0, 0);
  1918.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, 
  1919.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) | 
  1920.                            SYM895_DCNTL_STD));
  1921.         /* Wait for the SCRIPT instruction to finish using the host bus */
  1922.         CACHE_PIPE_FLUSH();
  1923.         taskDelay (sysClkRateGet()/ 1000); /* This needs to be tuned */ 
  1924.                                             /* now 100us */           
  1925.         CACHE_PIPE_FLUSH();
  1926.     
  1927.         /* 
  1928.          * The MOVE instruction waits for a phase change indicated by 
  1929.          * asserting of SREQ signal by the target. Assert SREQ.
  1930.          */
  1931.         
  1932.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL , 0xa0);   /* Hard code */    
  1933.         /* Wait for the ACK to be set by the initiator */
  1934.         temp =0;
  1935.         while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & 
  1936.                                   SYM895_SBCL_ACK) == 0)
  1937.             {
  1938.             temp++;
  1939.             if ( temp == 0)
  1940.                 {
  1941.                 SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
  1942.                 retVal = ERROR;
  1943.                 goto despatch;
  1944.                 }
  1945.             }
  1946.  
  1947.         msgInData = SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL); /* read data bus */
  1948.         /* Deassert SREQ signal */
  1949.  
  1950.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL, 
  1951.                            (SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) & 
  1952.                            ~SYM895_SOCL_REQ));
  1953.         /* Wait for the ACK signal to be deasserted by initiator */
  1954.   
  1955.         temp = 0;
  1956.         while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & 
  1957.                                   SYM895_SBCL_ACK) != 0)
  1958.             {
  1959.             temp++;
  1960.             if ( temp == 0)
  1961.                 {
  1962.                 SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
  1963.                 retVal = ERROR;
  1964.                 goto despatch;
  1965.                 }
  1966.             }
  1967.         SCSI_MSG ("sym895Loopback: Received Data In = 0x%xn",
  1968.                   msgInData, 0, 0, 0, 0, 0);
  1969.         if ( msgInData != dataBuf)
  1970.             {
  1971.             SCSI_MSG ("sym895Loopback: Error reading SCSI D0-D15 data busn",
  1972.                       0, 0, 0, 0, 0, 0);
  1973.             retVal = ERROR;
  1974.             goto despatch;
  1975.             }
  1976.  
  1977. SCSI_MSG("sym895Loopback: Loopback diagnostics "
  1978.                  "successful.n", 0, 0, 0, 0, 0, 0);
  1979.         retVal = OK;
  1980.         }
  1981.     else    /* select without ATN */
  1982.         { 
  1983.         SCSI_MSG ("sym895Loopback: Error ATN not asserted during selectionn",
  1984.                   0, 0, 0, 0, 0, 0);
  1985.         retVal = ERROR;
  1986.         }
  1987. despatch:
  1988.  
  1989.     /* Set the SCSI control lines to Bus free state */
  1990.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
  1991.                        (SYM895_REG8_READ(pSiop,SYM895_OFF_SOCL) & 
  1992.                        ~(SYM895_SOCL_CD | SYM895_SOCL_MSG | SYM895_SOCL_IO)));
  1993.     SYM895_REG8_WRITE ( pSiop, SYM895_OFF_SCNTL2,
  1994.                         SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL2) & 
  1995.                         ~(SYM895_SCNTL2_SDU) );
  1996.     SYM895_REG8_WRITE ( pSiop, SYM895_OFF_SCNTL1,
  1997.                         SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL1) & 
  1998.                         ~(SYM895_SCNTL1_CON) );
  1999.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,0x00);
  2000.   
  2001.     /* Enable manual Start */
  2002.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE, 
  2003.                        (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) | 
  2004.                        SYM895_DMODE_MAN)); 
  2005.     /* Clear off all interrupts. */
  2006.     temp = SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT);
  2007.     sym895Delay();
  2008.     CACHE_PIPE_FLUSH();
  2009.     temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0);    
  2010.     sym895Delay();
  2011.     CACHE_PIPE_FLUSH();
  2012.     temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1); 
  2013.     sym895Delay();
  2014.     CACHE_PIPE_FLUSH();
  2015.     temp = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);
  2016.     /* Set back the initial interrupt enable bits and bring to normal mode */
  2017.  
  2018.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN,  dien);
  2019.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN0, sien0);     
  2020.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN1, sien1);
  2021.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2, stest2);     
  2022.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, dcntl);     
  2023.     /* 
  2024.      * Start the WAIT script.. Again this is needed only if "sym895Loopback" is 
  2025.      * called while any scripts are running. If the WAIT scripts are not 
  2026.      * restarted, all SCSI transactions will be aborted as thread activation 
  2027.      * do not take place.
  2028.      */
  2029.     sym895ScriptStart (pSiop, (SYM895_THREAD *)pScsiCtrl->pIdentThread,
  2030.                        SYM895_SCRIPT_WAIT);  
  2031.     return (retVal);
  2032.     }