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

VxWorks

开发平台:

C/C++

  1. /* ncr810Lib.c - NCR 53C8xx PCI SCSI I/O Processor (SIOP) library (SCSI-2) */
  2. /* Copyright 1989-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02a,26apr02,pmr  SPR 76029: using intLock/intUnlock instead of
  8.  ncr810IntDisable/Restore.
  9. 01z,29oct01,pmr  modified ncr810XferParamsCvt() to update the period parameter
  10.                  with the correct value (SPR 71337).
  11. 01y,24oct01,dat  merge from ae 1.1, lint removal using diab
  12. 01x,20sep01,rcs  Added ncr810IntDisable() and ncr810IntRestore() and used them
  13.                  to replace intLock() / intUnlock() pairs in ncr810Abort(),
  14.                  ncr810Activate(), ncr810Resume(), and ncr810EventTypeGet(). 
  15.                  Also, added CACHE_PIPE_FLUSH() calls where nedded. SPR# 29734 
  16. 01w,21nov00,jkf  Fixed SPR#35801/35403, no NULL pointers if WIDE selected.
  17. 01v,03dec98,ihw  Modified handling of ident message for new thread:
  18.  add normal message out (if any) - e.g. sync/wide xfer.
  19.  Removed incorrect code in ncr810Activate() (used to fudge
  20.  controller state if reselection race occurred). (SPR 24089)
  21.  Added several CACHE_PIPE_FLUSH calls at strategic points.
  22. 01u,06oct98,dat  Fixed illegal device accesses, SPR 22597. Provided by luke.
  23. 01t,24aug98,sut  fixed SPR 21260
  24. 01s,18aug98,tpr  added PowerPC EC 603 support.
  25. 01r,23apr98,tm,  SPR 8384, 9025: Augmented ncr810RemainderGet() to support 
  26.             dds    825/875. inOrderExecute() changed to CACHE_PIPE_FLUSH
  27. 01q,14oct97,dds  SPR 9543, modified "ncr810Intr" to return immediately if a
  28.                  spurious interrupt is detected.
  29. 01p,28jul97,dds  SPR#9015: replaced logMsg with SCSI_INT_DEBUG_MSG.
  30. 01o,10jul97,mas  removed dependency on BSP-specific byte I/O routines.
  31. 01n,09jul97,mas  macros for all I/O; first delay count increased (SPR 8842).
  32. 01m,09jul97,dgp  doc: correct fonts per SPR 7853
  33. 01l,08may97,dat  temp fix for SPR 8540, VIRT_TO_PHYS problem
  34. 01k,10mar97,dds  SPR 7766: added changes for ncr875 SCSI adapter.
  35. 01j,06mar97,dds  SPR 7996/8091: added a delay to configure scsi devices
  36.                  when used with a fast processor.
  37. 01i,20nov96,myz  added CACHE_DMA_VIRT_TO_PHYS for those missing
  38. 01h,29oct96,dgp  doc: editing for newly published SCSI libraries
  39. 01g,19aug96,dds  modified to generate man pages.
  40. 01f,29jul96,jds  added inOrderExecute() to resolve erratic behaviour when
  41.  instruction cache is turned on.
  42. 01e,25jul96,dds  SPR 6818: documentation correction.
  43. 01d,01may96,jds  more doc tweaks
  44. 01c,22apr96,jds  doc tweaks.
  45. 01b,22apr96,jds  made to work with multiple NCR 8XX controllers. 
  46. 01a,28jun95,jds  Created. Adapted from ncr710Lib.c
  47. */
  48. /*
  49. DESCRIPTION
  50. This is the I/O driver for the NCR 53C8xx PCI SCSI I/O Processors (SIOP),
  51. supporting the NCR 53C810 and the NCR 53C825 SCSI controllers.
  52. It is designed to work with scsiLib and scsi2Lib.  This driver 
  53. runs in conjunction with a script program for the NCR 53C8xx controllers.
  54. These scripts use DMA transfers for all data, messages, and status.
  55. This driver supports cache functions through cacheLib.
  56. USER-CALLABLE ROUTINES
  57. Most of the routines in this driver are accessible only through the I/O
  58. system.  Three routines, however, must be called directly.  ncr810CtrlCreate()
  59. creates a controller structure and ncr810CtrlInit() initializes it.
  60. The NCR 53C8xx hardware registers need to be configured according to
  61. the hardware implementation.  If the default configuration is not correct,
  62. the routine ncr810SetHwRegister() must be used to properly configure
  63. the registers.
  64. PCI MEMORY ADDRESSING
  65. The global variable ncr810PciMemOffset was created to provide the BSP
  66. with a means of changing the VIRT_TO_PHYS mapping without changing the
  67. functions in the cacheFuncs structures.  In generating physical addresses
  68. for DMA on the PCI bus, local addresses are passed through the function
  69. CACHE_DMA_VIRT_TO_PHYS and then the value of ncr810PciMemOffset is added.
  70. For backward compatibility, the initial value of ncr810PciMemOffset comes
  71. from the macro PCI_TO_MEM_OFFSET defined in ncr810.h.
  72. I/O MACROS
  73. All device access for input and output is done via macros which can be
  74. customized for each BSP.  These routines are NCR810_IN_BYTE, NCR810_OUT_BYTE,
  75. NCR810_IN_16, NCR810_OUT_16, NCR810_IN_32 and NCR810_OUT_32.
  76. By default, these are defined as generic memory references.
  77. INTERNAL
  78. This driver supports multiple initiators, disconnect/reconnect, tagged
  79. command queueing and synchronous data transfer protocol.  In general, the
  80. SCSI system and this driver will automatically choose the best combination
  81. of these features to suit the target devices used.  However, the default
  82. choices may be over-ridden by using the function "scsiTargetOptionsSet()"
  83. (see scsiLib).
  84. There are debug variables to trace events in the driver.
  85. <scsiDebug> scsiLib debug variable, trace event in scsiLib, ncr810ScsiPhase(),
  86. and ncr810Transact().
  87. <scsiIntsDebug> prints interrupt informations.
  88. INCLUDE FILES
  89. ncr810.h, ncr810Script.h and scsiLib.h
  90. SEE ALSO: scsiLib, scsi2Lib, cacheLib, 
  91. .I "SYM53C825 PCI-SCSI I/O Processor Data Manual,"
  92. .I "SYM53C810 PCI-SCSI I/O Processor Data Manual," 
  93. .I "NCR 53C8XX Family PCI-SCSI I/O Processors Programming Guide,"
  94. .pG "I/O System"
  95. */
  96. #define  INCLUDE_SCSI2
  97. #include "vxWorks.h"
  98. #include "memLib.h"
  99. #include "ctype.h"
  100. #include "stdlib.h"
  101. #include "string.h"
  102. #include "stdio.h"
  103. #include "logLib.h"
  104. #include "semLib.h"
  105. #include "intLib.h"
  106. #include "errnoLib.h"
  107. #include "cacheLib.h"
  108. #include "taskLib.h"
  109. #include "drv/scsi/ncr810.h"
  110. #include "drv/scsi/ncr810Script.h"
  111. /* defines */
  112. #define SIOP_MAX_XFER_LENGTH   ((UINT) (0x00ffffff)) /* max data xfer length */
  113. /* I/O macros */
  114. #if ((CPU==PPC603) || (CPU == PPCEC603) || (CPU==PPC604))
  115. # undef CACHE_PIPE_FLUSH
  116. extern void  vxEieio (void);
  117. # define CACHE_PIPE_FLUSH() vxEieio()
  118. #endif
  119. #ifndef NCR810_IN_BYTE
  120. # define NCR810_IN_BYTE(adr)       (*(volatile UINT8 *)(adr))
  121. #endif
  122. #ifndef NCR810_OUT_BYTE
  123. # define NCR810_OUT_BYTE(adr,val)  (*(volatile UINT8 *)(adr)) = ((UINT8)(val))
  124. #endif
  125. #ifndef NCR810_IN_16
  126. # define NCR810_IN_16(adr)      (NCR810_SWAP_16(*(volatile UINT16 *)(adr)))
  127. #endif
  128. #ifndef NCR810_OUT_16
  129. # define NCR810_OUT_16(adr,val) (*(volatile UINT16 *)(adr)) = NCR810_SWAP_16((UINT)(val))
  130. #endif
  131. #ifndef NCR810_IN_32
  132. # define NCR810_IN_32(adr)      (NCR810_SWAP_32(*(UINT *)(adr)))
  133. #endif
  134. #ifndef NCR810_OUT_32
  135. # define NCR810_OUT_32(adr,val) (*(volatile UINT *)(adr)) = NCR810_SWAP_32((UINT)(val))
  136. #endif
  137. #define NCR810_VIRT_TO_PHYS(x) 
  138. ((UINT)CACHE_DMA_VIRT_TO_PHYS(x) + (UINT)ncr810PciMemOffset)
  139. /* Data stream swapping macros */
  140. #if (_BYTE_ORDER == _BIG_ENDIAN)
  141. #   define NCR810_SWAP_32(x)     LONGSWAP((UINT)x)
  142. #   define NCR810_SWAP_16(x)     ((LSB(x) << 8) | MSB(x))
  143. #else
  144. #   define NCR810_SWAP_32(x)    (x)
  145. #   define NCR810_SWAP_16(x)    (x)
  146. #endif 
  147. /* typedefs */
  148. typedef NCR_810_SCSI_CTRL SIOP;
  149. /* External */
  150. IMPORT BOOL scsiDebug;
  151. IMPORT BOOL scsiErrors;
  152. IMPORT BOOL scsiIntsDebug;
  153. /* Global variables */
  154. int delayCount=0;
  155. int ncr810DelayCount = 10;
  156. int ncr810PciMemOffset = (int)PCI_TO_MEM_OFFSET;
  157. /*
  158.  *  Configurable options
  159.  */
  160. int ncr810SingleStepSemOptions = SEM_Q_PRIORITY;
  161. char* ncr810ScsiTaskName      = SCSI_DEF_TASK_NAME;
  162. int   ncr810ScsiTaskOptions   = SCSI_DEF_TASK_OPTIONS;
  163. int   ncr810ScsiTaskPriority  = SCSI_DEF_TASK_PRIORITY;
  164. int   ncr810ScsiTaskStackSize = SCSI_DEF_TASK_STACK_SIZE;
  165. /* forward declarations */
  166. LOCAL void   ncr810HwInit        (SIOP *pSiop);
  167. LOCAL int    ncr810BusIdGet      (SIOP *pSiop, UINT busIdBits);
  168. LOCAL UINT   ncr810RemainderGet  (SIOP *pSiop, UINT phase);
  169. LOCAL int    ncr810EventTypeGet  (SIOP *pSiop);
  170. LOCAL STATUS ncr810PhaseMismatch (NCR810_THREAD * pThread,
  171.   int             phase,
  172.   UINT            remCount);
  173. LOCAL STATUS ncr810ScsiBusControl (SIOP *pSiop, int operation);
  174. LOCAL void   ncr810ScsiBusReset   (SIOP *pSiop);
  175. LOCAL STATUS ncr810ThreadActivate (SIOP *pSiop, NCR810_THREAD *pThread);
  176. LOCAL BOOL   ncr810ThreadAbort    (SIOP *pSiop, NCR810_THREAD *pThread);
  177. LOCAL void   ncr810Event          (SIOP *pSiop, NCR810_EVENT  *pEvent);
  178. LOCAL void   ncr810ThreadEvent   (NCR810_THREAD *pThread, NCR810_EVENT *pEvent);
  179. LOCAL void   ncr810InitEvent     (NCR810_THREAD *pThread, NCR810_EVENT *pEvent);
  180. LOCAL void   ncr810InitIdentEvent(NCR810_THREAD *pThread, NCR810_EVENT *pEvent);
  181. LOCAL void   ncr810TargIdentEvent(NCR810_THREAD *pThread, NCR810_EVENT *pEvent);
  182. LOCAL void   ncr810IdentInContinue (NCR810_THREAD *pThread);
  183. LOCAL void   ncr810ThreadReconnect (NCR810_THREAD *pThread);
  184. LOCAL void   ncr810SharedMemInit   (SIOP *pSiop, NCR810_SHARED *pShMem);
  185. LOCAL STATUS ncr810ThreadInit      (SIOP *pSiop, NCR810_THREAD *pThread);
  186. LOCAL STATUS ncr810IdentThreadInit (NCR810_THREAD *pThread);
  187. LOCAL void   ncr810ThreadUpdate    (NCR810_THREAD *pThread);
  188. LOCAL void   ncr810ThreadComplete  (NCR810_THREAD *pThread);
  189. LOCAL void   ncr810ThreadDefer     (NCR810_THREAD *pThread);
  190. LOCAL void   ncr810ThreadFail      (NCR810_THREAD *pThread, int errNum);
  191. LOCAL void   ncr810ThreadStateSet  (NCR810_THREAD *pThread,
  192.     SCSI_THREAD_STATE state);
  193. LOCAL STATUS ncr810Activate      (SIOP               *pSiop,
  194.   NCR810_THREAD      *pThread);
  195. LOCAL STATUS ncr810Resume        (SIOP               *pSiop,
  196.   NCR810_THREAD      *pThread,
  197.   NCR810_SCRIPT_ENTRY entryId);
  198. LOCAL void   ncr810Abort         (SIOP               *pSiop);
  199. LOCAL void   ncr810ScriptStart   (SIOP               *pSiop,
  200.   NCR810_THREAD      *pThread,
  201.   NCR810_SCRIPT_ENTRY entryId);
  202. LOCAL STATUS ncr810ThreadParamsSet (NCR810_THREAD * pThread,
  203.     UINT8      offset,
  204.     UINT8      period);
  205. LOCAL STATUS ncr810XferParamsQuery (SCSI_CTRL *pScsiCtrl,
  206.     UINT8     *pOffset,
  207.     UINT8     *pPeriod);
  208. LOCAL STATUS ncr810WideXferParamsQuery (SCSI_CTRL *pScsiCtrl,
  209.      UINT8     *xferWidth);
  210. LOCAL STATUS ncr810XferParamsSet   (SCSI_CTRL *pScsiCtrl,
  211.     UINT8      offset,
  212.     UINT8      period);
  213. LOCAL STATUS ncr810WideXferParamsSet   (SCSI_CTRL *pScsiCtrl,
  214.         UINT8      wideXfer);
  215. LOCAL BOOL   ncr810XferParamsCvt   (SIOP  *pSiop,
  216.     UINT8 *pOffset,
  217.     UINT8 *pPeriod,
  218.     UINT8 *pXferParams,
  219.     UINT8 *pClockDiv);
  220. LOCAL void   ncr810Delay (void);
  221. LOCAL void   ncr810ResetAtn (SCSI_CTRL *pScsiCtrl);
  222. /*******************************************************************************
  223. *
  224. * ncr810CtrlCreate - create a control structure for the NCR 53C8xx SIOP
  225. *
  226. * This routine creates an SIOP data structure and must be called before
  227. * using an SIOP chip.  It must be called exactly once for a 
  228. * specified SIOP controller. Since it allocates memory for a structure needed 
  229. * by all routines in ncr810Lib, it must be called before any other 
  230. * routines in the library. After calling this routine, ncr810CtrlInit() 
  231. * must be called at least once before any SCSI transactions are 
  232. * initiated using the SIOP.
  233. *
  234. * A detailed description of the input parameters follows:
  235. * .iP <baseAdrs>
  236. * the address at which the CPU accesses the lowest (SCNTL0/SIEN)
  237. * register of the SIOP.
  238. * .iP <clkPeriod>
  239. * the period of the SIOP SCSI clock input, in nanoseconds, multiplied
  240. * by 100.  This is used to determine the clock period for the
  241. * SCSI core of the chip and affects the timing of both asynchronous
  242. * and synchronous transfers.
  243. * Several commonly-used values are defined in ncr810.h as follows:
  244. *.CS
  245. * NCR810_1667MHZ  6000    /@ 16.67Mhz chip @/
  246. * NCR810_20MHZ    5000    /@ 20Mhz chip    @/
  247. * NCR810_25MHZ    4000    /@ 25Mhz chip    @/
  248. * NCR810_3750MHZ  2667    /@ 37.50Mhz chip @/
  249. * NCR810_40MHZ    2500    /@ 40Mhz chip    @/
  250. * NCR810_50MHZ    2000    /@ 50Mhz chip    @/
  251. * NCR810_66MHZ    1515    /@ 66Mhz chip    @/
  252. * NCR810_6666MHZ  1500    /@ 66.66Mhz chip @/
  253. *.CE
  254. * .iP <devType>
  255. * the specific NCR 8xx device type. Current device types
  256. * are defined in the header file ncr810.h.
  257. *
  258. * RETURNS: A pointer to the NCR_810_SCSI_CTRL structure, or NULL if memory 
  259. * is unavailable or there are invalid parameters.
  260. */
  261. NCR_810_SCSI_CTRL *ncr810CtrlCreate 
  262.     (
  263.     UINT8 *baseAdrs, /* base address of the SIOP */
  264.     UINT   clkPeriod, /* clock controller period (nsec*100) */
  265.     UINT16 devType /* NCR8XX SCSI device type */
  266.     )
  267.     {
  268.     FAST SIOP *pSiop;     /* ptr to SIOP info */
  269.     int        nBytes;          /* total amount of cache-coherent memory */
  270.     SCSI_CTRL *pScsiCtrl;
  271.     BOOL       wideXfer;
  272.     static NCR810_HW_REGS ncr810HwRegs = DEFAULT_810_HW_REGS;
  273.     /* verify parameters */
  274.     if (baseAdrs == ((UINT8 *) NULL))
  275. return ((SIOP *) NULL);
  276.     
  277.     if ((clkPeriod > NCR810_1667MHZ) ||  
  278.         (clkPeriod < NCR810_6666MHZ))
  279.         return ((SIOP *) NULL);
  280.     
  281.     /* check that dma buffers are cache-coherent */
  282.     if (!CACHE_DMA_IS_WRITE_COHERENT () ||
  283. !CACHE_DMA_IS_READ_COHERENT ())
  284. {
  285. SCSI_MSG ("ncr810CtrlCreate: shared memory not cache coherent.n",
  286.   0, 0, 0, 0, 0, 0);
  287.         return ((SIOP *) NULL);
  288. }
  289.     /* check to see if it is a supported NCR8XX device type */
  290.     switch (devType)
  291.         {
  292.         case NCR810_DEVICE_ID :
  293.             wideXfer = FALSE;
  294.             break;
  295.             
  296.         case NCR825_DEVICE_ID :
  297.             wideXfer = TRUE;
  298.             break;
  299.         case NCR875_DEVICE_ID :
  300.             wideXfer = TRUE;
  301.             break;
  302.         default:
  303.             logMsg ("Invalid NCR8XX device type. Not supported.n",
  304. 0, 0, 0, 0, 0, 0);
  305.             return ((SIOP *) NULL);
  306.         }
  307.     /* cacheDmaMalloc the controller info structure and two shared data areas */
  308.     nBytes = sizeof (SIOP) + 2 * sizeof (NCR810_SHARED);
  309.     if ((pSiop = (SIOP *) cacheDmaMalloc (nBytes)) == (SIOP *) NULL)
  310.         return ((SIOP *) NULL);
  311.     bzero ((char *) pSiop, nBytes);
  312.     pSiop->pIdentShMem  = (NCR810_SHARED *) (pSiop + 1);
  313.     pSiop->pClientShMem = pSiop->pIdentShMem + 1;
  314.     /* set up configuration variables */
  315.     pScsiCtrl = (SCSI_CTRL *) pSiop;
  316.     
  317.     pScsiCtrl->eventSize  = sizeof (NCR810_EVENT);
  318.     pScsiCtrl->threadSize = sizeof (NCR810_THREAD);
  319.     /* fill in virtual functions used by SCSI library */
  320.     
  321.     pScsiCtrl->maxBytesPerXfer = SIOP_MAX_XFER_LENGTH;
  322.     pScsiCtrl->scsiTransact = (FUNCPTR) scsiTransact;
  323.     pScsiCtrl->scsiEventProc       = (VOIDFUNCPTR) ncr810Event;
  324.     pScsiCtrl->scsiThreadInit      = (FUNCPTR)     ncr810ThreadInit;
  325.     pScsiCtrl->scsiThreadActivate  = (FUNCPTR)     ncr810ThreadActivate;
  326.     pScsiCtrl->scsiThreadAbort     = (FUNCPTR)     ncr810ThreadAbort;
  327.     pScsiCtrl->scsiBusControl      = (FUNCPTR)     ncr810ScsiBusControl;
  328.     pScsiCtrl->scsiXferParamsQuery = (FUNCPTR)     ncr810XferParamsQuery;
  329.     pScsiCtrl->scsiXferParamsSet   = (FUNCPTR)     ncr810XferParamsSet;
  330.     pScsiCtrl->scsiWideXferParamsQuery = (FUNCPTR) ncr810WideXferParamsQuery;
  331.     pScsiCtrl->scsiWideXferParamsSet   = (FUNCPTR) ncr810WideXferParamsSet;
  332.     /* the following virtual functions are not used with the NCR 53C810 */
  333.     
  334.     pScsiCtrl->scsiDevSelect = NULL;
  335.     pScsiCtrl->scsiInfoXfer  = NULL;
  336.     /* 
  337.      * The default scsiLib behaviour is to turn wide transfers off. However
  338.      * for the NCR825, the default behaviour should be to turn wide transfers 
  339.      * on. It is still possible to turn off / on wide transfers for individual 
  340.      * physical devices via the scsiTargetOptionsSet() routine defined
  341.      * by scsiLib.
  342.      */
  343.     pScsiCtrl->wideXfer = wideXfer;
  344.     /* fill in generic SCSI info for this controller */
  345.     scsiCtrlInit (&pSiop->scsiCtrl);
  346.     /* fill in SIOP specific data for this controller */
  347.     pSiop->pScntl0    = baseAdrs + OFF_SCNTL0;
  348.     pSiop->pScntl1    = baseAdrs + OFF_SCNTL1;
  349.     pSiop->pScntl2    = baseAdrs + OFF_SCNTL2;
  350.     pSiop->pScntl3    = baseAdrs + OFF_SCNTL3;
  351.     pSiop->pScid      = baseAdrs + OFF_SCID;
  352.     pSiop->pSxfer     = baseAdrs + OFF_SXFER;
  353.     pSiop->pSdid      = baseAdrs + OFF_SDID;
  354.     pSiop->pGpreg     = baseAdrs + OFF_GPREG;
  355.     pSiop->pSfbr      = baseAdrs + OFF_SFBR;
  356.     pSiop->pSocl      = baseAdrs + OFF_SOCL;
  357.     pSiop->pSsid      = baseAdrs + OFF_SSID;
  358.     pSiop->pSbcl      = baseAdrs + OFF_SBCL;
  359.     pSiop->pDstat     = baseAdrs + OFF_DSTAT;
  360.     pSiop->pSstat0    = baseAdrs + OFF_SSTAT0;
  361.     pSiop->pSstat1    = baseAdrs + OFF_SSTAT1;
  362.     pSiop->pSstat2    = baseAdrs + OFF_SSTAT2;
  363.     pSiop->pDsa       = (UINT *) (baseAdrs + OFF_DSA);
  364.     pSiop->pIstat     = baseAdrs + OFF_ISTAT;
  365.     pSiop->pCtest0    = baseAdrs + OFF_CTEST0;
  366.     pSiop->pCtest1    = baseAdrs + OFF_CTEST1;
  367.     pSiop->pCtest2    = baseAdrs + OFF_CTEST2;
  368.     pSiop->pCtest3    = baseAdrs + OFF_CTEST3;
  369.     pSiop->pTemp      = (UINT *) (baseAdrs + OFF_TEMP);
  370.     pSiop->pDfifo     = baseAdrs + OFF_DFIFO;
  371.     pSiop->pCtest4    = baseAdrs + OFF_CTEST4;
  372.     pSiop->pCtest5    = baseAdrs + OFF_CTEST5;
  373.     pSiop->pCtest6    = baseAdrs + OFF_CTEST6;
  374.     pSiop->pDbc       = (UINT *) (baseAdrs + OFF_DBC);
  375.     pSiop->pDcmd      = baseAdrs + OFF_DCMD;
  376.     pSiop->pDnad      = (UINT *) (baseAdrs + OFF_DNAD);
  377.     pSiop->pDsp       = (UINT *) (baseAdrs + OFF_DSP);
  378.     pSiop->pDsps      = (UINT *) (baseAdrs + OFF_DSPS);
  379.     pSiop->pScratcha0 = baseAdrs + OFF_SCRATCHA0;
  380.     pSiop->pScratcha1 = baseAdrs + OFF_SCRATCHA1;
  381.     pSiop->pScratcha2 = baseAdrs + OFF_SCRATCHA2;
  382.     pSiop->pScratcha3 = baseAdrs + OFF_SCRATCHA3;
  383.     pSiop->pDmode     = baseAdrs + OFF_DMODE;
  384.     pSiop->pDien      = baseAdrs + OFF_DIEN;
  385.     pSiop->pDwt       = baseAdrs + OFF_DWT;
  386.     pSiop->pDcntl     = baseAdrs + OFF_DCNTL;
  387.     pSiop->pAdder     = (UINT *) (baseAdrs + OFF_ADDER);
  388.     pSiop->pSien0     = baseAdrs + OFF_SIEN0;
  389.     pSiop->pSien1     = baseAdrs + OFF_SIEN1;
  390.     pSiop->pSist0     = baseAdrs + OFF_SIST0;
  391.     pSiop->pSist1     = baseAdrs + OFF_SIST1;
  392.     pSiop->pSlpar     = baseAdrs + OFF_SLPAR;
  393.     pSiop->pMacntl    = baseAdrs + OFF_MACNTL;
  394.     pSiop->pGpcntl    = baseAdrs + OFF_GPCNTL;
  395.     pSiop->pStime0    = baseAdrs + OFF_STIME0;
  396.     pSiop->pStime1    = baseAdrs + OFF_STIME1;
  397.     pSiop->pRespid    = baseAdrs + OFF_RESPID;
  398.     pSiop->pStest0    = baseAdrs + OFF_STEST0;
  399.     pSiop->pStest1    = baseAdrs + OFF_STEST1;
  400.     pSiop->pStest2    = baseAdrs + OFF_STEST2;
  401.     pSiop->pStest3    = baseAdrs + OFF_STEST3;
  402.     pSiop->pSidl      = (UINT16 *) (baseAdrs + OFF_SIDL);
  403.     pSiop->pSodl      = (UINT16 *) (baseAdrs + OFF_SODL);
  404.     pSiop->pSbdl      = (UINT16 *) (baseAdrs + OFF_SBDL);
  405.     pSiop->pScratchb  = (UINT *) (baseAdrs + OFF_SCRATCHB);
  406.     pSiop->devType   = devType;
  407.     pSiop->clkPeriod = clkPeriod;
  408.     /*
  409.      * Initialise hardware-dependent registers to default values.
  410.      */
  411.     bcopy ((char *)&ncr810HwRegs, (char *)&pSiop->hwRegs,
  412.                           sizeof (NCR810_HW_REGS));
  413.     /*
  414.      * Create synchronisation semaphore for single-step support
  415.      */
  416.     if ((pSiop->singleStepSem = semBCreate(ncr810SingleStepSemOptions,
  417.    SEM_EMPTY)) == NULL)
  418. {
  419. SCSI_MSG ("ncr810CtrlCreate: semBCreate of singleStepSem failed.n"
  420.   ,0, 0, 0, 0, 0, 0);
  421. goto failed;
  422.         }
  423.     /*
  424.      * Initialise controller state variables
  425.      */
  426.     pSiop->state      = NCR810_STATE_IDLE;
  427.     pSiop->cmdPending = FALSE;
  428.     /*
  429.      * Initialize fixed fields in client shared data area
  430.      */
  431.     ncr810SharedMemInit (pSiop, pSiop->pClientShMem);
  432.     /*
  433.      * Identification thread has been created by the generic initialisation.
  434.      * Initialise it for use with the NCR 53C810.
  435.      */
  436.     ncr810IdentThreadInit ((NCR810_THREAD *) pScsiCtrl->pIdentThread);
  437.     /* spawn SCSI manager - use generic code from "scsiLib.c" */
  438.     pScsiCtrl->scsiMgrId = taskSpawn (ncr810ScsiTaskName,
  439.                    ncr810ScsiTaskPriority,
  440.                    ncr810ScsiTaskOptions,
  441.                    ncr810ScsiTaskStackSize,
  442.                    (FUNCPTR) scsiMgr,
  443.                    (int) pSiop, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  444.     if (pScsiCtrl->scsiMgrId == ERROR)
  445. {
  446. SCSI_MSG ("ncr810CtrlCreate: can't spawn SCSI manager taskn",
  447.   0, 0, 0, 0, 0, 0);
  448. goto failed;
  449. }
  450.     return (pSiop);
  451. failed:
  452.     if (pSiop->singleStepSem != NULL)
  453. (void) semDelete (pSiop->singleStepSem);
  454.     (void) cacheDmaFree ((char *) pSiop);
  455.     
  456.     return (NULL);
  457.     }
  458. /*******************************************************************************
  459. *
  460. * ncr810CtrlInit - initialize a control structure for the NCR 53C8xx SIOP
  461. *
  462. * This routine initializes an SIOP structure, after the structure is created
  463. * with ncr810CtrlCreate().  This structure must be initialized before the
  464. * SIOP can be used.  It may be called more than once if needed;  however,
  465. * it must only be called while there is no activity on the SCSI interface.
  466. *
  467. * A detailed description of the input parameters follows:
  468. * .iP <pSiop>
  469. * a pointer to the NCR_810_SCSI_CTRL structure created with
  470. * ncr810CtrlCreate().
  471. * .iP <scsiCtrlBusId>
  472. * the SCSI bus ID of the SIOP.  Its value is somewhat arbitrary:  seven (7),
  473. * or highest priority, is conventional.  The value must be in the range 0 - 7.
  474. *
  475. * RETURNS: OK, or ERROR if parameters are out of range.
  476. */
  477. STATUS ncr810CtrlInit
  478.     (
  479.     FAST NCR_810_SCSI_CTRL *pSiop,  /* ptr to SIOP struct */
  480.     int scsiCtrlBusId     /* SCSI bus ID of this SIOP */
  481.     )
  482.     {
  483.     SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop;
  484.     volatile int delay;
  485.     /*
  486.      * Validate parameters
  487.      */
  488.     if (pSiop == (SIOP *)NULL)
  489. return (ERROR);
  490.     /*
  491.      * Validate and set bus ID
  492.      */
  493.     if (scsiCtrlBusId < SCSI_MIN_BUS_ID || scsiCtrlBusId > SCSI_MAX_BUS_ID)
  494. return (ERROR);
  495.     
  496.     pScsiCtrl->scsiCtrlBusId = scsiCtrlBusId;
  497.     /*
  498.      * Initialise the SIOP
  499.      */
  500.     ncr810HwInit (pSiop);
  501.     delay = ncr810DelayCount;
  502.     ncr810DelayCount *= 35; /* First delay must be longer */
  503.     ncr810ScriptStart (pSiop,
  504.        (NCR810_THREAD *) pScsiCtrl->pIdentThread,
  505.        NCR810_SCRIPT_WAIT);
  506.     pSiop->state = NCR810_STATE_PASSIVE;
  507.     ncr810DelayCount = delay; /* Restore original delay count */
  508.     return (OK);
  509.     }
  510. /*******************************************************************************
  511. *
  512. * ncr810HwInit - initialize the SIOP chip to a known state
  513. *
  514. * This routine puts the SIOP into a known quiescent state.  Because the value
  515. * of some registers depend upon the hardware implementation of the chip you 
  516. * may have to use ncr810SetHwRegister() to adjust them.
  517. *
  518. * This routine does not touch the bits in registers that are set by 
  519. * the ncr810SetHwRegister() routine.
  520. *
  521. * See the NCR 53C810 Data Manual for fuller details of the registers
  522. * programmed by this routine.
  523. *
  524. * SEE ALSO 
  525. * ncr810SetHwRegister()
  526. *
  527. * NOMANUAL
  528. */
  529. LOCAL void ncr810HwInit
  530.     (
  531.     FAST SIOP *pSiop /* ptr to an SIOP info structure */
  532.     )
  533.     {
  534.     UINT clkPeriod;
  535.     /*
  536.      * Software reset the SIOP
  537.      */
  538.     NCR810_OUT_BYTE(pSiop->pIstat, ISTAT_SOFTRST);
  539.     taskDelay (2);
  540.     NCR810_OUT_BYTE(pSiop->pIstat, 0);  /* clear the software reset */
  541.     /*
  542.      * Initialise hardware-dependent registers
  543.      */
  544.     ncr810SetHwRegister (pSiop, &pSiop->hwRegs);
  545.     /*
  546.      * DMA mode, control and watchdog timer registers
  547.      *
  548.      * Use manual start and NCR 53C700 compatibility mode.
  549.      * Set clock conversion factor (the clkPeriod has been checked in
  550.      * "ncr810CtrlCreate()") and save async clock period for use by
  551.      * "ncr810XferParamsCvt()".  Disable the watchdog timer.
  552.      *
  553.      * Note:
  554.      * Manual Start Mode. Setting this bit prevents automatic fetching and
  555.      * execution of scripts when the DSP register is written.
  556.      */
  557.     CACHE_PIPE_FLUSH();
  558.     NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) | DMODE_MAN);
  559.     /* NCR 53C700 Compatability is turned off */
  560.     CACHE_PIPE_FLUSH();
  561.     NCR810_OUT_BYTE(pSiop->pDcntl, NCR810_IN_BYTE(pSiop->pDcntl) | DCNTL_COM);
  562.     clkPeriod = pSiop->clkPeriod;
  563.     if (clkPeriod >= NCR810_25MHZ)             /* 16.67 - 25.00 MHz */
  564.      {
  565. /* set the async and sync period to be the same */
  566.         pSiop->clkDiv = NCR810_16MHZ_ASYNC_DIV;
  567.         NCR810_OUT_BYTE(pSiop->pScntl3, NCR810_16MHZ_ASYNC_DIV);
  568.      }
  569.     else if (clkPeriod >= NCR810_3750MHZ)         /* 25.01 - 37.50 MHz */
  570.      {
  571. /* set the async and sync period to be the same */
  572.         pSiop->clkDiv = NCR810_25MHZ_ASYNC_DIV;
  573.         NCR810_OUT_BYTE(pSiop->pScntl3, NCR810_25MHZ_ASYNC_DIV);
  574.      }
  575.     else if (clkPeriod >= NCR810_50MHZ)      /* 37.51 - 50.00 MHz */
  576.      {
  577. /* set the async and sync period to be the same */
  578.         pSiop->clkDiv = NCR810_50MHZ_ASYNC_DIV;
  579.         NCR810_OUT_BYTE(pSiop->pScntl3, NCR810_50MHZ_ASYNC_DIV);
  580.      }
  581.     else /* (clkPeriod >= NCR810_6666MHZ) */      /* 50.01 - 66.67 MHz */
  582.      {
  583. /* set the async and sync period to be the same */
  584.         pSiop->clkDiv = NCR810_66MHZ_ASYNC_DIV;
  585.         NCR810_OUT_BYTE(pSiop->pScntl3, NCR810_66MHZ_ASYNC_DIV);
  586.      }
  587.     /*
  588.      * SCSI control registers
  589.      *
  590.      * If disconnect/reconnect is enabled, use full arbitration.
  591.      * Always generate parity; check for parity if required to do so.
  592.      * Set slow cable mode if specified.
  593.      */
  594.     if (pSiop->scsiCtrl.disconnect) 
  595. {
  596.         CACHE_PIPE_FLUSH();
  597.         NCR810_OUT_BYTE(pSiop->pScntl0, NCR810_IN_BYTE(pSiop->pScntl0) |
  598.                         (SCNTL0_ARB1 | SCNTL0_ARB0)); /* full arbitration */
  599. }
  600.    
  601.     /* Enable select with attention */
  602.     CACHE_PIPE_FLUSH();
  603.     NCR810_OUT_BYTE(pSiop->pScntl0, NCR810_IN_BYTE(pSiop->pScntl0) |
  604.                     SCNTL0_WATN);
  605. #if FALSE
  606.     /* Parity not supported yet */
  607.     if (pSiop->parityCheckEnbl)
  608.         {
  609.         CACHE_PIPE_FLUSH();
  610.         NCR810_OUT_BYTE(pSiop->pScntl0, NCR810_IN_BYTE(pSiop->pScntl0) |
  611.                         B_EPC); /* Enable parity checking */
  612.         }
  613. #endif
  614.      
  615.     /*
  616.      * Set own SCSI bus ID (checked in "ncr810CtrlInit()")
  617.      */
  618.     CACHE_PIPE_FLUSH();
  619.     NCR810_OUT_BYTE(pSiop->pScid, NCR810_IN_BYTE(pSiop->pScid) |
  620.                     pSiop->scsiCtrl.scsiCtrlBusId);
  621.    
  622.     NCR810_OUT_BYTE(pSiop->pRespid, (1 << pSiop->scsiCtrl.scsiCtrlBusId));
  623.     /* Enable response to bus initiated selection and reselection */
  624.     CACHE_PIPE_FLUSH();
  625.     NCR810_OUT_BYTE(pSiop->pScid, NCR810_IN_BYTE(pSiop->pScid) |
  626.                     SCID_RRE | SCID_SRE);
  627.     /*
  628.      * Enable relevant SCSI and DMA interrupts (see "ncr810EventTypeGet()")
  629.      *
  630.      * Note: in target mode the phase mismatch interrupt (B_MA) is used to
  631.      * signal assertion of ATN.  Currently we cannot handle this either in
  632.      * this library or in the script.  Therefore, the script automatically
  633.      * disables this interrupt in target mode and enables it (for phase
  634.      * mismatch) in initiator mode.  Also see "ncr810EventTypeGet()".
  635.      */
  636.     NCR810_OUT_BYTE(pSiop->pSien0, (B_SGE | B_UDC | B_RST | B_PAR)); 
  637.     NCR810_OUT_BYTE(pSiop->pSien1, (B_STO | B_HTH)); 
  638.     NCR810_OUT_BYTE(pSiop->pDien,  (B_BF | B_ABT | B_SIR | B_IID));
  639.     /* CTEST registers to set in order to get the right initialisation */
  640.     CACHE_PIPE_FLUSH();
  641.     NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) |CTEST3_CLF);
  642.     }
  643. /*******************************************************************************
  644. *
  645. * ncr810SetHwRegister - set hardware-dependent registers for the NCR 53C8xx SIOP
  646. *
  647. * This routine sets up the registers used in the hardware
  648. * implementation of the chip.  Typically, this routine is called by 
  649. * the sysScsiInit() routine from the BSP. 
  650. *
  651. * The input parameters are as follows:
  652. * .iP <pSiop> 4
  653. * a pointer to the NCR_810_SCSI_CTRL structure created with
  654. * ncr810CtrlCreate().
  655. * .iP <pHwRegs>
  656. * a pointer to a NCR810_HW_REGS structure that is filled with the logical
  657. * values 0 or 1 for each bit of each register described below.
  658. *
  659. * This routine includes only the bit registers that can be used to modify 
  660. * the behavior of the chip. The default configuration used during 
  661. * ncr810CtlrCreate() and ncr810CrtlInit() is {0,0,0,0,0,1,0,0,0,0,0}.
  662. *
  663. *.CS
  664. * typedef struct
  665. *   {
  666. *   int stest1Bit7;             /@ Disable external SCSI clock  @/
  667. *   int stest2Bit7;             /@ SCSI control enable          @/
  668. *   int stest2Bit5;             /@ Enable differential SCSI bus @/
  669. *   int stest2Bit2;             /@ Always WIDE SCSI             @/
  670. *   int stest2Bit1;             /@ Extend SREQ/SACK filtering   @/
  671. *   int stest3Bit7;             /@ TolerANT enable              @/
  672. *   int dmodeBit7;              /@ Burst Length transfer bit 1  @/
  673. *   int dmodeBit6;              /@ Burst Length transfer bit 0  @/
  674. *   int dmodeBit5;              /@ Source I/O memory enable     @/
  675. *   int dmodeBit4;              /@ Destination I/O memory enable@/
  676. *   int scntl1Bit7;             /@ Slow cable mode              @/
  677. *   } NCR810_HW_REGS;
  678. *
  679. *.CE
  680. * For a more detailed explanation of the register bits, see the appropriate 
  681. * NCR 53C8xx data manuals.
  682. *
  683. * NOTE
  684. * Because this routine writes to the NCR 53C8xx chip registers, it cannot be
  685. * used when there is any SCSI bus activity.
  686. *
  687. * RETURNS: OK, or ERROR if any input parameter is NULL 
  688. *
  689. * SEE ALSO: ncr810.h, ncr810CtlrCreate()
  690. */
  691. STATUS ncr810SetHwRegister
  692.     (
  693.     FAST SIOP    *pSiop, /* pointer to SIOP info */
  694.     NCR810_HW_REGS *pHwRegs     /* pointer to a NCR810_HW_REGS info */
  695.     )
  696.     {
  697.     /* check input parameters */
  698.     if ((pSiop == NULL) || (pHwRegs == NULL))
  699. return (ERROR);
  700.     /* fill the SIOP structure with new parameters */
  701.     bcopy ((char *)pHwRegs, (char *) &pSiop->hwRegs, sizeof(NCR810_HW_REGS));
  702.     /* Set each bit register to the new value */
  703.     ((pHwRegs->stest1Bit7) ?
  704.      (NCR810_OUT_BYTE(pSiop->pStest1, NCR810_IN_BYTE(pSiop->pStest1) |
  705.       STEST1_SCLK)) :
  706.      (NCR810_OUT_BYTE(pSiop->pStest1, NCR810_IN_BYTE(pSiop->pStest1) &
  707.       ~STEST1_SCLK)));
  708.     ((pHwRegs->stest2Bit7) ?
  709.      (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) |
  710.       STEST2_SCE)) :
  711.      (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) &
  712.       ~STEST2_SCE)));
  713.     /* NCR825 specific initialisation */
  714.     if ((pSiop->devType == NCR825_DEVICE_ID) || 
  715. (pSiop->devType == NCR875_DEVICE_ID))
  716. {
  717.         CACHE_PIPE_FLUSH();
  718.         ((pHwRegs->stest2Bit5) ?
  719.  (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) |
  720.   STEST2_DIF)) :
  721.  (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) &
  722.     ~STEST2_DIF)));
  723.         CACHE_PIPE_FLUSH();
  724.         ((pHwRegs->stest2Bit2) ?
  725.  (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) |
  726.   STEST2_AWS)) :
  727.  (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) &
  728.   ~STEST2_AWS)));
  729.         }
  730.     CACHE_PIPE_FLUSH();
  731.     ((pHwRegs->stest2Bit1) ?
  732.      (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) |
  733.       STEST2_EXT)) :
  734.      (NCR810_OUT_BYTE(pSiop->pStest2, NCR810_IN_BYTE(pSiop->pStest2) &
  735.         ~STEST2_EXT)));
  736.     CACHE_PIPE_FLUSH();
  737.     ((pHwRegs->stest3Bit7) ?
  738.      (NCR810_OUT_BYTE(pSiop->pStest3, NCR810_IN_BYTE(pSiop->pStest3) |
  739.       STEST3_TE)) :
  740.      (NCR810_OUT_BYTE(pSiop->pStest3, NCR810_IN_BYTE(pSiop->pStest3) &
  741.       ~STEST3_TE)));
  742.     CACHE_PIPE_FLUSH();
  743.     ((pHwRegs->dmodeBit7)  ?
  744.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) |
  745.       DMODE_BL1)) :
  746.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) &
  747.       ~DMODE_BL1)));
  748.     CACHE_PIPE_FLUSH();
  749.     ((pHwRegs->dmodeBit6)  ?
  750.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) |
  751.       DMODE_BL0)) :
  752.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) &
  753.       ~DMODE_BL0)));
  754.     CACHE_PIPE_FLUSH();
  755.     ((pHwRegs->dmodeBit5)  ?
  756.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) |
  757.       DMODE_SIOM)) :
  758.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) &
  759.       ~DMODE_SIOM)));
  760.     CACHE_PIPE_FLUSH();
  761.     ((pHwRegs->dmodeBit4)  ?
  762.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) |
  763.       DMODE_DIOM)) :
  764.      (NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) &
  765.       ~DMODE_DIOM)));
  766.     CACHE_PIPE_FLUSH();
  767.     ((pHwRegs->scntl1Bit7) ?
  768.      (NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) |
  769.       SCNTL1_EXC)) :
  770.      (NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) &
  771.       ~SCNTL1_EXC)));
  772.     return (OK);
  773.     }
  774. /*******************************************************************************
  775. *
  776. * ncr810ScsiBusControl - miscellaneous low-level SCSI bus control operations
  777. *
  778. * Currently supports only the SCSI_BUS_RESET operation; other operations are
  779. * not used explicitly by the driver because they are carried out automatically
  780. * by the script program.
  781. *
  782. * NOTE: after the SCSI bus has been reset, the SIOP generates an interrupt
  783. * which causes an NCR810_BUS_RESET event to be sent to the SCSI manager.
  784. * See "ncr810Intr()".
  785. *
  786. * RETURNS: OK, or ERROR if an invalid operation is requested.
  787. *
  788. * NOMANUAL
  789. */
  790. LOCAL STATUS ncr810ScsiBusControl
  791.     (
  792.     SIOP * pSiop,        /* ptr to controller info                   */
  793.     int    operation     /* bitmask for operation(s) to be performed */
  794.     )
  795.     {
  796.     if ((operation & ~SCSI_BUS_RESET) != 0)
  797. return (ERROR);
  798.     if (operation & SCSI_BUS_RESET)
  799. ncr810ScsiBusReset (pSiop);
  800.     return (OK);
  801.     }
  802. /*******************************************************************************
  803. *
  804. * ncr810ScsiBusReset - assert the RST line on the SCSI bus 
  805. *
  806. * Issue a SCSI Bus Reset command to the NCR 810. This should put all devices
  807. * on the SCSI bus in an initial quiescent state.
  808. *
  809. * The bus reset will generate an interrupt which is handled by the normal
  810. * ISR (see "ncr810Intr()").
  811. *
  812. * RETURNS: N/A
  813. *
  814. * NOMANUAL
  815. */
  816. LOCAL void ncr810ScsiBusReset
  817.     (
  818.     FAST SIOP *pSiop /* ptr to SIOP info */
  819.     )
  820.     {
  821.     NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) |
  822.     SCNTL1_RST);
  823.     taskDelay (2); /* pause for at least 250 us */
  824.     NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) &
  825.     ~SCNTL1_RST);
  826.     }
  827. /*******************************************************************************
  828. *
  829. * ncr810Intr - interrupt service routine for the SIOP
  830. *
  831. * Find the event type corresponding to this interrupt, and carry out any
  832. * actions which must be done before the SIOP is re-started.  Determine
  833. * whether or not the SIOP is connected to the bus (depending on the event
  834. * type - see note below).  If not, start a client script if possible or
  835. * else just make the SIOP wait for something else to happen.
  836. *
  837. * Notify the SCSI manager of a controller event.
  838. *
  839. * NOTE:
  840. * The "connected" Boolean tells whether there is a SCSI thread in progress
  841. * which must be continued before any other SCSI activity can occur.  In
  842. * principle, it might seem that reading the appropriate bit in the SIOP's
  843. * SCNTL1 register would be better than inferring the value from the interrupt
  844. * code.
  845. *
  846. * However, the SCNTL1 register may change between the time the script
  847. * completes (generates the interrupt) and the time it is read - for example,
  848. * if the SIOP is reselected immediately after generating a DISCONNECTED
  849. * interrupt.
  850. *
  851. * Because the action taken by the ISR depends critically on what will happen
  852. * in software as a result of the current interrupt, and _not_ on the current
  853. * state of the SIOP hardware, if the hardware "connected" bit were used, the
  854. * above scenario would cause the ISR to fail to re-start a script when in
  855. * fact it should do.  The result would be that the SIOP would forever remain
  856. * IDLE, and the SCSI system would become deadlocked.  (I've seen it happen !)
  857. *
  858. * One disadvantage is that the ISR has to know a little too much about the
  859. * semantics of the interrupt codes - an improvement might be to have a
  860. * distinguishing feature (e.g. bit set) in the interrupt code to indicate
  861. * whether or not to start a new script.
  862. *
  863. * RETURNS: N/A
  864. *
  865. * NOMANUAL
  866. */
  867. void ncr810Intr
  868.     (
  869.     SIOP *pSiop
  870.     )
  871.     {
  872.     NCR810_EVENT    event;
  873.     SCSI_EVENT *    pScsiEvent = (SCSI_EVENT *) &event;
  874.     SCSI_CTRL *     pScsiCtrl  = (SCSI_CTRL *)  pSiop;
  875.     NCR810_THREAD * pThread    = (NCR810_THREAD *) pSiop->pHwThread;
  876.     BOOL connected = FALSE;
  877.     BOOL notify    = TRUE;
  878.     int  oldState  = (int) pSiop->state;
  879.     CACHE_PIPE_FLUSH();
  880.     /*
  881.      * Save (partial) SIOP register context in current thread
  882.      */
  883.     pThread->scratcha0 = NCR810_IN_BYTE(pSiop->pScratcha0);
  884.     pThread->scratcha1 = NCR810_IN_BYTE(pSiop->pScratcha1);
  885.     pThread->scratcha2 = NCR810_IN_BYTE(pSiop->pScratcha2);
  886.     pThread->scratcha3 = NCR810_IN_BYTE(pSiop->pScratcha3);
  887.     if ((pScsiEvent->type = ncr810EventTypeGet (pSiop))
  888. == (SCSI_EVENT_TYPE)ERROR)
  889. return;
  890.     SCSI_INT_DEBUG_MSG ("ncr810Intr: DSA = 0x%08x, DSP = 0x%08x, type = %d.n",
  891. NCR810_IN_32(pSiop->pDsa), 
  892. NCR810_IN_32(pSiop->pDsp), 
  893. pScsiEvent->type, 0, 0, 0);
  894.     /*
  895.      *  Synchronise with single-step routine, if enabled.
  896.      */
  897.     if (pSiop->singleStep)
  898.      semGive (pSiop->singleStepSem);
  899.     if (pScsiEvent->type == NCR810_SINGLE_STEP)
  900. return;
  901.     
  902.     /*
  903.      * Handle interrupt according to type.
  904.      */
  905.     switch (pScsiEvent->type)
  906. {
  907. /*
  908.  *  Following cases result from completion of a script run.
  909.  */
  910. case NCR810_CMD_COMPLETE:
  911. case NCR810_DISCONNECTED:
  912.     connected = FALSE;
  913.     break;
  914.      case NCR810_MESSAGE_OUT_SENT:
  915.      case NCR810_MESSAGE_IN_RECVD:
  916. case NCR810_EXT_MESSAGE_SIZE:
  917. case NCR810_NO_MSG_OUT:
  918. case NCR810_SCRIPT_ABORTED:
  919.     connected = TRUE;
  920.     break;
  921. case NCR810_PHASE_MISMATCH:
  922.     event.remCount = ncr810RemainderGet (pSiop, pThread->nBusPhase);
  923.     
  924.     connected = TRUE;
  925.     break;
  926. /*
  927.  *  Following cases are asynchronous conditions, i.e. not resulting
  928.  *  directly from running a script.
  929.  */
  930.      case NCR810_READY:
  931.     connected = FALSE;
  932.     notify    = FALSE;
  933.     break;
  934.     
  935.      case NCR810_SELECTED:
  936.      case NCR810_RESELECTED:
  937.     pScsiEvent->busId = ncr810BusIdGet (pSiop, pThread->nBusIdBits);
  938.     pScsiEvent->nBytesIdent =
  939. (pThread->nHostFlags & FLAGS_IDENTIFY) ? 1 : 0;
  940.     connected = TRUE;
  941.     break;
  942. case NCR810_SCSI_BUS_RESET:
  943.     connected = FALSE;
  944.     break;
  945. /*
  946.  *  Following cases are error conditions (mixture of synchronous
  947.  *  and asynchronous).
  948.  */
  949. case NCR810_SCSI_TIMEOUT:
  950. case NCR810_HANDSHAKE_TIMEOUT:
  951.     connected = FALSE;
  952.     break;
  953. case NCR810_ILLEGAL_PHASE:
  954.     connected = TRUE;
  955.     break;
  956. case NCR810_UNEXPECTED_DISCON:
  957.     connected = FALSE;
  958.     break;
  959.      case NCR810_NO_IDENTIFY:
  960.     logMsg ("ncr810Intr: no valid IDENTIFY message at (re)select.n",
  961.     0, 0, 0, 0, 0, 0);
  962.     connected = TRUE;
  963.     break;
  964.     
  965.      case NCR810_SPURIOUS_CMD:
  966.     logMsg ("ncr810Intr: spurious command interrupt.n",
  967.     0, 0, 0, 0, 0, 0);
  968.     connected = FALSE;
  969.     break;
  970. case NCR810_FATAL_ERROR:
  971.     logMsg ("ncr810Intr: unrecoverable error - re-starting SIOP.n",
  972.     0, 0, 0, 0, 0, 0);
  973.     ncr810HwInit (pSiop);
  974.     connected = FALSE;
  975.     break;
  976. default:
  977.     SCSI_INT_DEBUG_MSG ("ncr810Intr: unexpected interrupt (%d).n",
  978.     pScsiEvent->type, 0, 0, 0, 0, 0);
  979.     break;
  980. }
  981.     /*
  982.      *  Controller is now idle: if possible, make it run a script.
  983.      *
  984.      * If a SCSI thread is suspended and must be processed at task-level,
  985.      * leave the SIOP idle.  It will be re-started by the SCSI manager
  986.      * calling "ncr810Resume()".
  987.      *
  988.      * Otherwise, if there's a new SCSI thread to start (i.e., the SCSI
  989.      * manager has called "ncr810Activate()"), start the appropriate script.
  990.      *
  991.      * Otherwise, start a script which puts the SIOP into passive mode
  992.      * waiting for re-selection, selection or a host command.
  993.      *
  994.      * In all cases, clear any request to start a new thread.  The only
  995.      * tricky case is when there was a request pending and the SIOP is
  996.      * left IDLE.  This should only ever occur when the current event is
  997.      * selection or reselection, in which case the SCSI manager will retry
  998.      * the activation request.  (Also see "ncr810Activate ()".)
  999.      */
  1000.     if (connected)
  1001. {
  1002.      pSiop->state = NCR810_STATE_IDLE;
  1003. }
  1004.     else if (pSiop->cmdPending)
  1005. {
  1006. ncr810ScriptStart (pSiop,
  1007.    (NCR810_THREAD *) pSiop->pNewThread,
  1008.    NCR810_SCRIPT_INIT_START);
  1009. pSiop->state = NCR810_STATE_ACTIVE;
  1010. }
  1011.     else
  1012. {
  1013. ncr810ScriptStart (pSiop,
  1014.    (NCR810_THREAD *) pScsiCtrl->pIdentThread,
  1015.    NCR810_SCRIPT_WAIT);
  1016. pSiop->state = NCR810_STATE_PASSIVE;
  1017. }
  1018.     pSiop->cmdPending = FALSE;
  1019.     SCSI_INT_DEBUG_MSG ("ncr810Intr: state %d -> %dn",
  1020. oldState, pSiop->state, 0, 0, 0, 0);
  1021.     /*
  1022.      * Send the event to the SCSI manager to be processed.
  1023.      */
  1024.     if (notify)
  1025.      scsiMgrEventNotify ((SCSI_CTRL *) pSiop, pScsiEvent, sizeof (event));
  1026.     }
  1027. /*******************************************************************************
  1028. *
  1029. * ncr810BusIdGet - find bus ID of device which selected/reselected the SIOP.
  1030. *
  1031. * Get the Bus ID of the selecting/reselecting device by looking at SSID
  1032. * RETURNS: bus ID of connected peer device
  1033. *
  1034. * NOTE: This routine is called at interrupt level.
  1035. *
  1036. * NOMANUAL
  1037. */
  1038. LOCAL int ncr810BusIdGet
  1039.     (
  1040.     SIOP * pSiop, /* ptr to controller info       */
  1041.     UINT   busIdBits /* bits corresponding to bus ID */
  1042.     )
  1043.     {
  1044.     UINT8 devBusId;
  1045.     CACHE_PIPE_FLUSH();
  1046.     /* HELP: decode busIdBits, don't read the device ??? */
  1047.     devBusId = NCR810_IN_BYTE(pSiop->pSsid) & ((UINT8) SSID_ENC_MASK);
  1048.     
  1049.     return (devBusId);
  1050.     }
  1051. /*******************************************************************************
  1052. *
  1053. * ncr810RemainderGet - get remaining xfer count and clean up after mismatch
  1054. *
  1055. * Clean up the SIOP's data path and calculate the number of bytes which
  1056. * were expected to be, but have not been transferred.
  1057. *
  1058. * The information transfer phase which halted because of the mismatch has
  1059. * been saved as part of the SIOP's register context.
  1060. *
  1061. * RETURNS: number of bytes not transferred
  1062. *
  1063. * NOTE: This routine is called at interrupt level.
  1064. *
  1065. * NOMANUAL
  1066. */
  1067. LOCAL UINT ncr810RemainderGet
  1068.     (
  1069.     SIOP *pSiop, /* pointer to controller info     */
  1070.     UINT  phase /* phase terminated by mismatch   */
  1071.     )
  1072.     {
  1073.     UINT  remCount;
  1074.     UINT8 tmpCount;
  1075.     UINT  tmpCountWord;
  1076.     UINT8 countFifo;
  1077.     UINT8 syncMode;
  1078.     CACHE_PIPE_FLUSH();
  1079.     /* determine xfer mode */
  1080.     syncMode = NCR810_IN_BYTE(pSiop->pSxfer) & SXFER_OFFSET;
  1081.     /*
  1082.      * Find remaining byte count (may be corrected later).  For a fuller
  1083.      * explanation, see Chapter 2 of the NCR 53C810 Data Manual.
  1084.      */
  1085.     remCount = NCR810_IN_32(pSiop->pDbc) & NCR810_COUNT_MASK;
  1086.     /*
  1087.      *   check for data in fifo and output registers
  1088.      * (SODR & SODL), count from DBC minus DFIFO count and 0x7f
  1089.      * (see NCR 53C810 Data Manual).
  1090.      */
  1091.     /* look for deep fifo mode on 825/875 */
  1092.     tmpCount = 0;
  1093.     tmpCountWord = 0;
  1094.     if ( ((pSiop->devType == NCR825_DEVICE_ID)  ||
  1095.   (pSiop->devType == NCR875_DEVICE_ID)) &&
  1096.  (NCR810_IN_BYTE(pSiop->pCtest5) & CTEST5_DFS) ) 
  1097. {
  1098. tmpCountWord = ((((UINT)NCR810_IN_BYTE(pSiop->pCtest5)) & 0x0003) << 8);
  1099. tmpCountWord += (UINT)NCR810_IN_BYTE(pSiop->pDfifo);
  1100. tmpCountWord -= (remCount & 0x03FF);
  1101. }
  1102.     else
  1103. {
  1104. countFifo = NCR810_IN_BYTE(pSiop->pDfifo) & 0x7f;
  1105. tmpCount  = (UINT8)(countFifo - tmpCount) & 0x7f;
  1106. }
  1107.     switch (phase)
  1108.         {
  1109.         case PHASE_DATA_IN:
  1110.         case PHASE_MSG_IN:
  1111. case PHASE_STATUS:
  1112.     if (!syncMode)
  1113. {
  1114. /* Asynchronous Read */
  1115. if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_ILF)
  1116.     tmpCount++;
  1117. /* 825/875 Extensions */
  1118. if ((pSiop->devType == NCR825_DEVICE_ID) ||
  1119.     (pSiop->devType == NCR875_DEVICE_ID))
  1120.     {
  1121.     if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_ILF)
  1122. tmpCount++;
  1123.     if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_ILF)
  1124. tmpCount++;
  1125.     }
  1126. }
  1127.     else
  1128. {
  1129. /* Synchronous Read */
  1130. countFifo = (UINT8)((NCR810_IN_BYTE(pSiop->pSstat1) & FIFO_MASK)
  1131.     >> 4);
  1132. countFifo &= 0x0f;
  1133.     
  1134. /* 825/875 Extensions */
  1135. if ((pSiop->devType == NCR825_DEVICE_ID) ||
  1136.     (pSiop->devType == NCR875_DEVICE_ID))
  1137.     {
  1138.     if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_FF4)
  1139. countFifo |= 0x1f;
  1140.     }
  1141. tmpCount += countFifo;
  1142. }
  1143.     /* Check wide SCSI on 825/875 */
  1144.     if ((pSiop->devType == NCR825_DEVICE_ID) ||
  1145. (pSiop->devType == NCR875_DEVICE_ID))
  1146. {
  1147. if (NCR810_IN_BYTE(pSiop->pScntl2) & SCNTL2_WSR)
  1148.     tmpCount++;
  1149. }
  1150.     remCount += tmpCount;
  1151.          break;
  1152.         case PHASE_DATA_OUT:
  1153.         case PHASE_MSG_OUT:
  1154. case PHASE_COMMAND:
  1155.     /* Asynch/Synchronous write */
  1156.     if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_OLF)
  1157. tmpCount++;
  1158.     if ((pSiop->devType == NCR825_DEVICE_ID) ||
  1159. (pSiop->devType == NCR875_DEVICE_ID))
  1160. {
  1161. if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_OLF)
  1162.     tmpCount++;
  1163. }
  1164.     if (syncMode)
  1165. {
  1166. /* Synchronous write */
  1167. if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_ORF)
  1168.     tmpCount++;
  1169. /* 825/875 Extensions */
  1170. if ((pSiop->devType == NCR825_DEVICE_ID) ||
  1171.     (pSiop->devType == NCR875_DEVICE_ID))
  1172.     {
  1173.     if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_ORF)
  1174. tmpCount++;
  1175.     } /* 825/875 */
  1176. }
  1177.    
  1178.     remCount += tmpCount;
  1179.     break;
  1180.     
  1181.         default:
  1182.             logMsg ("ncr810RemainderGet: invalid phase.n", 0, 0, 0, 0, 0, 0);
  1183.     break;
  1184.         }
  1185.     /* Add in any deep fifo adjustments; this is zero for 88-byte fifos */
  1186.     remCount += tmpCountWord;
  1187.     /* Clear data FIFOs */
  1188.     NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) |
  1189.     CTEST3_CLF);
  1190.     return (remCount);
  1191.     }
  1192. /******************************************************************************
  1193. *
  1194. * ncr810EventTypeGet - parse SCSI and DMA status registers at interrupt time
  1195. *
  1196. * NOTE
  1197. * Only status bits which have corresponding interrupts enabled are checked !
  1198. *
  1199. * RETURNS: an interrupt (event) type code
  1200. *
  1201. * NOMANUAL
  1202. */
  1203. LOCAL int ncr810EventTypeGet
  1204.     (
  1205.     SIOP * pSiop
  1206.     )
  1207.     {
  1208.     UINT8 istat;
  1209.     UINT8 dmaStatus;
  1210.     UINT8 sist0;
  1211.     UINT8 sist1;
  1212.     int key;
  1213.     /*
  1214.      * Read interrupt status registers
  1215.      *
  1216.      * Note: reading the interrupt status register as a long word
  1217.      *  causes the status register to read as NULL. This should not
  1218.      *  be the case, however, the workaround is to read the status
  1219.      *  registers as 8 bit registers and insert 12 SCLK delays
  1220.      *  in between successive reads, as explained in the data manual.
  1221.      */
  1222.     
  1223.     /*
  1224.      * Interrupts need to be locked in interrupt context while the status
  1225.      * registers are being read so that there is no contention between
  1226.      * a synchronous thread and a bus initiated thread (reselect)
  1227.      *
  1228.      * HELP: Not certain that we need locking in this routine.  We only
  1229.      * get here as a result of a SCSI interrupt.  The SIOP should be stopped.
  1230.      * Investigate all uses of intLock and IntDisable/IntRestore.
  1231.      */
  1232.     key = intLock();
  1233.     CACHE_PIPE_FLUSH ();
  1234.     istat = NCR810_IN_BYTE(pSiop->pIstat); 
  1235.     if ((istat & (ISTAT_SIP | ISTAT_DIP)) != 0) 
  1236.         {
  1237. if (istat & ISTAT_ABRT)
  1238.     NCR810_OUT_BYTE(pSiop->pIstat, 0x00);
  1239. if ((istat & ISTAT_SIP) && (istat & ISTAT_DIP))
  1240.     {
  1241.     SCSI_INT_DEBUG_MSG ("Both SIP and DIP occurred simultaneouslyn",
  1242.                      0,0,0,0,0,0);
  1243.     }
  1244.         CACHE_PIPE_FLUSH ();
  1245. dmaStatus  = NCR810_IN_BYTE(pSiop->pDstat);
  1246.         CACHE_PIPE_FLUSH ();
  1247.         ncr810Delay ();
  1248.         sist0 = NCR810_IN_BYTE(pSiop->pSist0);
  1249.         CACHE_PIPE_FLUSH ();
  1250.         ncr810Delay ();
  1251.         sist1 = NCR810_IN_BYTE(pSiop->pSist1);
  1252. intUnlock (key);
  1253.         }
  1254.     else
  1255. {
  1256. intUnlock (key);
  1257. return (ERROR);
  1258. }
  1259.     SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet:"
  1260. "Interrupt status istat = 0x%02x, "
  1261. "SCSI status0 = 0x%02x, "
  1262. "SCSI status1 = 0x%02x"
  1263. "DMA status = 0x%02xn",
  1264.      istat, sist0, sist1, dmaStatus, 0, 0);
  1265.     /*
  1266.      * Check for fatal errors (first !)
  1267.      */
  1268.     if  (sist0 & B_SGE)
  1269.         {
  1270. logMsg ("ncr810: SCSI bus gross error.n", 0, 0, 0, 0, 0, 0);
  1271. return (NCR810_FATAL_ERROR);
  1272.         }
  1273.     if  (sist0 & B_PAR)
  1274.         {
  1275. logMsg ("ncr810: parity error.n", 0, 0, 0, 0, 0, 0);
  1276. return (NCR810_FATAL_ERROR);
  1277.         }
  1278.     if (dmaStatus & B_IID)
  1279.         {
  1280. logMsg ("ncr810: illegal instruction (DSP = 0x%08x).n",
  1281. NCR810_IN_32(pSiop->pDsp), 0, 0, 0, 0, 0);
  1282. return (NCR810_FATAL_ERROR);
  1283.         }
  1284.     if (dmaStatus & B_BF)
  1285.         {
  1286. logMsg ("ncr810: bus fault (DSPS = 0x%08x) DBC = (0x%08x).n",
  1287. NCR810_IN_32(pSiop->pDsps), 
  1288. NCR810_IN_32(pSiop->pDbc) & 0xffffff, 0, 0, 0, 0);
  1289. return (NCR810_FATAL_ERROR);
  1290.         }
  1291.     /*
  1292.      * No fatal errors; try the rest (NB order of tests is important !)
  1293.      */
  1294.     if  (sist0 & B_RST)
  1295.         {
  1296. SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: SCSI bus reset.n",
  1297.     0, 0, 0, 0, 0, 0);
  1298.         CACHE_PIPE_FLUSH();
  1299. NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) |
  1300. CTEST3_CLF); /* clear FIFOs */
  1301. return (NCR810_SCSI_BUS_RESET);
  1302.         }
  1303.     if  (sist0 & B_UDC)
  1304.         {
  1305. SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: unexpected disconnection.n",
  1306.     0, 0, 0, 0, 0, 0);
  1307. /* clear FIFOs */
  1308.         CACHE_PIPE_FLUSH();
  1309. NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) |
  1310. CTEST3_CLF);
  1311. return (NCR810_UNEXPECTED_DISCON);
  1312.         }
  1313.     if (sist1 & B_STO)
  1314. {
  1315.      SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: SCSI bus timeout.n",
  1316.     0, 0, 0, 0, 0, 0);
  1317. /* clear FIFOs */
  1318.         CACHE_PIPE_FLUSH();
  1319. NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) |
  1320. CTEST3_CLF);
  1321. return (NCR810_SCSI_TIMEOUT);
  1322. }
  1323.     if (sist1 & B_HTH)
  1324. {
  1325.      SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: SCSI handshake timeout.n",
  1326.     0, 0, 0, 0, 0, 0);
  1327. /* clear FIFOs */
  1328.         CACHE_PIPE_FLUSH();
  1329. NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) |
  1330. CTEST3_CLF);
  1331. return (NCR810_HANDSHAKE_TIMEOUT);
  1332. }
  1333.     if (sist0 & B_MA)
  1334.         {
  1335. /*
  1336.  *  The "phase mismatch" interrupt is used to indicate assertion of
  1337.  *  ATN in target mode.  This interrupt should have been disabled
  1338.  *  by the script when in target mode, because the current code does
  1339.  *  not know how to handle it.
  1340.  */
  1341.         CACHE_PIPE_FLUSH();
  1342. if (NCR810_IN_BYTE(pSiop->pScntl0) & SCNTL0_TRG)
  1343.     {
  1344.     if (NCR810_IN_BYTE(pSiop->pSien0) & B_MA)
  1345. {
  1346. logMsg ("ncr810EventTypeGet: enabled ATN interrupt!n",
  1347. 0, 0, 0, 0, 0, 0);
  1348. return (NCR810_FATAL_ERROR);
  1349. }
  1350.     }
  1351. else
  1352.     {
  1353.     SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: phase mismatch.n",
  1354.     0, 0, 0, 0, 0, 0);
  1355.     return (NCR810_PHASE_MISMATCH);
  1356.     }
  1357.         }
  1358.     if (dmaStatus & B_ABT)
  1359.         {
  1360. SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: script aborted.n",
  1361.          0, 0, 0, 0, 0, 0);
  1362. return (NCR810_SCRIPT_ABORTED);
  1363.         }
  1364.     if (dmaStatus & B_SIR)
  1365. {
  1366. SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: script completed.n",
  1367.     0, 0, 0, 0, 0, 0);
  1368. /* HELP: This doesn't look like a valid return value */
  1369. return ( NCR810_IN_32(pSiop->pDsps) );
  1370.         }
  1371.     if (dmaStatus & B_SSI)
  1372. {
  1373. SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: single-step.n",
  1374.     0, 0, 0, 0, 0, 0);
  1375. return (NCR810_SINGLE_STEP);
  1376. }
  1377.     /*
  1378.      * No (expected) reason for the interrupt !
  1379.      */
  1380.     logMsg ("ncr810EventTypeGet: spurious interrupt !n", 0, 0, 0, 0, 0, 0);
  1381.     logMsg ("tistat: (0x%x) dstat: (0x%x)n", istat, dmaStatus, 0, 0, 0, 0); 
  1382.     logMsg ("tsist0: (0x%x) sist1: (0x%x)n", sist0, sist1, 0, 0, 0, 0);
  1383.     
  1384.     return (NCR810_FATAL_ERROR);
  1385.     }
  1386. /*******************************************************************************
  1387. *
  1388. * ncr810ThreadActivate - activate a SCSI connection for an initiator thread
  1389. *
  1390. * Set whatever thread/controller state variables need to be set.  Ensure that
  1391. * all buffers used by the thread are coherent with the contents of the
  1392. * system caches (if any).
  1393. *
  1394. * Set transfer parameters for the thread based on what its target device
  1395. * last negotiated.
  1396. *
  1397. * Update the thread context (including shared memory area) and note that
  1398. * there is a new client script to be activated (see "ncr810Activate()").
  1399. *
  1400. * Set the thread's state to ESTABLISHED.  This is strictly a bit premature,
  1401. * but there is no distinction as far as this driver is concerned between a
  1402. * thread which is connecting and one which has connected (i.e., the script
  1403. * just runs to completion and we have to examine its exit status to determine
  1404. * how far through the process the thread got).
  1405. *
  1406. * Do not wait for the script to be activated.  Completion of the script will
  1407. * be signalled by an event which is handled by "ncr810Event()".
  1408. *
  1409. * RETURNS: OK or ERROR
  1410. *
  1411. * NOMANUAL
  1412. */
  1413. LOCAL STATUS ncr810ThreadActivate
  1414.     (
  1415.     SIOP *          pSiop, /* ptr to controller info */
  1416.     NCR810_THREAD * pThread /* ptr to thread info     */
  1417.     )
  1418.     {
  1419.     SCSI_CTRL *   pScsiCtrl   = (SCSI_CTRL *)   pSiop;
  1420.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1421.     SCSI_TARGET * pScsiTarget = pScsiThread->pScsiTarget;
  1422.     SCSI_THREAD * pOrigThread;
  1423.     
  1424.     SCSI_DEBUG_MSG ("ncr810ThreadActivate: thread 0x%08x: activatingn",
  1425.     (int) pThread, 0, 0, 0, 0, 0);
  1426.     scsiCacheSynchronize (pScsiThread, SCSI_CACHE_PRE_COMMAND);
  1427.     /*
  1428.      * Reset controller state variables: set sync xfer parameters
  1429.      */
  1430.     pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE;
  1431.     pScsiCtrl->msgInState  = SCSI_MSG_IN_NONE;
  1432.     
  1433.     pOrigThread = pScsiCtrl->pThread;
  1434.     pScsiCtrl->pThread = pScsiThread;
  1435.     /*
  1436.      * A wide transfer is initiated before a synchronous transfer. However,
  1437.      * when a wide transfer has been done the next activation causes the
  1438.      * synchronous transfer to be activated. Another possible but more
  1439.      * complicated way to implement this would be to have both wide and
  1440.      * synchronous negotiations in the same activation or thread i.e.
  1441.      * the same SCSI transaction.
  1442.      */
  1443.     scsiWideXferNegotiate (pScsiCtrl, pScsiTarget, WIDE_XFER_NEW_THREAD);
  1444.     scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD);
  1445.     if (ncr810ThreadParamsSet (pThread, pScsiTarget->xferOffset,
  1446.               pScsiTarget->xferPeriod) != OK)
  1447. {
  1448. SCSI_ERROR_MSG ("ncr810ThreadActivate: failed to set thread params.n",
  1449. 0, 0, 0, 0, 0, 0);
  1450.         pScsiCtrl->pThread = pOrigThread; 
  1451. return (ERROR);
  1452. }
  1453.     /*
  1454.      *  Concatenate the ident message with a pending 'normal' message out,
  1455.      *  if possible.  This allows the script to send the first message out
  1456.      *  within the same MSG OUT phase as the IDENTIFY message - needed on
  1457.      *  some target systems (e.g. DG Clariion RAID) to avoid the message
  1458.      *  being rejected(!).
  1459.      */
  1460.     pSiop->identMsgLength = 0;
  1461.     bcopy ((char *)pScsiThread->identMsg,
  1462.            (char *)pSiop->identMsg,
  1463.            pScsiThread->identMsgLength);
  1464.     pSiop->identMsgLength += pScsiThread->identMsgLength;
  1465.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)
  1466.         {
  1467.         bcopy ((char *)pScsiCtrl->msgOutBuf,
  1468.                (char *)pSiop->identMsg + pSiop->identMsgLength,
  1469.                pScsiCtrl->msgOutLength);
  1470.         pSiop->identMsgLength += pScsiCtrl->msgOutLength;
  1471.         }
  1472.     /*
  1473.      * Update thread context; activate the thread
  1474.      */
  1475.     ncr810ThreadUpdate (pThread);
  1476.     
  1477.     if (ncr810Activate (pSiop, pThread) != OK)
  1478. {
  1479. SCSI_ERROR_MSG ("ncr810ThreadActivate: failed to activate thread.n",
  1480.         0, 0, 0, 0, 0, 0);
  1481.         pScsiCtrl->pThread = pOrigThread; 
  1482. return (ERROR);
  1483. }
  1484.     pScsiCtrl->pThread = pScsiThread;
  1485.     ncr810ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  1486.     
  1487.     return (OK);
  1488.     }
  1489. /*******************************************************************************
  1490. *
  1491. * ncr810ThreadAbort - abort a thread
  1492. *
  1493. * If the thread is not currently connected, do nothing and return FALSE to
  1494. * indicate that the SCSI manager should abort the thread.
  1495. *
  1496. * Otherwise (the thread is active onthe controller), build an ABORT or
  1497. * ABORT TAG message which will (eventually) be sent, causing the taget to
  1498. * disconnect.  Abort the current script run so that this message can be
  1499. * sent.  Set the state of the thread accordingly, and return TRUE to
  1500. * indicate that the controller driver will handle the abort process.
  1501. *
  1502. * RETURNS: TRUE if the thread is being aborted by this driver (i.e. it is
  1503. * currently active on the controller, else FALSE.
  1504. *
  1505. * NOMANUAL
  1506. */
  1507. LOCAL BOOL ncr810ThreadAbort
  1508.     (
  1509.     SIOP *          pSiop, /* ptr to controller info */
  1510.     NCR810_THREAD * pThread /* ptr to thread info     */
  1511.     )
  1512.     {
  1513.     BOOL          tagged;
  1514.     SCSI_CTRL *   pScsiCtrl   = (SCSI_CTRL *)   pSiop;
  1515.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1516.     SCSI_DEBUG_MSG ("ncr810ThreadAbort: thread 0x%08x (state = %d) abortingn",
  1517.     (int) pThread, pScsiThread->state, 0, 0, 0, 0);
  1518.     if (pScsiThread != pScsiCtrl->pThread)
  1519. return (FALSE);
  1520.     
  1521.     switch (pScsiThread->state)
  1522. {
  1523. case SCSI_THREAD_INACTIVE:
  1524. case SCSI_THREAD_WAITING:
  1525. case SCSI_THREAD_DISCONNECTED:
  1526.     return (FALSE);
  1527.     break;
  1528. default:
  1529.     /*
  1530.      * Build an ABORT (or ABORT TAG) message.  When this has been
  1531.      * sent, the target should disconnect.  Mark the thread aborted
  1532.      * and continue until disconnection.
  1533.      */
  1534.     tagged = (pScsiThread->tagNumber != (UINT)NONE);
  1535.     pScsiCtrl->msgOutBuf[0] = tagged ? SCSI_MSG_ABORT_TAG
  1536.                     : SCSI_MSG_ABORT;
  1537.     pScsiCtrl->msgOutLength = 1;
  1538.     pScsiCtrl->msgOutState  = SCSI_MSG_OUT_PENDING;
  1539.     ncr810Abort (pSiop);
  1540.     
  1541.          ncr810ThreadStateSet (pThread, SCSI_THREAD_ABORTING);
  1542.     break;
  1543. }
  1544.     return (TRUE);
  1545.     }
  1546. /*******************************************************************************
  1547. *
  1548. * ncr810Event - NCR 53C810 SCSI controller event processing routine
  1549. *
  1550. * Parse the event type and act accordingly.  Controller-level events are
  1551. * handled within this function, and the event is then passed to the current
  1552. * thread (if any) for thread-level processing.
  1553. *
  1554. * Note the special case when (re)selection occurs: if there is a current
  1555. * thread when the event occurs, it receives the event (and is assumed to
  1556. * defer itself) before the identification thread is made current.  The
  1557. * event is then forwarded to the identification thread.
  1558. *
  1559. * RETURNS: N/A
  1560. */
  1561. LOCAL void ncr810Event
  1562.     (
  1563.     SIOP *         pSiop,
  1564.     NCR810_EVENT * pEvent
  1565.     )
  1566.     {
  1567.     SCSI_CTRL  *    pScsiCtrl  = (SCSI_CTRL *)  pSiop;
  1568.     SCSI_EVENT *    pScsiEvent = (SCSI_EVENT *) pEvent;
  1569.     NCR810_THREAD * pThread    = (NCR810_THREAD *) pScsiCtrl->pThread;
  1570.     
  1571.     SCSI_DEBUG_MSG ("ncr810Event: received event %d (thread = 0x%08x)n",
  1572.     pScsiEvent->type, (int) pThread, 0, 0, 0, 0);
  1573.     /*
  1574.      * Do controller-level event processing
  1575.      */
  1576.     switch (pScsiEvent->type)
  1577. {
  1578. case NCR810_SELECTED:
  1579. case NCR810_RESELECTED:
  1580.     /*
  1581.      * Forward event to current thread, if any (it should defer)
  1582.      * then install a reserved thread for identification purposes.
  1583.      */
  1584.          if (pThread != 0)
  1585.      ncr810ThreadEvent (pThread, pEvent);
  1586.          pScsiCtrl->peerBusId = pScsiEvent->busId;
  1587.          pScsiCtrl->pThread = pScsiCtrl->pIdentThread;
  1588.     
  1589.     pScsiCtrl->pThread->role = (pScsiEvent->type == NCR810_SELECTED)
  1590.                ? SCSI_ROLE_IDENT_TARG
  1591.      : SCSI_ROLE_IDENT_INIT;
  1592.     pThread = (NCR810_THREAD *) pScsiCtrl->pThread;
  1593.     scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED);
  1594.     break;
  1595. case NCR810_DISCONNECTED:
  1596. case NCR810_CMD_COMPLETE:
  1597. case NCR810_UNEXPECTED_DISCON:
  1598. case NCR810_SCSI_TIMEOUT:
  1599.          pScsiCtrl->peerBusId = NONE;
  1600.          pScsiCtrl->pThread   = 0;
  1601.     scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED);
  1602.     
  1603.     break;
  1604. case NCR810_SCSI_BUS_RESET:
  1605.          pScsiCtrl->peerBusId = NONE;
  1606.          pScsiCtrl->pThread   = 0;
  1607.          scsiMgrBusReset (pScsiCtrl);
  1608.     break;
  1609. default:
  1610.     /*
  1611.      * Any other event type is assumed to be thread-specific.
  1612.      * The thread event handler will report an error if it's
  1613.      * not a valid type.
  1614.      */
  1615.     if (pThread == 0)
  1616. {
  1617.      logMsg ("ncr810Event: invalid event type (%d)n",
  1618.      pScsiEvent->type, 0, 0, 0, 0, 0);
  1619. }
  1620.     break;
  1621. }
  1622.     /*
  1623.      * If there's a thread on the controller, forward the event to it
  1624.      */
  1625.     if (pThread != 0)
  1626. ncr810ThreadEvent (pThread, pEvent);
  1627.     }
  1628.     
  1629. /*******************************************************************************
  1630. *
  1631. * ncr810ThreadEvent - NCR 53C810 thread event processing routine
  1632. *
  1633. * Forward the event to the proper handler for the thread's current role.
  1634. *
  1635. * If the thread is still active, update the thread context (including
  1636. * shared memory area) and resume the thread.
  1637. *
  1638. * RETURNS: N/A
  1639. *
  1640. * NOMANUAL
  1641. */
  1642. LOCAL void ncr810ThreadEvent
  1643.     (
  1644.     NCR810_THREAD * pThread,
  1645.     NCR810_EVENT *  pEvent
  1646.     )
  1647.     {
  1648.     SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;
  1649.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1650.     SIOP *        pSiop       = (SIOP *)        pScsiThread->pScsiCtrl;
  1651.     NCR810_SCRIPT_ENTRY entryPt;
  1652.     
  1653.     SCSI_DEBUG_MSG ("ncr810ThreadEvent: thread 0x%08x: received event %dn",
  1654.     (int) pThread, pScsiEvent->type, 0, 0, 0, 0);
  1655.     switch (pScsiThread->role)
  1656. {
  1657. case SCSI_ROLE_INITIATOR:
  1658.     ncr810InitEvent (pThread, pEvent);
  1659.     entryPt = NCR810_SCRIPT_INIT_CONTINUE;
  1660.     break;
  1661.     
  1662. case SCSI_ROLE_IDENT_INIT:
  1663.     ncr810InitIdentEvent (pThread, pEvent);
  1664.     entryPt = NCR810_SCRIPT_INIT_CONTINUE;
  1665.     break;
  1666. case SCSI_ROLE_IDENT_TARG:
  1667.     ncr810TargIdentEvent (pThread, pEvent);
  1668.     entryPt = NCR810_SCRIPT_TGT_DISCONNECT;
  1669.     break;
  1670.     
  1671. case SCSI_ROLE_TARGET:
  1672. default:
  1673.     logMsg ("ncr810ThreadEvent: thread 0x%08x: invalid role (%d)n",
  1674.     (int) pThread, pScsiThread->role, 0, 0, 0, 0);
  1675.     entryPt = NCR810_SCRIPT_TGT_DISCONNECT;
  1676.     break;
  1677. }
  1678.     /*
  1679.      * Resume thread iff it is still connected
  1680.      */
  1681.     switch (pScsiThread->state)
  1682. {
  1683. case SCSI_THREAD_INACTIVE:
  1684. case SCSI_THREAD_WAITING:
  1685. case SCSI_THREAD_DISCONNECTED:
  1686.     break;
  1687. default:
  1688.          ncr810ThreadUpdate (pThread);
  1689.     if (ncr810Resume (pSiop, pThread, entryPt) != OK)
  1690.      {
  1691.      SCSI_ERROR_MSG ("ncr810ThreadEvent: failed to resume threadn",
  1692.      0, 0, 0, 0, 0, 0);
  1693. ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1694.      }
  1695.     break;
  1696. }
  1697.     }
  1698. /*******************************************************************************
  1699. *
  1700. * ncr810InitEvent - NCR 53C810 initiator thread event processing routine
  1701. *
  1702. * Parse the event type and handle it accordingly.  This may result in state
  1703. * changes for the thread, state variables being updated, etc.
  1704. *
  1705. * RETURNS: N/A
  1706. *
  1707. * NOMANUAL
  1708. */
  1709. LOCAL void ncr810InitEvent
  1710.     (
  1711.     NCR810_THREAD * pThread,
  1712.     NCR810_EVENT *  pEvent
  1713.     )
  1714.     {
  1715.     SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;
  1716.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1717.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  1718.     /*
  1719.      *  Update controller msg in/out state after script completes
  1720.      */
  1721.     pScsiCtrl->msgOutState = pThread->nMsgOutState;
  1722.     pScsiCtrl->msgInState  = pThread->nMsgInState;
  1723.     
  1724.     /*
  1725.      * Parse script exit status; handle as necessary
  1726.      */
  1727.     switch (pScsiEvent->type)
  1728. {
  1729. case NCR810_DISCONNECTED:
  1730.          SCSI_DEBUG_MSG ("DISCONNECT message inn", 0, 0, 0, 0, 0, 0);
  1731.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DISCONNECTED);
  1732.     ncr810ThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED);
  1733.     break;
  1734. case NCR810_CMD_COMPLETE:
  1735.     SCSI_DEBUG_MSG ("COMMAND COMPLETE message inn", 0, 0, 0, 0, 0, 0);
  1736.     ncr810ThreadComplete (pThread);
  1737.     break;
  1738. case NCR810_SELECTED:
  1739. case NCR810_RESELECTED:
  1740.          SCSI_DEBUG_MSG ("ncr810InitEvent: thread 0x%08x: (re)selection.n",
  1741.          (int) pThread, 0, 0, 0, 0, 0);
  1742.     ncr810ThreadDefer (pThread);
  1743.     break;
  1744.      case NCR810_MESSAGE_OUT_SENT:
  1745.     (void) scsiMsgOutComplete (pScsiCtrl, pScsiThread);
  1746.     break;
  1747.     
  1748. case NCR810_MESSAGE_IN_RECVD:
  1749.     (void) scsiMsgInComplete (pScsiCtrl, pScsiThread);
  1750.     break;
  1751.     
  1752. case NCR810_NO_MSG_OUT:
  1753.     /*
  1754.      * The target has requested a message out when there is none
  1755.      * pending.  Set up a NO-OP message to be sent when thread is
  1756.      *  resumed.
  1757.      *
  1758.      * The script could handle this on its own, but arguably the
  1759.      * host should be involved as it may represent an error.
  1760.      */
  1761.     pScsiCtrl->msgOutBuf[0] = SCSI_MSG_NO_OP;
  1762.     pScsiCtrl->msgOutLength = 1;
  1763.     pScsiCtrl->msgOutState  = SCSI_MSG_OUT_NONE;    /* sic */
  1764.     break;
  1765.     
  1766. case NCR810_EXT_MESSAGE_SIZE:
  1767.     /*
  1768.      *  The SIOP has just read the length byte for an extended
  1769.      *  message in.  The shared memory area is updated with the
  1770.      * appropriate length just before the thread is resumed (see
  1771.      * "ncr810ThreadUpdate()".
  1772.      */
  1773.     break;
  1774.     
  1775. case NCR810_PHASE_MISMATCH:
  1776.     if (ncr810PhaseMismatch (pThread,
  1777.      pThread->nBusPhase,
  1778.      pEvent->remCount) != OK)
  1779. {
  1780. ncr810ThreadFail (pThread, errno);
  1781. }
  1782.     break;
  1783. case NCR810_SCSI_TIMEOUT:
  1784.     SCSI_ERROR_MSG ("ncr810InitEvent: thread 0x%08x: select timeout.n",
  1785.     (int) pThread, 0, 0, 0, 0, 0);
  1786.     ncr810ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
  1787.     break;
  1788. case NCR810_SCRIPT_ABORTED:
  1789.     SCSI_DEBUG_MSG ("ncr810InitEvent: thread 0x%08x: abortedn",
  1790.     (int) pThread, 0, 0, 0, 0, 0);
  1791.     break;
  1792.     
  1793. case NCR810_SCSI_BUS_RESET:
  1794.          SCSI_DEBUG_MSG ("ncr810InitEvent: thread 0x%08x: bus resetn",
  1795.          (int) pThread, 0, 0, 0, 0, 0);
  1796.     /*
  1797.      * Do not try to resume this thread.  SCSI mgr will tidy up.
  1798.      */
  1799.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1800.     break;
  1801. case NCR810_UNEXPECTED_DISCON:
  1802.     /* not really unexpected after an abort message ... */
  1803.          SCSI_ERROR_MSG ("ncr810InitEvent: thread 0x%08x: "
  1804.          "unexpected disconnectionn",
  1805.          (int) pThread, 0, 0, 0, 0, 0);
  1806.     ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1807.     break;
  1808.     
  1809. case NCR810_ILLEGAL_PHASE:
  1810.     SCSI_ERROR_MSG ("ncr810InitEvent: thread 0x%08x: "
  1811.     "illegal phase requested.n",
  1812.     (int) pThread, 0, 0, 0, 0, 0);
  1813.     ncr810ThreadFail (pThread, S_scsiLib_INVALID_PHASE);
  1814.     break;
  1815. default:
  1816.     logMsg ("ncr810InitEvent: invalid event type (%d)n",
  1817.     pScsiEvent->type, 0, 0, 0, 0, 0);
  1818.     break;
  1819. }
  1820.     }
  1821.     
  1822. /*******************************************************************************
  1823. *
  1824. * ncr810InitIdentEvent - NCR 53C810 identification thread event processing 
  1825. *
  1826. * Parse the event type and handle it accordingly.  This may result in state
  1827. * changes for the thread, state variables being updated, etc.
  1828. *
  1829. * RETURNS: N/A
  1830. *
  1831. * NOMANUAL
  1832. */
  1833. LOCAL void ncr810InitIdentEvent
  1834.     (
  1835.     NCR810_THREAD * pThread,
  1836.     NCR810_EVENT *  pEvent
  1837.     )
  1838.     {
  1839.     SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;
  1840.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1841.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  1842.     /*
  1843.      *  Update controller msg in/out state after script completes
  1844.      */
  1845.     pScsiCtrl->msgOutState = pThread->nMsgOutState;
  1846.     pScsiCtrl->msgInState  = pThread->nMsgInState;
  1847.     
  1848.     /*
  1849.      * Parse script exit status; handle as necessary
  1850.      */
  1851.     switch (pScsiEvent->type)
  1852. {
  1853. case NCR810_RESELECTED:
  1854.          pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;
  1855.     bcopy ((char *) pScsiCtrl->identBuf,
  1856.    (char *) pScsiThread->identMsg,
  1857.    pScsiThread->nBytesIdent);
  1858.     ncr810ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);
  1859.          ncr810IdentInContinue (pThread);
  1860.     break;
  1861. case NCR810_MESSAGE_OUT_SENT:
  1862.     /*
  1863.      * This will be after we have sent an "ABORT (TAG)" msg.
  1864.      * The target will disconnect any time; it may have already
  1865.      * done so, in which case we won't be able to resume the
  1866.      * thread, but no matter.
  1867.      */
  1868.     break;
  1869. case NCR810_MESSAGE_IN_RECVD:
  1870.     /*
  1871.      *  Continue parsing the identification message.  It
  1872.      *  should by now be complete.
  1873.      */
  1874.     /*
  1875.      * First byte of ident msg is already in ident buffer.
  1876.      * Remaining bytes are in the normal message input buffer.
  1877.      * This should always be a two-byte message (viz. QUEUE TAG);
  1878.      * it would be nicer if there were a way to avoid hard-coding
  1879.      * this.
  1880.      */
  1881.     bcopy ((char *) pScsiCtrl->msgInBuf,
  1882.    (char *) pScsiThread->identMsg + pScsiThread->nBytesIdent,
  1883.    2);
  1884.     
  1885.          pScsiThread->nBytesIdent += 2;
  1886.          ncr810IdentInContinue (pThread);
  1887.     break;
  1888. case NCR810_SCRIPT_ABORTED:
  1889.     SCSI_DEBUG_MSG ("ncr810InitIdentEvent: thread 0x%08x: abortedn",
  1890.     (int) pThread, 0, 0, 0, 0, 0);
  1891.     break;
  1892.         case NCR810_DISCONNECTED:
  1893.     SCSI_DEBUG_MSG ("ncr810InitIdentEvent: thread 0x%08x:"
  1894.     "disconnectedn",
  1895.     (int) pThread, 0, 0, 0, 0, 0);
  1896.     ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1897.     break;
  1898.     
  1899. case NCR810_SCSI_BUS_RESET:
  1900.          SCSI_DEBUG_MSG ("ncr810InitIdentEvent: thread 0x%08x: bus resetn",
  1901.          (int) pThread, 0, 0, 0, 0, 0);
  1902.     /*
  1903.      * Do not try to resume this thread.  SCSI mgr will tidy up.
  1904.      */
  1905.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1906.     break;
  1907. case NCR810_UNEXPECTED_DISCON:
  1908.     /* not really unexpected after an abort message ... */
  1909.          SCSI_ERROR_MSG ("ncr810InitIdentEvent: thread 0x%08x: "
  1910.          "unexpected disconnectionn",
  1911.          (int) pThread, 0, 0, 0, 0, 0);
  1912.     ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  1913.     break;
  1914.     
  1915. case NCR810_ILLEGAL_PHASE:
  1916.     SCSI_ERROR_MSG ("ncr810InitIdentEvent: thread 0x%08x: "
  1917.     "illegal phase requested.n",
  1918.     (int) pThread, 0, 0, 0, 0, 0);
  1919.     
  1920.     ncr810ThreadFail (pThread, S_scsiLib_INVALID_PHASE);
  1921.     break;
  1922. default:
  1923.     logMsg ("ncr810InitIdentEvent: invalid event type (%d)n",
  1924.     pScsiEvent->type, 0, 0, 0, 0, 0);
  1925.     break;
  1926. }
  1927.     }
  1928.     
  1929. /*******************************************************************************
  1930. *
  1931. * ncr810TargIdentEvent - NCR 53C810 identification thread event processing 
  1932. *
  1933. * Parse the event type and handle it accordingly.  This may result in state
  1934. * changes for the thread, state variables being updated, etc.
  1935. *
  1936. * RETURNS: N/A
  1937. *
  1938. * NOMANUAL
  1939. */
  1940. LOCAL void ncr810TargIdentEvent
  1941.     (
  1942.     NCR810_THREAD * pThread,
  1943.     NCR810_EVENT *  pEvent
  1944.     )
  1945.     {
  1946.     SCSI_EVENT *  pScsiEvent  = (SCSI_EVENT *)  pEvent;
  1947.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1948.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;
  1949.     /*
  1950.      *  Update controller msg in/out state after script completes
  1951.      */
  1952.     pScsiCtrl->msgOutState = pThread->nMsgOutState;
  1953.     pScsiCtrl->msgInState  = pThread->nMsgInState;
  1954.     
  1955.     /*
  1956.      * Parse script exit status; handle as necessary
  1957.      */
  1958.     switch (pScsiEvent->type)
  1959. {
  1960. case NCR810_SELECTED:
  1961.          pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;
  1962.     bcopy ((char *) pScsiCtrl->identBuf,
  1963.    (char *) pScsiThread->identMsg,
  1964.    pScsiThread->nBytesIdent);
  1965.     ncr810ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);
  1966.     break;
  1967.     
  1968.         case NCR810_DISCONNECTED:
  1969.     SCSI_DEBUG_MSG ("ncr810TargIdentEvent: thread 0x%08x:"
  1970.             " disconnectedn",
  1971.     (int) pThread, 0, 0, 0, 0, 0);
  1972.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1973.     break;
  1974.     
  1975. case NCR810_SCSI_BUS_RESET:
  1976.          SCSI_DEBUG_MSG ("ncr810TargIdentEvent: thread 0x%08x: bus resetn",
  1977.          (int) pThread, 0, 0, 0, 0, 0);
  1978.     
  1979.     /*
  1980.      * Do not try to resume this thread.  SCSI mgr will tidy up.
  1981.      */
  1982.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1983.     break;
  1984. case NCR810_UNEXPECTED_DISCON:
  1985.          SCSI_ERROR_MSG ("ncr810TargIdentEvent: thread 0x%08x: "
  1986.          "unexpected disconnectionn",
  1987.          (int) pThread, 0, 0, 0, 0, 0);
  1988.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  1989.     break;
  1990.     
  1991. default:
  1992.     logMsg ("ncr810TargIdentEvent: invalid event type (%d)n",
  1993.     pScsiEvent->type, 0, 0, 0, 0, 0);
  1994.     break;
  1995. }
  1996.     }
  1997.     
  1998. /*******************************************************************************
  1999. *
  2000. * ncr810PhaseMismatch - recover from a SCSI bus phase mismatch
  2001. *
  2002. * This routine does whatever is required to keep the pointers, counts, etc.
  2003. * used by task-level software in step when a SCSI phase mismatch occurs.
  2004. *
  2005. * The interrupt-level mismatch processing has stored the phase of the
  2006. * information transfer before the mismatch, and the number of bytes
  2007. * remaining to be transferred.  See "ncr810RemainderGet()".
  2008. *
  2009. * Note that the only phase mismatches supported at this level are:
  2010. *
  2011. * 1) during data in/out phases - presumably because the target has
  2012. *    transferred as much data as it intends to before sending a message
  2013. *    in (typically DISCONNECT or COMMAND COMPLETE).  Recovery consists
  2014. *    of updating the active data pointer/count according to the number
  2015. *    of data bytes actually transferred before the mismatch.
  2016. *
  2017. * 2) during a message out phase - presumably because the target does not
  2018. *    understand our outgoing message and is sending a MESSAGE REJECT
  2019. *    message, or similar.  No recovery is needed here - it's all done
  2020. *    when the MESSAGE REJECT message has been received (see routine
  2021. *    "scsiMsgOutReject()").
  2022. *
  2023. * 3) during a message in phase - presumably because we have asserted ATN
  2024. *    to abort or reject an incoming message.  No recovery is needed here -
  2025. *    it's done by the thread management code, which should have enough
  2026. *    state information to know what to do.
  2027. *
  2028. * RETURNS: OK, or ERROR for an unsupported or invalid phase
  2029. *
  2030. * NOMANUAL
  2031. */
  2032. LOCAL STATUS ncr810PhaseMismatch
  2033.     (
  2034.     NCR810_THREAD  * pThread, /* ptr to thread info           */
  2035.     int              phase, /* bus phase before mismatch    */
  2036.     UINT             remCount /* # bytes not yet transferred  */
  2037.     )
  2038.     {
  2039.     SCSI_THREAD *pScsiThread = (SCSI_THREAD *) pThread;
  2040.     SCSI_CTRL *   pScsiCtrl   = pScsiThread->pScsiCtrl;    
  2041.     UINT xferCount;
  2042.     switch (phase)
  2043. {
  2044. case SCSI_DATA_IN_PHASE:
  2045. case SCSI_DATA_OUT_PHASE:
  2046.     xferCount = NCR810_SWAP_32(pThread->pShMem->data.size) - remCount;
  2047.     pScsiThread->activeDataAddress += xferCount;
  2048.     pScsiThread->activeDataLength  -= xferCount;
  2049.     
  2050.     SCSI_DEBUG_MSG ("ncr810PhaseMismatch: data transfer aborted "
  2051.     "(%d of %d bytes transferred).n",
  2052.     xferCount, 
  2053.     NCR810_SWAP_32(pThread->pShMem->data.size), 
  2054.     0, 0, 0, 0);
  2055.     break;
  2056.     
  2057. case SCSI_MSG_OUT_PHASE:
  2058.             
  2059.     SCSI_DEBUG_MSG("ncr810PhaseMismatch: message out aborted "
  2060.    "(%d of %d bytes sent).n",
  2061.    pScsiThread->pScsiCtrl->msgOutLength,
  2062.    pScsiThread->pScsiCtrl->msgOutLength - remCount,
  2063.    0, 0, 0, 0);
  2064.             
  2065.     /* Abort the Out message */
  2066.     pScsiCtrl->msgOutLength = 0;
  2067.     pScsiCtrl->msgOutState  = SCSI_MSG_OUT_NONE;
  2068.     ncr810ResetAtn (pScsiCtrl);
  2069.             
  2070.     break;
  2071.     
  2072. case SCSI_MSG_IN_PHASE:
  2073.     SCSI_DEBUG_MSG("ncr810PhaseMismatch: message in aborted "
  2074.    "(%d bytes received).n",
  2075.    pScsiThread->pScsiCtrl->msgInLength,
  2076.    0, 0, 0, 0, 0);
  2077.     break;
  2078. case SCSI_COMMAND_PHASE:
  2079. case SCSI_STATUS_PHASE:
  2080.     SCSI_ERROR_MSG ("ncr810PhaseMismatch: unsupported phase (%d).n",
  2081.     phase, 0, 0, 0, 0, 0);
  2082.     return (ERROR);
  2083.     
  2084. default:
  2085.     logMsg ("ncr810PhaseMismatch: invalid phase (%d).n",
  2086.     phase, 0, 0, 0, 0, 0);
  2087.     return (ERROR);
  2088.         }
  2089.     return (OK);
  2090.     }
  2091. /*******************************************************************************
  2092. *
  2093. * ncr810IdentInContinue - continue incoming identification
  2094. *
  2095. * Parse the message built up so far.  If it is not yet complete, do nothing.
  2096. * If the message is complete, attempt to reconnect the thread it identifies,
  2097. * and deactivate this thread (the identification thread is no longer active).
  2098. * Otherwise (identification has failed), abort the identification sequence.
  2099. *
  2100. * NOTE:
  2101. * This is almost entirely generic code.  It would be nice if the non-hardware
  2102. * specific parts could be provided as a standard routine by the SCSI library.
  2103. *
  2104. * RETURNS: N/A
  2105. *
  2106. * NOMANUAL
  2107. */
  2108. LOCAL void ncr810IdentInContinue
  2109.     (
  2110.     NCR810_THREAD * pThread
  2111.     )
  2112.     {
  2113.     SCSI_THREAD *     pNewThread;
  2114.     SCSI_THREAD *     pScsiThread = (SCSI_THREAD *) pThread;
  2115.     SCSI_CTRL *       pScsiCtrl   = pScsiThread->pScsiCtrl;
  2116.     SCSI_IDENT_STATUS status;
  2117.     SCSI_THREAD_STATE state;
  2118.     status = scsiIdentMsgParse (pScsiCtrl, pScsiThread->identMsg,
  2119.                    pScsiThread->nBytesIdent,
  2120.                   &pScsiThread->pScsiPhysDev,
  2121.        &pScsiThread->tagNumber);
  2122.     switch (status)
  2123. {
  2124. case SCSI_IDENT_INCOMPLETE:
  2125.     state = SCSI_THREAD_IDENT_IN;
  2126.     break;
  2127. case SCSI_IDENT_COMPLETE:
  2128.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_RECONNECTED);
  2129.     if ((pNewThread = scsiMgrPhysDevActiveThreadFind (
  2130.           pScsiThread->pScsiPhysDev,
  2131.           pScsiThread->tagNumber)) == 0)
  2132. {
  2133. state = SCSI_THREAD_IDENT_ABORTING;
  2134. }
  2135.     else
  2136. {
  2137.      ncr810ThreadReconnect ((NCR810_THREAD *) pNewThread);
  2138.      state = SCSI_THREAD_INACTIVE;
  2139. }
  2140.     break;
  2141. case SCSI_IDENT_FAILED:
  2142.     state = SCSI_THREAD_IDENT_ABORTING;
  2143.     break;
  2144. default:
  2145.     logMsg ("ncr810IdentInContinue: invalid ident status (%d)n",
  2146.               status, 0, 0, 0, 0, 0);
  2147.     state = SCSI_THREAD_INACTIVE;
  2148.     break;
  2149. }
  2150.     if (state == SCSI_THREAD_IDENT_ABORTING)
  2151. ncr810ThreadAbort ((SIOP *) pScsiCtrl, pThread);
  2152.     ncr810ThreadStateSet (pThread, state);
  2153.     }
  2154. /*******************************************************************************
  2155. *
  2156. * ncr810ThreadReconnect - reconnect a thread
  2157. *
  2158. * Restore the SCSI pointers for the thread (this really should be in a more
  2159. * generic section of code - perhaps part of the SCSI manager's thread event
  2160. * procesing ?).  Update the newly-connected thread's context (including
  2161. * shared memory area) and resume it.  Set the thread's state to ESTABLISHED.
  2162. *
  2163. * RETURNS: N/A
  2164. *
  2165. * NOMANUAL
  2166. */
  2167. LOCAL void ncr810ThreadReconnect
  2168.     (
  2169.     NCR810_THREAD * pThread
  2170.     )
  2171.     {
  2172.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  2173.     SCSI_CTRL   * pScsiCtrl   = pScsiThread->pScsiCtrl;
  2174.     SIOP        * pSiop       = (SIOP *) pScsiCtrl;
  2175.     
  2176.     SCSI_DEBUG_MSG ("ncr810ThreadReconnect: reconnecting thread 0x%08xn",
  2177.     (int) pThread, 0, 0, 0, 0, 0);
  2178.     pScsiCtrl->pThread = pScsiThread;
  2179.     /* Implied RESTORE POINTERS action: see "scsiMsgInComplete ()" */
  2180.     pScsiThread->activeDataAddress = pScsiThread->savedDataAddress;
  2181.     pScsiThread->activeDataLength  = pScsiThread->savedDataLength;
  2182.     ncr810ThreadUpdate (pThread);
  2183.     if (ncr810Resume (pSiop, pThread, NCR810_SCRIPT_INIT_CONTINUE) != OK)
  2184. {
  2185. SCSI_ERROR_MSG ("ncr810ThreadReconnect: failed to resume thread.n",
  2186. 0, 0, 0, 0, 0, 0);
  2187. ncr810ThreadFail (pThread, S_scsiLib_DISCONNECTED);
  2188. return;
  2189. }
  2190.     ncr810ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  2191.     }
  2192. /*******************************************************************************
  2193. *
  2194. * ncr810SharedMemInit - initialize the fields in a shared memory area
  2195. *
  2196. * Initialise pointers and counts for all message transfers.  These are
  2197. * always directed to buffers provided by the SCSI_CTRL structure.
  2198. *
  2199. * RETURNS: N/A
  2200. *
  2201. * NOMANUAL
  2202. */
  2203. LOCAL void ncr810SharedMemInit
  2204.     (
  2205.     SIOP *          pSiop,
  2206.     NCR810_SHARED * pShMem
  2207.     )
  2208.     {
  2209.     /*
  2210.      * Note: All the values being set in the shared memory need to be
  2211.      * 32 bit byte swapped. Actual swapping takes place when, when memory
  2212.      * is big endian (since the NCR8xx is a little endian PCI device. 
  2213.      * Otherwise, if memory is little endian then the byte swapping 
  2214.      * does not do anything. The "endianness" is configurable at compile
  2215.      * time.
  2216.      *
  2217.      * Similarly, a PCI offset is added to all addresses so that the
  2218.      * NCR8xx PCI chip can get to memory. This value is also configurable
  2219.      * at compile time.
  2220.      */
  2221.     pShMem->identIn.size = NCR810_SWAP_32(1);
  2222.     pShMem->identIn.addr = (UINT8 *) NCR810_SWAP_32(
  2223.  NCR810_VIRT_TO_PHYS 
  2224.             (pSiop->scsiCtrl.identBuf)
  2225.  );
  2226.     pShMem->msgOut.size = NCR810_SWAP_32(0); /* set dynamically */
  2227.     pShMem->msgOut.addr = (UINT8 *) NCR810_SWAP_32(
  2228.         NCR810_VIRT_TO_PHYS 
  2229.    (pSiop->scsiCtrl.msgOutBuf)
  2230. );
  2231.     
  2232.     pShMem->msgIn.size  = NCR810_SWAP_32(1);
  2233.     pShMem->msgIn.addr  = (UINT8 *) NCR810_SWAP_32(
  2234. NCR810_VIRT_TO_PHYS 
  2235.    (pSiop->scsiCtrl.msgInBuf)
  2236. );
  2237.     pShMem->msgInSecond.size = NCR810_SWAP_32(1);
  2238.     pShMem->msgInSecond.addr = (UINT8 *) NCR810_SWAP_32(
  2239.      NCR810_VIRT_TO_PHYS 
  2240.              (pSiop->scsiCtrl.msgInBuf)
  2241.       + (UINT) 1
  2242.      );
  2243.     pShMem->msgInRest.size   = NCR810_SWAP_32(0);   /* set dynamically */
  2244.     pShMem->msgInRest.addr   = (UINT8 *) NCR810_SWAP_32
  2245.      (
  2246.      NCR810_VIRT_TO_PHYS
  2247.      (pSiop->scsiCtrl.msgInBuf)
  2248.      + (UINT) 2
  2249.      );
  2250.     }
  2251. /*******************************************************************************
  2252. *
  2253. * ncr810ThreadInit - initialize a client thread structure
  2254. *
  2255. * Initialize the fixed data for a thread (i.e., independent of the command).
  2256. * Called once when a thread structure is first created.
  2257. *
  2258. * RETURNS: OK, or ERROR if an error occurs
  2259. *
  2260. * NOMANUAL
  2261. */
  2262. LOCAL STATUS ncr810ThreadInit
  2263.     (
  2264.     SIOP *          pSiop,
  2265.     NCR810_THREAD * pThread
  2266.     )
  2267.     {
  2268.     if (scsiThreadInit (&pThread->scsiThread) != OK)
  2269. return (ERROR);
  2270.     
  2271.     pThread->pShMem = pSiop->pClientShMem;
  2272.     pThread->scntl3 = pSiop->clkDiv;
  2273.     return (OK);
  2274.     }
  2275.     
  2276. /*******************************************************************************
  2277. *
  2278. * ncr810IdentThreadInit - initialize an identification thread structure
  2279. *
  2280. * Set up pointers and counts for all buffers other than messages.  Also set
  2281. * transfer parameters for asynchronous mode, and update the shared memory
  2282. * area to match this thread.
  2283. *
  2284. * NOTE:
  2285. * The pointers/counts set here are normally never used by the identification
  2286. * thread; however, when an identification thread is aborted, it's possible
  2287. * that the target will attempt to transfer one or more non-message bytes
  2288. * before requesting the abort message out.  To handle this, the thread's
  2289. * pointers and counts all specify a dummy buffer.  There is no re-entrancy
  2290. * problem here because we do not care what data is transferred.  This might
  2291. * be handled more elegantly if there were a special script entry to abort
  2292. * an identification thread.
  2293. *
  2294. * RETURNS: OK, or ERROR if an error occurs
  2295. *
  2296. * NOMANUAL
  2297. */
  2298. LOCAL STATUS ncr810IdentThreadInit
  2299.     (
  2300.     NCR810_THREAD * pThread
  2301.     )
  2302.     {
  2303.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  2304.     SIOP *        pSiop       = (SIOP *) pScsiThread->pScsiCtrl;
  2305.     static UINT8  dummy;
  2306.     
  2307.     /*
  2308.      * Initialise Pointers and counts in thread
  2309.      */
  2310.     pScsiThread->cmdLength         = 1;
  2311.     pScsiThread->cmdAddress        = &dummy;
  2312.     pScsiThread->dataLength        = 1;
  2313.     pScsiThread->dataAddress       = &dummy;
  2314.     pScsiThread->activeDataLength  = 1;
  2315.     pScsiThread->activeDataAddress = &dummy;
  2316.     pScsiThread->savedDataLength   = 1;
  2317.     pScsiThread->savedDataAddress  = &dummy;
  2318.     pScsiThread->statusLength      = 1;
  2319.     pScsiThread->statusAddress     = &dummy;
  2320.     pScsiThread->identMsgLength    = 1;
  2321.     
  2322.     /*
  2323.      * Initialise SIOP register context in thread
  2324.      */
  2325.     pThread->nHostFlags   = 0;
  2326.     pThread->nMsgOutState = SCSI_MSG_OUT_NONE;
  2327.     pThread->nMsgInState  = SCSI_MSG_IN_NONE;
  2328.     pThread->sxfer = NCR810_SYNC_XFER_PARAMS_ASYNC;
  2329. /* XXX hard code for now. Will need to REDISIGN */
  2330.   /*  pThread->scntl3 = pSiop->clkDiv; */
  2331.     pThread->scntl3 = 0x3; 
  2332.     /*
  2333.      * Initialise shared memory area
  2334.      */
  2335.     pThread->pShMem = pSiop->pIdentShMem;
  2336.     
  2337.     ncr810SharedMemInit (pSiop, pThread->pShMem);
  2338.     ncr810ThreadUpdate (pThread);
  2339.     
  2340.     return (OK);
  2341.     }
  2342. /*******************************************************************************
  2343. *
  2344. * ncr810ThreadUpdate - update the thread structure for a current SCSI command
  2345. *
  2346. * Update the dynamic data (e.g. data pointers, transfer parameters) in
  2347. * the thread to reflect the latest state of the corresponding physical device.
  2348. *
  2349. * RETURNS: N/A
  2350. *
  2351. * NOMANUAL
  2352. */
  2353. LOCAL void ncr810ThreadUpdate
  2354.     (
  2355.     NCR810_THREAD * pThread /* thread info */
  2356.     )
  2357.     {
  2358.     SCSI_THREAD   * pScsiThread = (SCSI_THREAD *) pThread;
  2359.     SCSI_CTRL     * pScsiCtrl   = pScsiThread->pScsiCtrl;
  2360.     SIOP          * pSiop       = (SIOP *) pScsiCtrl;
  2361.     NCR810_SHARED * pShMem      = pThread->pShMem;
  2362.     UINT            flags       = 0;
  2363.     UINT            msgOutSize;
  2364.     UINT            msgInSize;
  2365.     /*
  2366.      *  If there is an identification message, ensure ATN is asserted
  2367.      * during (re)selection.
  2368.      */
  2369.     if (pScsiThread->identMsgLength != 0)
  2370. flags |= FLAGS_IDENTIFY;
  2371.     /*
  2372.      * Update SIOP register context
  2373.      */
  2374.     pThread->nHostFlags   = (UCHAR)flags;
  2375.     pThread->nMsgOutState = (UCHAR)pScsiCtrl->msgOutState;
  2376.     pThread->nMsgInState  = (UCHAR)pScsiCtrl->msgInState;
  2377.     /*
  2378.      * Update dynamic message in/out sizes
  2379.      */
  2380.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_NONE)
  2381. msgOutSize = 0;
  2382.     else
  2383. msgOutSize = pScsiCtrl->msgOutLength;
  2384.     if (pScsiCtrl->msgInState != SCSI_MSG_IN_EXT_MSG_DATA)
  2385. msgInSize = 0;
  2386.     
  2387.     else if ((msgInSize = pScsiCtrl->msgInBuf[SCSI_EXT_MSG_LENGTH_BYTE]) == 0)
  2388. msgInSize = SCSI_EXT_MSG_MAX_LENGTH;
  2389.     /*
  2390.      * Update shared memory area
  2391.      */
  2392.     pShMem->command.size  = NCR810_SWAP_32(pScsiThread->cmdLength);
  2393.     pShMem->command.addr  = (UINT8 *) NCR810_SWAP_32
  2394.   (
  2395.   (UINT32) NCR810_VIRT_TO_PHYS
  2396.   ((UINT) pScsiThread->cmdAddress)
  2397.   );
  2398.     pShMem->data.size     = NCR810_SWAP_32(pScsiThread->activeDataLength);
  2399.     pShMem->data.addr     = (UINT8 *) NCR810_SWAP_32( 
  2400.   (UINT32) NCR810_VIRT_TO_PHYS
  2401. ((UINT) pScsiThread->activeDataAddress)
  2402.   );
  2403.     pShMem->status.size   = NCR810_SWAP_32(pScsiThread->statusLength);
  2404.     pShMem->status.addr   = (UINT8 *) NCR810_SWAP_32
  2405.   (
  2406.   (UINT32) NCR810_VIRT_TO_PHYS
  2407.   ((UINT) pScsiThread->statusAddress)
  2408.   );
  2409.     /* These used to be pScsiThread->identMsg/identMsgLength */
  2410.     pShMem->identOut.size = NCR810_SWAP_32(pSiop->identMsgLength);
  2411.     pShMem->identOut.addr = (UINT8 *) NCR810_SWAP_32
  2412.   (
  2413.   (UINT32) NCR810_VIRT_TO_PHYS
  2414.   ((UINT) pSiop->identMsg)
  2415.   );
  2416.     pShMem->msgOut.size    = NCR810_SWAP_32(msgOutSize);
  2417.     pShMem->msgInRest.size = NCR810_SWAP_32(msgInSize);
  2418.     }
  2419. /*******************************************************************************
  2420. *
  2421. * ncr810ThreadComplete - successfully complete execution of a client thread
  2422. *
  2423. * Set the thread status and errno appropriately, depending on whether or
  2424. * not the thread has been aborted.  Set the thread inactive, and notify
  2425. * the SCSI manager of the completion.
  2426. *
  2427. * RETURNS: N/A
  2428. *
  2429. * NOMANUAL
  2430. */
  2431. LOCAL void ncr810ThreadComplete
  2432.     (
  2433.     NCR810_THREAD * pThread
  2434.     )
  2435.     {
  2436.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  2437.     
  2438.     SCSI_DEBUG_MSG ("ncr810ThreadComplete: thread 0x%08x completedn",
  2439.     (int) pThread, 0, 0, 0, 0, 0);
  2440.     if (pScsiThread->state == SCSI_THREAD_ABORTING)
  2441. {
  2442. pScsiThread->status = ERROR;
  2443. pScsiThread->errNum = S_scsiLib_ABORTED;
  2444. }
  2445.     else
  2446. {
  2447.      pScsiThread->status = OK;
  2448.      pScsiThread->errNum = 0;
  2449.      }
  2450.     
  2451.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  2452.     scsiCacheSynchronize (pScsiThread, SCSI_CACHE_POST_COMMAND);
  2453.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);
  2454.     }
  2455. /*******************************************************************************
  2456. *
  2457. * ncr810ThreadDefer - defer execution of a thread
  2458. *
  2459. * Set the thread's state to INACTIVE and notify the SCSI manager of the
  2460. * deferral event.
  2461. *
  2462. * RETURNS: N/A
  2463. *
  2464. * NOMANUAL
  2465. */
  2466. LOCAL void ncr810ThreadDefer
  2467.     (
  2468.     NCR810_THREAD * pThread
  2469.     )
  2470.     {
  2471.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  2472.     
  2473.     SCSI_DEBUG_MSG ("ncr810ThreadDefer: thread 0x%08x deferredn",
  2474.     (int) pThread, 0, 0, 0, 0, 0);
  2475.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  2476.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DEFERRED);
  2477.     }
  2478.     
  2479. /*******************************************************************************
  2480. *
  2481. * ncr810ThreadFail - complete execution of a thread, with error status
  2482. *
  2483. * Set the thread's status and errno according to the type of error.  Set
  2484. * the thread's state to INACTIVE, and notify the SCSI manager of the
  2485. * completion event.
  2486. *
  2487. * RETURNS: N/A
  2488. *
  2489. * NOMANUAL
  2490. */
  2491. LOCAL void ncr810ThreadFail
  2492.     (
  2493.     NCR810_THREAD * pThread,
  2494.     int             errNum
  2495.     )
  2496.     {
  2497.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  2498.     
  2499.     SCSI_DEBUG_MSG ("ncr810ThreadFail: thread 0x%08x failed (errno = %d)n",
  2500.     (int) pThread, errNum, 0, 0, 0, 0);
  2501.     pScsiThread->status = ERROR;
  2502.     if (pScsiThread->state == SCSI_THREAD_ABORTING)
  2503. pScsiThread->errNum = S_scsiLib_ABORTED;
  2504.     else
  2505.      pScsiThread->errNum = errNum;
  2506.     
  2507.     ncr810ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
  2508.     scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);
  2509.     }
  2510.     
  2511. /******************************************************************************
  2512. *
  2513. * ncr810ThreadStateSet - set the state of a thread
  2514. *
  2515. * This is really just a place-holder for debugging and possible future
  2516. * enhancements such as state-change logging.
  2517. *
  2518. * RETURNS: N/A
  2519. *
  2520. * NOMANUAL
  2521. */
  2522. LOCAL void ncr810ThreadStateSet
  2523.     (
  2524.     NCR810_THREAD *   pThread, /* ptr to thread info */
  2525.     SCSI_THREAD_STATE state
  2526.     )
  2527.     {
  2528.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  2529.     
  2530.     SCSI_DEBUG_MSG ("ncr810ThreadStateSet: thread 0x%08x: %d -> %dn",
  2531.     (int) pThread, pScsiThread->state, state, 0, 0, 0);
  2532.     pScsiThread->state = state;
  2533.     }
  2534. /******************************************************************************
  2535. *
  2536. * ncr810Activate - activate a script corresponding to a new thread
  2537. *
  2538. * Request activation of (the script for) a new thread, if possible; do not
  2539. * wait for the script to complete (or even start) executing.  Activation
  2540. * is requested by signalling the controller, which causes an interrupt.
  2541. * The script is started by the ISR in response to this event.
  2542. *
  2543. * There is a race condition inherent in SCSI between the synchronous
  2544. * activation of a thread (i.e., execution of this routine) and asynchronous
  2545. * activation of a thread as a result of selection or reselection.  The SCSI
  2546. * manager is designed to take account of this, and assumes that either the
  2547. * new thread has been successfully activated or a (re)selection has taken
  2548. * place, as determined by the next event it receives.  In the case when
  2549. * (re)selection occurs, the current activation request is deferred and
  2550. * retried later.
  2551. *
  2552. * Therefore, an activation request is lodged only if the controller is
  2553. * currently PASSIVE (waiting for (re)selection or a host command).  If the
  2554. * controller is IDLE, (re)selection is assumed to have already occurred.
  2555. * Note that this is not an error condition; there is no way for the
  2556. * caller to distinguish the two cases, because even if the thread appears
  2557. * to have been activated it may yet be "pre-empted" by (re)selection.
  2558. *
  2559. * The controller should never be ACTIVE.  If it is, the SCSI manager has
  2560. * tried to activate multiple concurrent threads on the controller, which
  2561. * indicates a major (software) disaster.
  2562. *
  2563. * NOTE: Interrupt locking is required to ensure that the correct action
  2564. * is taken once the controller state has been checked.
  2565. *
  2566. * RETURNS: OK, or ERROR if the controller is in an invalid state (this
  2567. * indicates a major software failure).
  2568. *
  2569. * NOMANUAL
  2570. */
  2571. LOCAL STATUS ncr810Activate
  2572.     (
  2573.     SIOP *          pSiop,
  2574.     NCR810_THREAD * pThread
  2575.     )
  2576.     {
  2577.     STATUS status;
  2578.     BOOL   sienMasked = TRUE; 
  2579.     int key;
  2580.     if (pSiop->cmdPending)
  2581. {
  2582. logMsg ("ncr810Activate: activation request already pending !n",
  2583. 0, 0, 0, 0, 0, 0);
  2584. return (ERROR);
  2585. }
  2586.     
  2587.     /*
  2588.      * Check controller state, set a new command pending and signal it
  2589.      *  if necessary.
  2590.      */
  2591.     key = intLock();
  2592.     
  2593.     switch (pSiop->state)
  2594. {
  2595. case NCR810_STATE_IDLE:
  2596.     status = OK;
  2597.     break;
  2598. case NCR810_STATE_PASSIVE:  /* do nothing */
  2599.     pSiop->pNewThread = pThread;
  2600.     pSiop->cmdPending = TRUE;
  2601.             /* 
  2602.      * Signal the wait for (re) select script which then jumps to
  2603.      * the relative alternate address. 
  2604.      */
  2605.     intUnlock (key);
  2606.             CACHE_PIPE_FLUSH();
  2607.     NCR810_OUT_BYTE(pSiop->pIstat, NCR810_IN_BYTE(pSiop->pIstat) |
  2608.     ISTAT_SIGP);
  2609.     status = OK;
  2610.             sienMasked = FALSE;
  2611.     break;
  2612.     
  2613. case NCR810_STATE_ACTIVE:
  2614. default:
  2615.     status = ERROR;
  2616.     break;
  2617. }
  2618.     if (sienMasked)
  2619.         {
  2620.         intUnlock (key);
  2621.         }
  2622.     if (status != OK)
  2623. {
  2624. logMsg ("ncr810Activate: invalid controller state.n",
  2625. pSiop->state, 0, 0, 0, 0, 0);
  2626. errnoSet (S_scsiLib_SOFTWARE_ERROR);
  2627. }
  2628.     return (status);
  2629.     }
  2630. /*******************************************************************************
  2631. *
  2632. * ncr810Resume - resume a script corresponding to a suspended thread
  2633. *
  2634. * NOTE: the script can only be resumed if the controller is currently idle.
  2635. * To avoid races, interrupts must be locked while this is checked and the
  2636. * script re-started.
  2637. *
  2638. * Reasons why the controller might not be idle include SCSI bus reset and
  2639. * unexpected disconnection, both of which might occur in practice.  Hence
  2640. * this is not considered to be a major software error.
  2641. *
  2642. * RETURNS: OK, or ERROR if the controller is in an invalid state (this
  2643. * should not be treated as a major software failure).
  2644. *
  2645. * NOMANUAL
  2646. */
  2647. LOCAL STATUS ncr810Resume
  2648.     (
  2649.     SIOP *              pSiop, /* ptr to controller info          */
  2650.     NCR810_THREAD *     pThread, /* ptr to thread info              */
  2651.     NCR810_SCRIPT_ENTRY entryId /* entry point of script to resume */
  2652.     )
  2653.     {
  2654.     STATUS status;
  2655.     BOOL   sienMasked = TRUE; 
  2656.     int key;
  2657.     /*
  2658.      * Check validity of connection and start script if OK
  2659.      */
  2660.     key = intLock();
  2661.     switch (pSiop->state)
  2662. {
  2663. case NCR810_STATE_IDLE:
  2664.             SCSI_INT_DEBUG_MSG ("ncr810Resume: thread: 0x%08x:"
  2665.                                 " state %d -> %dn",
  2666.                                 (int) pThread,
  2667.                                 NCR810_STATE_IDLE, NCR810_STATE_ACTIVE,
  2668.                                 0, 0, 0);
  2669.     intUnlock (key);
  2670.     ncr810ScriptStart (pSiop, pThread, entryId);
  2671.             
  2672.     pSiop->state = NCR810_STATE_ACTIVE;
  2673.             sienMasked = FALSE;
  2674.     status = OK;
  2675.     break;
  2676. case NCR810_STATE_PASSIVE:
  2677. case NCR810_STATE_ACTIVE:
  2678. default:
  2679.     status = ERROR;
  2680.     break;
  2681. }
  2682.     if (sienMasked)
  2683.         {
  2684.         intUnlock (key);
  2685.         }
  2686.     return (status);
  2687.     }
  2688. /*******************************************************************************
  2689. *
  2690. * ncr810Abort - abort the active script corresponding to the current thread
  2691. *
  2692. * Check that there is currently an active script running.  If so, set the
  2693. * SIOP's Abort flag which will halt the script and cause an interrupt.
  2694. *
  2695. * RETURNS: N/A
  2696. *
  2697. * NOMANUAL
  2698. */
  2699. LOCAL void ncr810Abort
  2700.     (
  2701.     SIOP * pSiop /* ptr to controller info */
  2702.     )
  2703.     {
  2704.     STATUS status;
  2705.     int key;
  2706.     key = intLock();
  2707.     switch (pSiop->state)
  2708. {
  2709. case NCR810_STATE_IDLE:
  2710. case NCR810_STATE_PASSIVE:
  2711.     status = OK;
  2712.     break;
  2713. case NCR810_STATE_ACTIVE:
  2714.             CACHE_PIPE_FLUSH();
  2715.     NCR810_OUT_BYTE(pSiop->pIstat, NCR810_IN_BYTE(pSiop->pIstat) |
  2716.     ISTAT_ABRT);
  2717.     status = OK;
  2718.     break;
  2719.     
  2720. default:
  2721.     status = ERROR;
  2722.     break;
  2723. }
  2724.     intUnlock (key);
  2725.     if (status != OK)
  2726. {
  2727. logMsg ("ncr810Abort: thread = 0x%08x: invalid state (%d)n",
  2728. pSiop->state, 0, 0, 0, 0, 0);
  2729. }
  2730.     }
  2731. /*******************************************************************************
  2732. *
  2733. * ncr810ScriptStart - start the SIOP executing a script
  2734. *
  2735. * Restore the SIOP register context, including the shared memory area, from
  2736. * the thread context.  Put the address of the script entry point into the
  2737. * DSP register.  If not in single-step mode, start the script.
  2738. *
  2739. * NOTE: should always be called with SIOP interrupts locked.
  2740. *
  2741. * RETURNS: N/A
  2742. * NOMANUAL
  2743. */
  2744. LOCAL void ncr810ScriptStart
  2745.     (
  2746.     SIOP               *pSiop, /* pointer to  SIOP info */
  2747.     NCR810_THREAD      *pThread, /* ncr thread info */
  2748.     NCR810_SCRIPT_ENTRY entryId /* routine address entry point */
  2749.     )
  2750.     {
  2751.     /*
  2752.      * Script entry point addresses.  These are resolved by PROCs
  2753.      * defined in the script itself (see "ncr810init.n").
  2754.      *
  2755.      * NOTE: The number and order of members of this array _must_ match
  2756.      * the enum NCR810_SCRIPT_ENTRY.
  2757.      */
  2758.     static ULONG * ncr810ScriptEntry [] =
  2759. {
  2760.         ncr810Wait, /* wait for re-select or host cmd   */
  2761.      ncr810InitStart, /* start an initiator thread        */
  2762.      ncr810InitContinue, /* continue an initiator thread     */
  2763. ncr810TgtDisconnect,       /* disconnect a target thread       */
  2764. };    
  2765.     /*
  2766.      * Set current hardware thread pointer for ISR
  2767.      */
  2768.     pSiop->pHwThread = pThread;
  2769.     /*
  2770.      * Restore the SIOP register context for this thread.
  2771.      */
  2772.     NCR810_OUT_BYTE(pSiop->pScratcha0, pThread->scratcha0);
  2773.     NCR810_OUT_BYTE(pSiop->pScratcha1, pThread->scratcha1);
  2774.     NCR810_OUT_BYTE(pSiop->pScratcha2, pThread->scratcha2);
  2775.     NCR810_OUT_BYTE(pSiop->pScratcha3, pThread->scratcha3);
  2776.     NCR810_OUT_BYTE(pSiop->pScntl3, pThread->scntl3);
  2777.     NCR810_OUT_BYTE(pSiop->pSxfer,  pThread->sxfer);
  2778.     /*
  2779.      * Set the shared data address, load the script start address,
  2780.      * then start the SIOP unless it's in single-step mode.
  2781.      */
  2782.     NCR810_OUT_32(pSiop->pDsa, (UINT32)NCR810_VIRT_TO_PHYS (pThread->pShMem));
  2783.     NCR810_OUT_32(pSiop->pDsp, (UINT32)NCR810_VIRT_TO_PHYS(
  2784. (UINT32)ncr810ScriptEntry[entryId]));
  2785.     if (pSiop->singleStep)
  2786. {
  2787. logMsg ("ncr810ScriptStart: single-step required to start scriptn",
  2788. 0, 0, 0, 0, 0, 0);
  2789. }
  2790.     else
  2791. {
  2792.         CACHE_PIPE_FLUSH();
  2793. NCR810_OUT_BYTE(pSiop->pDcntl, NCR810_IN_BYTE(pSiop->pDcntl) |
  2794. DCNTL_STD); 
  2795.         /*
  2796.          * inOrderExecute() is a BSP specific routine that makes sure that
  2797.          * the SCSI registers written above are executed in order and completely
  2798.          * before continuing on. In the case of the faster PPC processors, it
  2799.          * has been found that without this flushing of the pipes the processor
  2800.          * is much faster than the SIOP, and causes erratic behaviour like bus
  2801.          * errors and invalid events.
  2802.          */
  2803.         CACHE_PIPE_FLUSH();
  2804.         ncr810Delay (); /* XXX - needs to be understood better for fast PPCs */
  2805. CACHE_PIPE_FLUSH();
  2806. }
  2807.     }
  2808. /*******************************************************************************
  2809. *
  2810. * ncr810ThreadParamsSet - set various parameters for a thread
  2811. *
  2812. * Parameters include transfer offset and period, as well as the ID of the
  2813. * target device.  All of these end up as encoded values stored either in
  2814. * the thread's register context or its associated shared memory area.
  2815. *
  2816. * Transfer period is specified in SCSI units (multiples of 4 ns).  An offset
  2817. * of zero specifies asynchronous transfer.
  2818. *
  2819. * RETURNS: OK if parameters are OK, else ERROR.
  2820. *
  2821. * NOMANUAL
  2822. */
  2823. LOCAL STATUS ncr810ThreadParamsSet
  2824.     (
  2825.     NCR810_THREAD * pThread,      /* thread to be affected  */
  2826.     UINT8           offset, /* max REQ/ACK offset     */
  2827.     UINT8           period /* min transfer period    */
  2828.     )
  2829.     {
  2830.     SCSI_THREAD *   pScsiThread = (SCSI_THREAD *) pThread;
  2831.     SIOP *          pSiop       = (SIOP *) pScsiThread->pScsiCtrl;
  2832.     SCSI_TARGET *   pScsiTarget = pScsiThread->pScsiTarget;
  2833.     UINT            busId       = pScsiTarget->scsiDevBusId;
  2834.     UINT8     xferWidth   = pScsiTarget->xferWidth;
  2835.     NCR810_SHARED * pShMem      = pThread->pShMem;
  2836.     if (!ncr810XferParamsCvt (pSiop, &offset, &period, &pThread->sxfer,
  2837.                                &pThread->scntl3))
  2838. { /* should never happen */
  2839. errnoSet (S_scsiLib_ILLEGAL_PARAMETER);
  2840. return (ERROR);
  2841. }
  2842.     /* Do we want a wide (16 bit) transfer ? */
  2843.     if (xferWidth == SCSI_WIDE_XFER_SIZE_DEFAULT)
  2844.         {
  2845.         pThread->scntl3 |= SCNTL3_EWS;
  2846.         }
  2847.     pShMem->device = NCR810_SWAP_32(
  2848.          (pThread->sxfer <<  NCR810_XFER_PARAMS_SHIFT) |
  2849.                          (busId << NCR810_TARGET_BUS_ID_SHIFT) |
  2850.          (pThread->scntl3 << 24)
  2851.  );
  2852.     return (OK);
  2853.     }
  2854. /*******************************************************************************
  2855. *
  2856. * ncr810XferParamsQuery - get (synchronous) transfer parameters
  2857. *
  2858. * Updates the synchronous transfer parameters suggested in the call to match
  2859. * the NCR 53C810's capabilities.  Transfer period is in SCSI units (multiples
  2860. * of 4 ns).
  2861. *
  2862. * Note: the transfer period is made longer and the offset is made smaller if
  2863. * the NCR 53C810 cannot handle the specified values.
  2864. *
  2865. * RETURNS: OK
  2866. *
  2867. * NOMANUAL
  2868. */
  2869. LOCAL STATUS ncr810XferParamsQuery
  2870.     (
  2871.     SCSI_CTRL *pScsiCtrl, /* ptr to controller info       */
  2872.     UINT8     *pOffset, /* max REQ/ACK offset  [in/out] */
  2873.     UINT8     *pPeriod /* min transfer period [in/out] */
  2874.     )
  2875.     {
  2876.     UINT8 unused;
  2877.     (void) ncr810XferParamsCvt ((SIOP *) pScsiCtrl, pOffset, pPeriod,
  2878. &unused, &unused);
  2879.     
  2880.     return (OK);
  2881.     }
  2882. /*******************************************************************************
  2883. *
  2884. * ncr810WideXferParamsQuery - get wide data transfer parameters
  2885. *
  2886. * Updates the wide data transfer parameters suggested in the call to match
  2887. * the NCR 53C810's capabilities.  Transfer width is in the units 
  2888. * of the WIDE DATA TRANSFER message's transfer width exponent field. This is
  2889. * an 8 bit field where 0 represents a narrow transfer of 8 bits, 1 represents
  2890. * a wide transfer of 16 bits and 2 represents a wide transfer of 32 bits.
  2891. *
  2892. * Note: the transfer width is made smaller if the NCR 53C810 cannot handle 
  2893. * the specified value.
  2894. *
  2895. * RETURNS: OK
  2896. *
  2897. * NOMANUAL
  2898. */
  2899. LOCAL STATUS ncr810WideXferParamsQuery
  2900.     (
  2901.     SCSI_CTRL *pScsiCtrl, /* ptr to controller info       */
  2902.     UINT8     *xferWidth /* suggested transfer width     */
  2903.     )
  2904.     {
  2905.     if (*xferWidth > NCR810_MAX_XFER_WIDTH)
  2906. *xferWidth = NCR810_MAX_XFER_WIDTH;
  2907.     
  2908.     ncr810WideXferParamsSet (pScsiCtrl, *xferWidth);
  2909.     return (OK);
  2910.     }
  2911. /*******************************************************************************
  2912. *
  2913. * ncr810XferParamsSet - set transfer parameters
  2914. *
  2915. * Validate the requested parameters, convert to the NCR 53C810's native
  2916. * format and save in the current thread for later use (the chip's registers
  2917. * are not actually set until the next script activation for this thread).
  2918. *
  2919. * Transfer period is specified in SCSI units (multiples of 4 ns).  An offset
  2920. * of zero specifies asynchronous transfer.
  2921. *
  2922. * RETURNS: OK if transfer parameters are OK, else ERROR.
  2923. *
  2924. * NOMANUAL
  2925. */
  2926. LOCAL STATUS ncr810XferParamsSet
  2927.     (
  2928.     SCSI_CTRL *pScsiCtrl, /* ptr to controller info */
  2929.     UINT8      offset, /* max REQ/ACK offset     */
  2930.     UINT8      period /* min transfer period    */
  2931.     )
  2932.     {
  2933.     NCR810_THREAD * pThread = (NCR810_THREAD *) pScsiCtrl->pThread;
  2934.     return (ncr810ThreadParamsSet (pThread, offset, period));
  2935.     }
  2936. /*******************************************************************************
  2937. *
  2938. * ncr810WideXferParamsSet - set wide transfer parameters
  2939. *
  2940. * Assume valid parameters and set the NCR810's thread parameters to the
  2941. * appropriate values. The actual registers are not written yet, but will
  2942. * be written from the thread values when it is activated.
  2943. *
  2944. * Transfer width is specified in SCSI transfer width exponent units. 
  2945. *
  2946. * RETURNS: OK 
  2947. *
  2948. * NOMANUAL
  2949. */
  2950. LOCAL STATUS ncr810WideXferParamsSet
  2951.     (
  2952.     SCSI_CTRL *pScsiCtrl, /* ptr to controller info */
  2953.     UINT8      xferWidth  /* wide data transfer width */
  2954.     )
  2955.     {
  2956.     NCR810_THREAD * pThread = (NCR810_THREAD *) pScsiCtrl->pThread;
  2957.     if (NULL == pThread) 
  2958.         {
  2959.         logMsg("pThread is NULL POINTER",0,0,0,0,0,0); 
  2960.         return(ERROR); 
  2961.         }
  2962.     if (xferWidth == SCSI_WIDE_XFER_SIZE_NARROW)
  2963. {
  2964. pThread->scntl3 &= ~SCNTL3_EWS; /* Disable wide scsi data transfers */
  2965. }
  2966.     else
  2967. {
  2968.         pThread->scntl3 |= SCNTL3_EWS; /* Enable wide scsi data transfers */
  2969. }
  2970.     return (OK);
  2971.     }
  2972. /*******************************************************************************
  2973. *
  2974. * ncr810XferParamsCvt - convert transfer period from SCSI to NCR 53C810 units
  2975. *
  2976. * Given a "suggested" REQ/ACK offset and transfer period (in SCSI units of
  2977. * 4 ns), return the nearest offset and transfer period the NCR 53C810 is
  2978. * capable of using.  Also return the corresponding values of the NCR 53C810's
  2979. * Synchronous Transfer and Synchronous Bus Control registers.
  2980. *
  2981. * An offset of zero specifies asynchronous transfer, in which case the period
  2982. * is irrelevant.  Otherwise, the offset may be clipped to be within the
  2983. * maximum limit the NCR 53C810 is capable of.
  2984. *
  2985. * The transfer period is normally rounded towards longer periods if the NCR
  2986. * 53C810 is not capable of using the exact specified value.  The period may
  2987. * also be clipped to be within the NCR 53C810's maximum and minimum limits
  2988. * according to its clock period.
  2989. *
  2990. * If either the offset or period need to be clipped, the value FALSE is
  2991. * retuned as this may reflect an error condition.
  2992. *
  2993. * RETURNS: TRUE if input period is within NCR 53C810's range, else FALSE
  2994. *
  2995. * NOMANUAL
  2996. */
  2997. LOCAL BOOL ncr810XferParamsCvt
  2998.     (
  2999.     FAST SIOP  *pSiop, /* ptr to controller info            */
  3000.     FAST UINT8 *pOffset, /* REQ/ACK offset                    */
  3001.     FAST UINT8 *pPeriod, /* xfer period, SCSI units (x 4 ns)  */
  3002.     FAST UINT8 *pXferParams, /* corresponding Sync Xfer Reg value */
  3003.     FAST UINT8 *pClockDiv /* corresponding clock division bits */
  3004.     )
  3005.     {
  3006.     UINT  offset  = (UINT) *pOffset;
  3007.     UINT  period  = (UINT) *pPeriod;
  3008.     UINT  xferp;
  3009.     UINT  sccpDiv;
  3010.     UINT8 clkDiv;
  3011.     UINT8 xferParams;
  3012.     UINT8 clockDivide;
  3013.     UINT  sccp; /* Scsi Core Clock Period */
  3014.     if (offset == SCSI_SYNC_XFER_ASYNC_OFFSET)
  3015. {
  3016. xferParams  = NCR810_SYNC_XFER_PARAMS_ASYNC;
  3017. clockDivide = pSiop->clkDiv; 
  3018. offset = SCSI_SYNC_XFER_ASYNC_OFFSET;
  3019. period = 0;
  3020.      }
  3021.     else
  3022. {
  3023. SCSI_DEBUG_MSG ("ncr810XferParamsCvt: requested: "
  3024. "offset = %d, period = %dn",
  3025.      offset, period, 0, 0, 0, 0);
  3026.         /* Default sccpDiv and clkDiv values for SCLK <= 50MHz */
  3027. sccpDiv = 100;
  3028. clkDiv = 1;
  3029.         /* Unless the SCLK is > 50MHz but < 66.7MHz */ 
  3030.         if (pSiop->clkPeriod < NCR810_50MHZ) /* then faster than 50MHZ */
  3031.             {
  3032.     sccpDiv  = 67;
  3033.     clkDiv = 2;
  3034.     }
  3035.         /* convert all variables to ns */
  3036. period *= 4; /* ns */
  3037.         sccp = pSiop->clkPeriod / sccpDiv; /* ns */
  3038.         xferp = period / sccp;
  3039. /* adjust xferp to fit the allowable range */
  3040. if (xferp < NCR810_MIN_XFERP)
  3041.     xferp = NCR810_MIN_XFERP;
  3042.         else if (xferp > NCR810_MAX_XFERP)
  3043.     xferp = NCR810_MAX_XFERP;
  3044.         /* update the period using the adjusted xferp */
  3045. period = xferp * sccp;
  3046.         /* adjust the synchronous offset to fit the allowable range */
  3047. if (offset < NCR810_MIN_REQ_ACK_OFFSET)
  3048.     offset = NCR810_MIN_REQ_ACK_OFFSET;
  3049.         else if (offset > NCR810_MAX_REQ_ACK_OFFSET)
  3050.     offset = NCR810_MAX_REQ_ACK_OFFSET;
  3051.         xferParams = (UINT8)(((xferp - NCR810_MIN_XFERP) & 0x07) << 
  3052. NCR810_SYNC_XFER_PERIOD_SHIFT); 
  3053.         xferParams |= (UINT8)(offset & 0x0f);
  3054.         /* 
  3055.  * The clock dividers for scntl3 remain fixed because this is a static
  3056.  * value that does not change on a per transfer basis. The divider
  3057.  * is based on the SCLK frequency from the board to the SCSI core 
  3058.  */
  3059. clockDivide = (pSiop->clkDiv & 0x0f); 
  3060. clockDivide = (UINT8)(clockDivide | (clkDiv << 4));
  3061.         /* convert the period back to 4ns units */
  3062. period /= 4;
  3063.         } /* else */
  3064.     SCSI_DEBUG_MSG ("ncr810XferParamsCvt: converted to: "
  3065.       "offset     = %d, period      = %dn"
  3066.     "xferParams = %d, clockDivide = %dn",
  3067.     offset, period, xferParams, clockDivide, 0, 0);
  3068.     *pOffset     = (UINT8)offset;
  3069.     *pPeriod     = (UINT8)period;
  3070.     *pXferParams = xferParams;
  3071.     *pClockDiv   = clockDivide;
  3072.     return (TRUE);
  3073.     }
  3074. /*******************************************************************************
  3075. *
  3076. * ncr810StepEnable - Enable/disable script single step 
  3077. *
  3078. * Enable/disable single step facility on ncr chip.  Also, unmask/mask single 
  3079. * step interrupt in Dien register.
  3080. * Before any SCSI execution you just have to use 
  3081. * ncr810StepEnable (pSiop, TRUE) to run in single step mode.  
  3082. * To run a script step use ncr810SingleStep(pSiop).
  3083. * To disable use ncr810StepEnable (pSiop, FALSE).
  3084. * RETURNS: N/A
  3085. *
  3086. * NOMANUAL
  3087. */
  3088. void ncr810StepEnable 
  3089.     (
  3090.     SIOP *pSiop, /* pointer to SIOP info       */
  3091.     BOOL enable           /* TRUE => enable single-step */
  3092.     )
  3093.     {
  3094.     if  (enable)
  3095. {
  3096. /* enable single-step interrupt */
  3097.         CACHE_PIPE_FLUSH(); 
  3098.         NCR810_OUT_BYTE(pSiop->pDien, NCR810_IN_BYTE(pSiop->pDien) |
  3099. B_SSI);
  3100. /* set single-step mode */
  3101.         CACHE_PIPE_FLUSH(); 
  3102. NCR810_OUT_BYTE(pSiop->pDcntl, NCR810_IN_BYTE(pSiop->pDcntl) |
  3103. DCNTL_SSM);
  3104. /* disable manual Start */
  3105.         CACHE_PIPE_FLUSH(); 
  3106.    NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) &
  3107. ~DMODE_MAN); 
  3108. }
  3109.     else 
  3110. {
  3111. /* unset single-step mode */
  3112.         CACHE_PIPE_FLUSH(); 
  3113. NCR810_OUT_BYTE(pSiop->pDcntl, NCR810_IN_BYTE(pSiop->pDcntl) &
  3114. ~DCNTL_SSM);
  3115. /* disable single-step interrupt */
  3116.         CACHE_PIPE_FLUSH(); 
  3117.         NCR810_OUT_BYTE(pSiop->pDien, NCR810_IN_BYTE(pSiop->pDien) & ~B_SSI);
  3118. /* enable manual Start */
  3119.         CACHE_PIPE_FLUSH(); 
  3120. NCR810_OUT_BYTE(pSiop->pDmode, NCR810_IN_BYTE(pSiop->pDmode) |
  3121. DMODE_MAN);
  3122.         }
  3123.     pSiop->singleStep = enable;
  3124.     }
  3125. /*******************************************************************************
  3126. *
  3127. * ncr810SingleStep - Perform a single step 
  3128. *
  3129. * Perform a single step by writing the STD bit in the DCNTL register.
  3130. * The parameter is a pointer to the SIOP information. 
  3131. * RETURNS: N/A
  3132. * NOMANUAL
  3133. */
  3134. void ncr810SingleStep
  3135.     (
  3136.     SIOP * pSiop,  /* pointer to SIOP info */ 
  3137.     BOOL   verbose /* show all registers   */
  3138.     )
  3139.     {
  3140.     UINT *siopPc;
  3141.     /*
  3142.      * Start the SIOP: if not in single-step mode it will then continue
  3143.      * the normal instruction sequence.  If in single-step mode, wait
  3144.      * until one instruction has been executed.
  3145.      */
  3146.     CACHE_PIPE_FLUSH(); 
  3147.     NCR810_OUT_BYTE(pSiop->pDcntl, NCR810_IN_BYTE(pSiop->pDcntl) |
  3148.     DCNTL_STD);
  3149.     if (!pSiop->singleStep)
  3150. return;
  3151.     semTake (pSiop->singleStepSem, WAIT_FOREVER);
  3152.     /*
  3153.      * Allow any tasks using SCSI to get a look-in - they may change the
  3154.      * controller state, in which case we'd like to see that change now
  3155.      * rather than next time.
  3156.      */
  3157.     taskDelay (5);
  3158.     /*
  3159.      * Show what the SIOP is about to do
  3160.      */
  3161.     if (pSiop->state == NCR810_STATE_IDLE)
  3162. printf ("NCR810 is idle.nn");
  3163.     else
  3164. {
  3165.         CACHE_PIPE_FLUSH();
  3166. siopPc = (UINT *) NCR810_IN_32(pSiop->pDsp);
  3167.  /* mask PCI's view of memory */ 
  3168. siopPc = (UINT *) ((UINT) siopPc & 0x7fffffff);
  3169. printf ("NCR810 [%d] Next Opcode (0x%08x) => 0x%08x 0x%08xnn",
  3170. pSiop->state, (int) siopPc, NCR810_SWAP_32(siopPc[0]), 
  3171.     NCR810_SWAP_32(siopPc[1]) );
  3172. }
  3173.     
  3174.     /*
  3175.      * Dump the SIOP registers, if in verbose mode
  3176.      */
  3177.     if (verbose)
  3178.      ncr810Show ((SCSI_CTRL *) pSiop);
  3179.     }
  3180. /*******************************************************************************
  3181. *
  3182. * ncr810Show - display values of all readable NCR 53C8xx SIOP registers
  3183. *
  3184. * This routine displays the state of the SIOP registers in a user-friendly way.
  3185. * It is useful primarily for debugging. The input parameter is the pointer to 
  3186. * the SIOP information structure returned by the ncr810CtrlCreate() call.
  3187. *
  3188. * NOTE
  3189. * The only readable register during a script execution is the Istat register. 
  3190. * If you use this routine during the execution of a SCSI command, the result 
  3191. * could be unpredictable.
  3192. *
  3193. * EXAMPLE:
  3194. * .CS
  3195. * -> ncr810Show
  3196. * NCR810 Registers 
  3197. * ---------------- 
  3198. * 0xfff47000: Sien    = 0xa5 Sdid    = 0x00 Scntl1  = 0x00 Scntl0  = 0x04
  3199. * 0xfff47004: Socl    = 0x00 Sodl    = 0x00 Sxfer   = 0x80 Scid    = 0x80
  3200. * 0xfff47008: Sbcl    = 0x00 Sbdl    = 0x00 Sidl    = 0x00 Sfbr    = 0x00
  3201. * 0xfff4700c: Sstat2  = 0x00 Sstat1  = 0x00 Sstat0  = 0x00 Dstat   = 0x80
  3202. * 0xfff47010: Dsa     = 0x00000000
  3203. * 0xfff47014: Ctest3  = ???? Ctest2  = 0x21 Ctest1  = 0xf0 Ctest0  = 0x00
  3204. * 0xfff47018: Ctest7  = 0x32 Ctest6  = ???? Ctest5  = 0x00 Ctest4  = 0x00
  3205. * 0xfff4701c: Temp    = 0x00000000
  3206. * 0xfff47020: Lcrc    = 0x00 Ctest8  = 0x00 Istat   = 0x00 Dfifo   = 0x00
  3207. * 0xfff47024: Dcmd/Ddc= 0x50000000
  3208. * 0xfff47028: Dnad    = 0x00066144
  3209. * 0xfff4702c: Dsp     = 0x00066144
  3210. * 0xfff47030: Dsps    = 0x00066174
  3211. * 0xfff47037: Scratch3= 0x00 Scratch2= 0x00 Scratch1= 0x00 Scratch0= 0x0a
  3212. * 0xfff47038: Dcntl   = 0x21 Dwt     = 0x00 Dien    = 0x37 Dmode   = 0x01
  3213. * 0xfff4703c: Adder   = 0x000cc2b8
  3214. * value = 0 = 0x0
  3215. * .CE
  3216. *
  3217. * RETURNS: OK, or ERROR if <pScsiCtrl> and <pSysScsiCtrl> are both NULL.
  3218. *
  3219. * SEE ALSO: ncr810CtrlCreate()
  3220. */
  3221. STATUS ncr810Show 
  3222.     (
  3223.     FAST SCSI_CTRL *pScsiCtrl  /* ptr to SCSI controller info */
  3224.     )
  3225.     {
  3226.     FAST SIOP *pSiop; /* prt to SIOP info */
  3227.     if (pScsiCtrl == NULL)
  3228. {
  3229. if (pSysScsiCtrl == NULL)
  3230.     {
  3231.     printErr ("No SCSI controller specified.n");
  3232.     return (ERROR);
  3233.     }
  3234. pScsiCtrl = pSysScsiCtrl;
  3235. }
  3236.     pSiop = (SIOP *) pScsiCtrl; 
  3237.     CACHE_PIPE_FLUSH();
  3238.  
  3239.     printf ("NCR810 Registers n");
  3240.     printf ("---------------- n");
  3241.     printf ("0x%08x: ", (int) pSiop->pScntl0);
  3242.     printf ("Scntl0   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pScntl0)); 
  3243.     printf ("Scntl1   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pScntl1)); 
  3244.     printf ("Scntl2   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pScntl2)); 
  3245.     printf ("Scntl3   = 0x%02xn", NCR810_IN_BYTE(pSiop->pScntl3)); 
  3246.     printf ("0x%08x: ", (int) pSiop->pScid);
  3247.     printf ("Scid     = 0x%02x ",  NCR810_IN_BYTE(pSiop->pScid)); 
  3248.     printf ("Sxfer    = 0x%02x ",  NCR810_IN_BYTE(pSiop->pSxfer)); 
  3249.     printf ("Sdid     = 0x%02xn", NCR810_IN_BYTE(pSiop->pSdid)); 
  3250.     /* No need to print Gpreg (not used) */
  3251.     printf ("0x%08x: ", (int) pSiop->pSfbr);
  3252.     printf ("Sfbr    = 0x%02x ",  NCR810_IN_BYTE(pSiop->pSfbr)); 
  3253.     printf ("Socl    = 0x%02x ",  NCR810_IN_BYTE(pSiop->pSocl)); 
  3254.     printf ("Ssid    = 0x%02x ",  NCR810_IN_BYTE(pSiop->pSsid)); 
  3255.     printf ("Sbcl    = 0x%02xn", NCR810_IN_BYTE(pSiop->pSbcl)); 
  3256.     printf ("0x%08x: ", (int) pSiop->pDstat);
  3257.     /* Reading this register clears the interrupts */
  3258.     printf ("Dstat   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pDstat)); 
  3259.     printf ("Sstat0  = 0x%02x ",  NCR810_IN_BYTE(pSiop->pSstat0)); 
  3260.     printf ("Sstat1  = 0x%02x ",  NCR810_IN_BYTE(pSiop->pSstat1)); 
  3261.     printf ("Sstat2  = 0x%02xn", NCR810_IN_BYTE(pSiop->pSstat2)); 
  3262.     printf ("0x%08x: ", (int) pSiop->pDsa);
  3263.     printf ("Dsa     = 0x%08xn", NCR810_IN_32(pSiop->pDsa)); 
  3264.     printf ("0x%08x: ", (int) pSiop->pIstat);
  3265.     printf ("Istat   = 0x%02xn", NCR810_IN_BYTE(pSiop->pIstat));
  3266.     printf ("0x%08x: ", (int) pSiop->pCtest0);
  3267.     printf ("Ctest0  = 0x%02x ",  NCR810_IN_BYTE(pSiop->pCtest0));
  3268.     printf ("Ctest1  = 0x%02x ",  NCR810_IN_BYTE(pSiop->pCtest1));
  3269.     printf ("Ctest2  = 0x%02x ",  NCR810_IN_BYTE(pSiop->pCtest2));
  3270.     printf ("Ctest3  = 0x%02xn", NCR810_IN_BYTE(pSiop->pCtest3));
  3271.     
  3272.     printf ("0x%08x: ", (int) pSiop->pTemp);
  3273.     printf ("Temp    = 0x%08xn", NCR810_IN_32(pSiop->pTemp)); 
  3274.     printf ("0x%08x: ", (int) pSiop->pDfifo);
  3275.     printf ("Dfifo   = 0x%02xn", NCR810_IN_BYTE(pSiop->pDfifo)); 
  3276.     /* XXX Forget Ctest4-6 for now */
  3277.     printf ("Dbc0:23-Dcmd24:31   = 0x%08xn", NCR810_IN_32(pSiop->pDbc)); 
  3278.     printf ("0x%08x: ", (int) pSiop->pDnad);
  3279.     printf ("Dnad    = 0x%08xn", NCR810_IN_32(pSiop->pDnad)); 
  3280.     printf ("0x%08x: ", (int) pSiop->pDsp);
  3281.     printf ("Dsp     = 0x%08xn", NCR810_IN_32(pSiop->pDsp)); 
  3282.     printf ("0x%08x: ", (int) pSiop->pDsps);
  3283.     printf ("Dsps    = 0x%08xn", NCR810_IN_32(pSiop->pDsps)); 
  3284.     printf ("0x%08x: ", (int) pSiop->pScratcha0);
  3285.     printf ("Scratch0= 0x%02x ",  NCR810_IN_BYTE(pSiop->pScratcha0)); 
  3286.     printf ("Scratch1= 0x%02x ",  NCR810_IN_BYTE(pSiop->pScratcha1)); 
  3287.     printf ("Scratch2= 0x%02x ",  NCR810_IN_BYTE(pSiop->pScratcha2)); 
  3288.     printf ("Scratch3= 0x%02xn", NCR810_IN_BYTE(pSiop->pScratcha3)); 
  3289.     printf ("0x%08x: ", (int) pSiop->pDmode);
  3290.     printf ("Dmode   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pDmode));
  3291.     printf ("Dien    = 0x%02x ",  NCR810_IN_BYTE(pSiop->pDien));
  3292.     printf ("Dwt     = 0x%02x ",  NCR810_IN_BYTE(pSiop->pDwt));
  3293.     printf ("Dcntl   = 0x%02xn", NCR810_IN_BYTE(pSiop->pDcntl));
  3294.     printf ("0x%08x: ", (int) pSiop->pSien0);
  3295.     printf ("Sien0    = 0x%02x ", NCR810_IN_BYTE(pSiop->pSien0)); 
  3296.     printf ("Sien1    = 0x%02x ", NCR810_IN_BYTE(pSiop->pSien1)); 
  3297.     /* Reading these registers clears the interrupts */
  3298.     printf ("Sist0    = 0x%02x ", NCR810_IN_BYTE(pSiop->pSist0)); 
  3299.     printf ("Sist1    = 0x%02x",  NCR810_IN_BYTE(pSiop->pSist1)); 
  3300.     printf ("n");
  3301.     printf ("0x%08x: ", (int) pSiop->pSlpar);
  3302.     printf ("Slpar    = 0x%02x ", NCR810_IN_BYTE(pSiop->pSlpar)); 
  3303.     if ((pSiop->devType == NCR825_DEVICE_ID) ||
  3304. (pSiop->devType == NCR875_DEVICE_ID))
  3305. {
  3306.         printf ("Swide    = 0x%02x ", NCR810_IN_BYTE(pSiop->pSwide)); 
  3307. }
  3308.     printf ("Macntl   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pMacntl)); 
  3309.     printf ("Gpcntl   = 0x%02xn", NCR810_IN_BYTE(pSiop->pGpcntl)); 
  3310.     printf ("0x%08x: ", (int) pSiop->pStime0);
  3311.     printf ("Stime0   = 0x%02x ", NCR810_IN_BYTE(pSiop->pStime0)); 
  3312.     printf ("Stime1   = 0x%02x ", NCR810_IN_BYTE(pSiop->pStime1)); 
  3313.     if (pSiop->devType == NCR825_DEVICE_ID)
  3314. {
  3315. #if FALSE /* XXX fix later */
  3316.         printf ("Respid0  = 0x%02x ", NCR810_IN_BYTE(pSiop->pRespid0)); 
  3317.         printf ("Respid1  = 0x%02x ", NCR810_IN_BYTE(pSiop->pRespid1)); 
  3318. #endif
  3319.         printf ("Respid   = 0x%02x ", NCR810_IN_BYTE(pSiop->pRespid)); 
  3320. }
  3321.     else 
  3322. {
  3323.         printf ("Respid   = 0x%02x ", NCR810_IN_BYTE(pSiop->pRespid)); 
  3324. }
  3325.     printf ("n");
  3326.     printf ("0x%08x: ", (int) pSiop->pStest0);
  3327.     printf ("Stest0   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pStest0)); 
  3328.     printf ("Stest1   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pStest1)); 
  3329.     printf ("Stest2   = 0x%02x ",  NCR810_IN_BYTE(pSiop->pStest2)); 
  3330.     printf ("Stest3   = 0x%02xn", NCR810_IN_BYTE(pSiop->pStest3)); 
  3331.     printf ("Sidl     = 0x%04x ",  NCR810_IN_16(pSiop->pSidl)); 
  3332.     printf ("Sodl     = 0x%04x ",  NCR810_IN_16(pSiop->pSodl)); 
  3333.     printf ("Sbdl     = 0x%04xn", NCR810_IN_16(pSiop->pSbdl)); 
  3334.     printf ("Scratchb = 0x%08xn", NCR810_IN_32(pSiop->pScratchb)); 
  3335.     return (OK);
  3336.     }
  3337. /*******************************************************************************
  3338. *
  3339. * ncr810Delay - do an arbitrary scsi delay
  3340. *
  3341. * XXX This is only a temporary routine.
  3342. *
  3343. * RETURNS: N/A
  3344. */
  3345. LOCAL void ncr810Delay (void)
  3346.     {
  3347.     int delayCount;
  3348.     for (delayCount=0; delayCount < ncr810DelayCount; delayCount++)
  3349. /* do nothing */ ;
  3350.     }
  3351. /*******************************************************************************
  3352. *
  3353. * ncr810ResetAtn - Resets the ATN signal
  3354. *
  3355. * This routine resets the ATN signal of the specifiedcontroller
  3356. *
  3357. * RETURNS : N/A.
  3358. */
  3359. LOCAL void ncr810ResetAtn
  3360.     (
  3361.     SCSI_CTRL *pScsiCtrl /* controller */
  3362.     )
  3363.     {
  3364.     SIOP * pSiop; /* ptr to SIOP info */
  3365.     UINT8 cSocl; 
  3366.     pSiop = (SIOP *) pScsiCtrl;
  3367.     cSocl = NCR810_IN_BYTE(pSiop->pSocl);
  3368.     cSocl &= ~B_ATN;
  3369.     NCR810_OUT_BYTE(pSiop->pSocl,cSocl);
  3370.     }