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

VxWorks

开发平台:

C/C++

  1. /* sym895Lib.c - SCSI-2 driver for Symbios SYM895 SCSI Controller. */
  2. /* Copyright 1989-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01f,31jan02,pmr  SPR 71337: properly setting transfer period in
  8.                  sym895XferParamsCvt(), fixed warnings.
  9. 01e,30jul01,rcs  documented sym895DelayCount. SPR# 69249 
  10. 01d,18jun01,dtr  sysInWord,sysOutWord,sysInLong,sysOutLong are usually byte
  11.                  swapped in the BSP.So the byteswapping is removed for
  12.                  _BYTE_ORDER == _BIG_ENDIAN. SPR# 68497
  13. 01c,19jul00,rcs  corrected include path for sym895Lib.h
  14. 01b,23jun00,bsp  modified IO access macros, as per sysLib.h
  15. 01a,03mar00,bsp  written (from templateSCSI2.c, ver 01p).
  16. */
  17. /*
  18. DESCRIPTION
  19. The SYM53C895 PCI-SCSI I/O Processor (SIOP) brings Ultra2 SCSI performance
  20. to Host adapter, making it easy to add a high performance SCSI Bus to any PCI
  21. System.  It supports Ultra-2 SCSI rates and allows increased SCSI connectivity
  22. and cable length Low Voltage Differential (LVD) signaling for SCSI.  This 
  23. driver runs in conjunction with SCRIPTS Assembly program for the Symbios SCSI
  24. controllers.  These scripts use DMA transfers for all data, messages, and status
  25. transfers.
  26. For each controller device a manager task is created to manage SCSI threads
  27. on each bus.  A SCSI thread represents each unit of SCSI work.
  28. This driver supports multiple initiators, disconnect/reconnect, tagged
  29. command queuing and synchronous data transfer protocol.  In general, the
  30. SCSI system and this driver will automatically choose the best combination
  31. of these features to suit the target devices used.  However, the default
  32. choices may be over-ridden by using the function "scsiTargetOptionsSet()"
  33. (see scsiLib).
  34. Scatter/ Gather memory support: Scatter-Gather transfers are used when data 
  35. scattered across memory must be transferred across the SCSI bus together 
  36. with out CPU intervention.  This is achieved by a chain of block move script 
  37. instructions together with the support from the driver. The driver is expected
  38. to provide a set of addresses and byte counts for the SCRIPTS code.  However 
  39. there is no support as such from vxworks SCSI Manager for this kind of data 
  40. transfers.  So the implementation, as of today, is not completely integrated 
  41. with vxworks, and assumes support from SCSI manager in the form of array of
  42. pointers. The macro SCATTER_GATHER in sym895.h is thus not defined to avoid
  43. compilation errors.
  44. Loopback mode allows 895 chip to control all SCSI signals, regardless of 
  45. whether it is in initiator or target role.  This mode insures proper SCRIPTS 
  46. instructions fetches and data paths.  SYM895 executes initiator instructions 
  47. through the SCRIPTS, and the target role is implemented in sym895Loopback by 
  48. asserting and polling the appropriate SCSI signals in the SOCL, SODL, SBCL, 
  49. and SBDL registers.
  50. USER-CALLABLE ROUTINES
  51. Most of the routines in this driver are accessible only through the I/O
  52. system.  Three routines, however, must be called directly sym895CtrlCreate() 
  53. to create a controller structure, and sym895CtrlInit() to initialize it.
  54. If the default configuration is not correct, the routine sym895SetHwRegister() 
  55. must be used to properly configure the registers.
  56. Critical events, which are to be logged anyway irrespective of whether
  57. debugging is being done or not, can be logged by using the SCSI_MSG macro.
  58. PCI MEMORY ADDRESSING
  59. The global variable sym895PciMemOffset was created to provide the BSP
  60. with a means of changing the VIRT_TO_PHYS mapping without changing the
  61. functions in the cacheFuncs structures.  In generating physical addresses
  62. for DMA on the PCI bus, local addresses are passed through the function
  63. CACHE_DMA_VIRT_TO_PHYS and then the value of sym895PciMemOffset is added.
  64. For backward compatibility, the initial value of sym895PciMemOffset comes
  65. from the macro PCI_TO_MEM_OFFSET.
  66. INTERFACE
  67. The BSP must connect the interrupt service routine for the controller device
  68. to the appropriate interrupt system.  The routine to be called is
  69. sym895Intr(), and the argument is the pointer to the controller device pSiop.
  70. i.e.
  71. .CS
  72.     pSiop = sym895CtrlCreate (...);
  73.     intConnect (XXXX, sym895Intr, pSiop);
  74.     sym895CtrlInit (pSiop, ...);
  75. .CE
  76. HARDWARE ACCESS
  77. All hardware access is to be done through macros.  The default definition
  78. of the SYM895_REGx_READ() and SYM895_REGx_WRITE() macros (where x stands for 
  79. the width of the register being accessed ) assumes an I/O mapped model.  
  80. Register access mode can be set to either IO/memory using SYM895_IO_MAPPED
  81. macro in sym895.h.  The macros can be redefined as necessary to accommodate 
  82. other models, and situations where timing and write pipe considerations 
  83. need to be addressed.  In IO mapped mode, BSP routines sysInByte(), sysOutByte()
  84. are used for accessing SYM895 registers.  If these standard calls are not 
  85. supported, the calls supported by respective BSP are to be mapped to these 
  86. standard calls.  Memory mapped mode makes use of pointers to register offsets.
  87. The macro SYM895_REGx_READ(pDev, reg) is used to read a
  88. register of width x bits.  The two arguments are the device structure
  89. pointer and the register offset.
  90. The macro SYM895_REGx_WRITE(pDev, reg,data) is used to write data to the
  91. specified register address.  These macros presume memory mapped I/O by
  92. default.  Both macros can be redefined to tailor the driver to some other
  93. I/O model.
  94. The global variable sym895Delaycount provides the control count for 
  95. the sym895 's delay loop. This variable is global in order to allow 
  96. BSPs to adjust its value if necessary. The default value is 10 but it
  97. may be set to a higher value as system clock speeds dictate.  
  98. INCLUDE FILES
  99. scsiLib.h, sym895.h, and sym895Script.c
  100. SEE ALSO scsiLib, scsi2Lib, cacheLib, 
  101. .I "SYM53C895 PCI-SCSI I/O Processor Data Manual Version 3.0,"
  102. .I "Symbios Logic PCI-SCSI I/O Processors Programming Guide Version 2.1,"
  103. */
  104. #define INCLUDE_SCSI2 /* This is a SCSI2 driver */
  105. #include "vxWorks.h"
  106. #include "sysLib.h"
  107. #include "memLib.h"
  108. #include "ctype.h"
  109. #include "stdlib.h"
  110. #include "string.h"
  111. #include "stdio.h"
  112. #include "logLib.h"
  113. #include "semLib.h"
  114. #include "intLib.h"
  115. #include "errnoLib.h"
  116. #include "cacheLib.h"
  117. #include "taskLib.h"
  118. #include "scsiLib.h"
  119. #include "drv/scsi/sym895.h"
  120. /* Include SCRIPTS Assembly code */
  121. #include "sym895Script.c"
  122. /* defines */
  123. /*
  124.  * short hand. All through the documentation, 
  125.  * "SIOP" is used extensively for "SCSI Controller"
  126.  */
  127. typedef SYM895_SCSI_CTRL SIOP;
  128. #define PCI_TO_MEM_OFFSET 0x00
  129. #if (_BYTE_ORDER == _BIG_ENDIAN)
  130. #define SYM895_SWAP_32(x)  LONGSWAP((UINT)x)
  131. #define SYM895_SWAP_16(x)  ((LSB(x) << 8)|MSB(x))
  132. #else   /* _BYTE_ORDER == _BIG_ENDIAN   */
  133. /* 
  134.  * Byte order is Little endian 
  135.  * Don't need to swap because the chip is little endian inherently.
  136.  */
  137. #define SYM895_SWAP_32   
  138. #define SYM895_SWAP_16
  139. #endif    /* _BYTE_ORDER == _BIG_ENDIAN   */
  140. #define SYM895_SCSI_DEBUG_MSG SCSI_DEBUG_MSG
  141. #define SYM895_VIRT_TO_PHYS(x) 
  142. ((UINT)CACHE_DMA_VIRT_TO_PHYS(x) + (UINT)sym895PciMemOffset)
  143. #define SYM895_PHYS_TO_VIRT(x) 
  144. ((UINT)CACHE_DMA_PHYS_TO_VIRT(x) + (UINT)sym895PciMemOffset)
  145. /* Hardware Abstraction macros hide all actual access to the chip */
  146. #ifdef SYM895_IO_MAPPED
  147. #if (_BYTE_ORDER==_LITTLE_ENDIAN)
  148. #define SYM895_REG8_READ(pSiop, reg) 
  149. sysInByte((UINT32)((pSiop->baseAddress) + (reg)))
  150. #define SYM895_REG8_WRITE(pSiop, reg, data) 
  151. sysOutByte((UINT32)((pSiop->baseAddress) + (reg)),(UINT8)data)
  152. #define SYM895_REG16_READ(pSiop, reg) 
  153. SYM895_SWAP_16(sysInWord((UINT32)((pSiop->baseAddress) + (reg))))
  154. #define SYM895_REG16_WRITE(pSiop, reg, data) 
  155. sysOutWord((UINT32)((pSiop->baseAddress) + (reg)), 
  156.                    SYM895_SWAP_16((UINT16)data))
  157. #define SYM895_REG32_READ(pSiop, reg) 
  158. SYM895_SWAP_32(sysInLong((UINT32)((pSiop->baseAddress) + (reg))))
  159. #define SYM895_REG32_WRITE(pSiop, reg, data) 
  160. sysOutLong((UINT32)((pSiop->baseAddress) + (reg)), 
  161.                    SYM895_SWAP_32((UINT32)data))
  162. #else
  163. #define SYM895_REG8_READ(pSiop, reg) 
  164. sysInByte((ULONG)((pSiop->baseAddress) + (reg)))
  165. #define SYM895_REG8_WRITE(pSiop, reg, data) 
  166. sysOutByte((ULONG)((pSiop->baseAddress) + (reg)),(UINT8)data)
  167. #define SYM895_REG16_READ(pSiop, reg) 
  168. sysInWord((ULONG)((pSiop->baseAddress) + (reg)))
  169. #define SYM895_REG16_WRITE(pSiop, reg, data) 
  170. sysOutWord((ULONG)((pSiop->baseAddress) + (reg)), 
  171.                    (UINT16)data)
  172. #define SYM895_REG32_READ(pSiop, reg) 
  173. sysInLong((ULONG)((pSiop->baseAddress) + (reg)))
  174. #define SYM895_REG32_WRITE(pSiop, reg, data) 
  175. sysOutLong((ULONG)((pSiop->baseAddress) + (reg)), 
  176.                    (UINT32)data)
  177. #endif 
  178. #else /* SYM895_IO_MAPPED */
  179. #define SYM895_REG8_READ(pSiop, reg) 
  180. (*(UINT8 *)((pSiop->baseAddress) + (reg)))
  181. #define SYM895_REG8_WRITE(pSiop, reg, data) 
  182. (*(UINT8 *)((pSiop->baseAddress) + (reg)) = (UINT8)data)
  183. #define SYM895_REG16_READ(pSiop, reg) 
  184. SYM895_SWAP_16(*(UINT16 *)((pSiop->baseAddress) + (reg)))
  185. #define SYM895_REG16_WRITE(pSiop, reg, data) 
  186. (*(UINT16 *)((pSiop->baseAddress) + (reg)) = SYM895_SWAP_16((UINT)data))
  187. #define SYM895_REG32_READ(pSiop, reg) 
  188. SYM895_SWAP_32(*(UINT32 *)((pSiop->baseAddress) + (reg)))
  189. #define SYM895_REG32_WRITE(pSiop, reg, data) 
  190. (*(UINT32 *)((pSiop->baseAddress) + (reg)) = SYM895_SWAP_32((UINT)data))
  191. #endif   /* SYM895_IO_MAPPED */
  192. /* Other miscellaneous defines */
  193. #define SYM895_MAX_XFER_LENGTH 0xffffff /* 16MB max transfer */
  194. IMPORT BOOL scsiDebug;
  195. /* Configurable options, scsi manager task */
  196. int     sym895SingleStepSemOptions = SEM_Q_PRIORITY;
  197. char *  sym895ScsiTaskName         = SCSI_DEF_TASK_NAME;
  198. int     sym895ScsiTaskOptions      = SCSI_DEF_TASK_OPTIONS;
  199. int     sym895ScsiTaskPriority     = SCSI_DEF_TASK_PRIORITY;
  200. int     sym895ScsiTaskStackSize    = SCSI_DEF_TASK_STACK_SIZE;
  201. /* Globals */
  202. int     sym895PciMemOffset = PCI_TO_MEM_OFFSET;
  203. int     sym895DelayCount   = 10;
  204. ULONG * sym895ScriptEntry [] =  {
  205. sym895Wait,
  206. sym895InitStart,
  207. sym895InitContinue,
  208. sym895TgtDisconnect,
  209.                                 sym895Diag
  210. };
  211. /* 
  212.  * The variable "sym895Instructions" needs to be defined for PPC family. As  
  213.  * the memory is Big-Endian and PCI bus being little endian,the sym895 
  214.  * scripts need to be byte swapped in memory. However, they should only be 
  215.  * swapped the first time that sysSym895PciInit() is invoked. This variable is
  216.  * used in BSP file sysScsi.c to swap the scripts in memory.
  217.  * 
  218.  * vxEieio () is needed for PPC family to make sure that SIOP registers
  219.  * are written in order.
  220.  */
  221. #if (CPU_FAMILY==PPC)
  222. ULONG sym895Instructions = SYM895_INSTRUCTIONS;
  223. #endif
  224. #if ((CPU==PPC603) || (CPU == PPCEC603) || (CPU==PPC604))
  225. # undef CACHE_PIPE_FLUSH
  226. extern void  vxEieio ();
  227. # define CACHE_PIPE_FLUSH() vxEieio()
  228. #endif
  229. /* forward declarations */
  230. LOCAL STATUS sym895HwInit (SIOP * pSiop);
  231. LOCAL void   sym895SharedMemInit ( SIOP * pSiop, SYM895_SHARED * pShMem);
  232. LOCAL STATUS sym895IdentThreadInit (SYM895_THREAD * pThread);
  233. STATUS       sym895SetHwOptions (SIOP * pSiop, SYM895_HW_OPTIONS * pHwOptions);
  234. LOCAL void   sym895Delay (void);
  235. LOCAL void   sym895ScsiBusReset (FAST SIOP * pSiop);
  236. LOCAL UINT   sym895RemainderGet ( SIOP * pSiop, UINT phase);
  237. LOCAL void   sym895Event (SIOP * pSiop, SYM895_EVENT * pEvent);
  238. LOCAL STATUS sym895ThreadInit (SIOP * pSiop, SYM895_THREAD * pThread);
  239. LOCAL STATUS sym895ThreadActivate (SIOP * pSiop, SYM895_THREAD * pThread);
  240. LOCAL BOOL   sym895ThreadAbort (SIOP * pSiop, SYM895_THREAD * pThread);
  241. LOCAL STATUS sym895ScsiBusControl (SIOP * pSiop, int operation);
  242. LOCAL STATUS sym895XferParamsQuery (SCSI_CTRL * pScsiCtrl, UINT8 * pOffset,
  243.                                     UINT8 * pPeriod);
  244. LOCAL STATUS sym895XferParamsSet (SCSI_CTRL * pScsiCtrl, UINT8 offset,
  245.                                   UINT8 period);
  246. LOCAL BOOL   sym895XferParamsCvt (SIOP * pSiop, UINT8 * pOffset, UINT8 * pPeriod,  
  247.                                   UINT8 * pXferParams, UINT8 * pClockDiv);
  248. LOCAL void   sym895TargIdentEvent (SYM895_THREAD * pThread, 
  249.                                    SYM895_EVENT * pEvent);
  250. LOCAL STATUS sym895WideXferParamsQuery (SCSI_CTRL * pScsiCtrl,
  251.                                         UINT8 * xferWidth);
  252. LOCAL STATUS sym895WideXferParamsSet (SCSI_CTRL * pScsiCtrl, UINT8 xferWidth);
  253. LOCAL void   sym895ScriptStart (SIOP * pSiop, SYM895_THREAD * pThread,
  254.                                 SYM895_SCRIPT_ENTRY entryId);
  255. LOCAL int    sym895EventTypeGet (SIOP * pSiop);
  256. LOCAL STATUS sym895ThreadParamsSet (SYM895_THREAD *, UINT8, UINT8);
  257. LOCAL STATUS sym895Activate (SIOP * pSiop, SYM895_THREAD * pThread);
  258. LOCAL void   sym895ThreadStateSet (SYM895_THREAD * pThread,
  259.                                    SCSI_THREAD_STATE state);
  260. LOCAL void   sym895Abort (SIOP * pSiop);
  261. LOCAL void   sym895ThreadEvent (SYM895_THREAD * pThread, 
  262.                                 SYM895_EVENT *  pEvent);
  263. LOCAL void   sym895InitEvent (SYM895_THREAD * pThread,
  264.                               SYM895_EVENT *  pEvent);
  265. LOCAL void   sym895ThreadUpdate (SYM895_THREAD * pThread);
  266. LOCAL void   sym895InitIdentEvent (SYM895_THREAD * pThread,
  267.                                    SYM895_EVENT * pEvent);
  268. LOCAL void   sym895IdentInContinue (SYM895_THREAD * pThread);
  269. LOCAL STATUS sym895Resume (SIOP * pSiop, SYM895_THREAD * pThread,
  270.                            SYM895_SCRIPT_ENTRY entryId);
  271. LOCAL void   sym895ThreadFail (SYM895_THREAD * pThread, int errNum);
  272. LOCAL void   sym895ThreadComplete (SYM895_THREAD * pThread);
  273. LOCAL void   sym895ThreadDefer (SYM895_THREAD * pThread);
  274. LOCAL STATUS sym895PhaseMismatch (SYM895_THREAD * pThread, int phase,
  275.   UINT remCount);
  276. LOCAL void   sym895ThreadReconnect (SYM895_THREAD * pThread);
  277. /*******************************************************************************
  278. *
  279. * sym895CtrlCreate - create a structure for a SYM895 device.
  280. *
  281. * This routine creates a SCSI Controller data structure and must be called 
  282. * before using a SCSI Controller chip.  It should be called once and only 
  283. * once for a specified SCSI Controller. Since it allocates memory for a 
  284. * structure needed by all routines in sym895Lib, it must be called
  285. * before any other routines in the library. After calling this routine,
  286. * sym895CtrlInit() should be called at least once before any SCSI
  287. * transactions are initiated using the SCSI Controller.
  288. *
  289. * A Detailed description of parameters follows.
  290. *
  291. * .IP <siopBaseAdrs>
  292. * base address of the SCSI controller.
  293. * .IP <clkPeriod>
  294. * clock controller period (nsec*100).This is used to determine the clock period
  295. * for the SCSI core and affects the timing of both asynchronous and synchronous
  296. * transfers. Several Commonly used values are
  297. *
  298. * .CS
  299. * SYM895_1667MHZ  6000    16.67Mhz chip 
  300. * SYM895_20MHZ    5000    20Mhz chip 
  301. * SYM895_25MHZ    4000    25Mhz chip 
  302. * SYM895_3750MHZ  2667    37.50Mhz chip 
  303. * SYM895_40MHZ    2500    40Mhz chip 
  304. * SYM895_50MHZ    2000    50Mhz chip 
  305. * SYM895_66MHZ    1515    66Mhz chip 
  306. * SYM895_6666MHZ  1500    66Mhz chip 
  307. * SYM895_75MHZ    1333    75Mhz chip 
  308. * SYM895_80MHZ    1250    80Mhz chip 
  309. * SYM895_160MHZ    625    40Mhz chip with Quadrupler 
  310. * .CE
  311. *
  312. * .IP <devType>
  313. * SCSI sym8xx device type 
  314. * .IP <siopRamBaseAdrs>
  315. * base address of the internal scripts RAM
  316. * .IP <flags>
  317. * various device/debug options for the driver. Commonly used values are
  318. *
  319. * .CS
  320. * SYM895_ENABLE_PARITY_CHECK      0x01
  321. * SYM895_ENABLE_SINGLE_STEP       0x02
  322. * SYM895_COPY_SCRIPTS             0x04
  323. * .CE
  324. *
  325. * RETURNS: A pointer to SYM895_SCSI_CTRL structure, or NULL if memory 
  326. * is unavailable or there are invalid parameters.
  327. *
  328. * ERRORS: N/A
  329. *
  330. */
  331. SYM895_SCSI_CTRL * sym895CtrlCreate
  332.     (
  333.     UINT8 *  siopBaseAdrs,        /* base address of the SCSI Controller */
  334.     UINT     clkPeriod,           /* clock controller period (nsec*100)  */
  335.     UINT16   devType,             /* SCSI device type */
  336.     UINT8 *  siopRamBaseAdrs,     /* on Chip Ram Address */
  337.     UINT16   flags                /* options */
  338.     )
  339.     {
  340.     FAST SIOP *  pSiop;           /* pointer to SCSI Controller info */
  341.     SCSI_CTRL *  pScsiCtrl;
  342.     UINT nBytes;                  /* Required memory */
  343.     
  344.     static SYM895_HW_OPTIONS sym895Options = SYM895_FAST_SCSI_OPTIONS;
  345.      /* Verify parameters */
  346.     if ((siopBaseAdrs == NULL) || (siopRamBaseAdrs == NULL))
  347.         return ((SIOP *)NULL);
  348.     if ((clkPeriod > SYM895_1667MHZ) || (clkPeriod < SYM895_160MHZ))
  349.         return ((SIOP *)NULL);
  350.     /* Check that the DM Buffers are cache coherent */
  351.     if (!CACHE_DMA_IS_WRITE_COHERENT () || !CACHE_DMA_IS_READ_COHERENT ())
  352.         {
  353.         SCSI_MSG ("sym895CtrlCreate : Shared memory not cache coherent. n",
  354.                   0, 0, 0, 0, 0, 0);
  355.         return ((SIOP *)NULL);
  356.         }
  357.     switch (devType)
  358.         {
  359.         case NCR810_DEVICE_ID   :
  360.         case NCR825_DEVICE_ID   :
  361.         case NCR875_DEVICE_ID   :
  362.         case SYM895_DEVICE_ID :
  363.         case NCR895A_DEVICE_ID  :
  364.              break;
  365.         default                 :
  366.              SCSI_MSG (" sym895CtrlCreate : Invalid Device type %xn",
  367.                        devType, 0, 0, 0, 0, 0);
  368.              return ((SIOP *)NULL);
  369.         }
  370.     /* cacheDmaMalloc the controller struct and the two shared data areas */
  371.     nBytes = sizeof (SIOP) + 2 * sizeof (SYM895_SHARED);
  372.     if ((pSiop = (SIOP *) cacheDmaMalloc (nBytes)) == (SIOP *) NULL)
  373.         return ((SIOP *) NULL);
  374.     memset ((char *) pSiop, 0, nBytes);
  375.     pSiop->pIdentShMem = (SYM895_SHARED *) (pSiop + 1);
  376.     pSiop->pClientShMem = pSiop->pIdentShMem + 1;
  377.     pScsiCtrl = &(pSiop->scsiCtrl);
  378.     /* fill in generic SCSI info for this controller */
  379.     pScsiCtrl->eventSize     = sizeof (SYM895_EVENT);
  380.     pScsiCtrl->threadSize     = sizeof (SYM895_THREAD);
  381.     pScsiCtrl->maxBytesPerXfer     = SYM895_MAX_XFER_LENGTH;
  382.     pScsiCtrl->scsiTransact     = (FUNCPTR)    scsiTransact;
  383.     pScsiCtrl->scsiEventProc       = (VOIDFUNCPTR) sym895Event;
  384.     pScsiCtrl->scsiThreadInit      = (FUNCPTR)     sym895ThreadInit;
  385.     pScsiCtrl->scsiThreadActivate  = (FUNCPTR)     sym895ThreadActivate;
  386.     pScsiCtrl->scsiThreadAbort     = (FUNCPTR)     sym895ThreadAbort;
  387.     pScsiCtrl->scsiBusControl      = (FUNCPTR)     sym895ScsiBusControl;
  388.     pScsiCtrl->scsiXferParamsQuery = (FUNCPTR)     sym895XferParamsQuery;
  389.     pScsiCtrl->scsiXferParamsSet   = (FUNCPTR)     sym895XferParamsSet;
  390.     pScsiCtrl->scsiWideXferParamsQuery = (FUNCPTR) sym895WideXferParamsQuery;
  391.     pScsiCtrl->scsiWideXferParamsSet   = (FUNCPTR) sym895WideXferParamsSet;
  392.     pScsiCtrl->wideXfer     = TRUE; /* for 895 and above */
  393.     scsiCtrlInit (&(pSiop->scsiCtrl));
  394.     pSiop->baseAddress        = siopBaseAdrs;
  395.     pSiop->devType            = devType;
  396.     pSiop->clkPeriod          = clkPeriod;
  397.     pSiop->siopRamBaseAddress = siopRamBaseAdrs;
  398.     memcpy (&(pSiop->hwOptions), &(sym895Options), sizeof (SYM895_HW_OPTIONS));
  399.     /* Create synchronisation semaphore for single-step support  */
  400.     if (flags & SYM895_ENABLE_SINGLE_STEP)
  401.         {
  402.         pSiop->singleStepSem = semBCreate (sym895SingleStepSemOptions, SEM_EMPTY);
  403.         if(pSiop->singleStepSem == NULL)
  404.             {
  405.             SCSI_MSG ("sym895CtrlCreate: Error Creating Single step semaphoren", 
  406.                      0, 0, 0, 0, 0, 0);
  407.             (void) cacheDmaFree ((char *)pSiop);
  408.              return (NULL);
  409.             }
  410.         }
  411.     else
  412.         pSiop->singleStepSem = NULL;
  413.     pSiop->state        = SYM895_STATE_IDLE;
  414.     pSiop->isCmdPending = FALSE;
  415.     /* Set the user chosen options */
  416.     pSiop->isParityCheck  = (flags & SYM895_ENABLE_PARITY_CHECK)? TRUE:FALSE;
  417.     pSiop->isSingleStep   = (flags & SYM895_ENABLE_SINGLE_STEP)? TRUE:FALSE; 
  418.     pSiop->isScriptsCopy  = (flags & SYM895_COPY_SCRIPTS)? TRUE:FALSE;
  419.     /* Initialize fields in client shared data area */
  420.     sym895SharedMemInit (pSiop,pSiop->pClientShMem);
  421.     /* Initialize the Identification Thread */
  422.     sym895IdentThreadInit ((SYM895_THREAD *)pScsiCtrl->pIdentThread);
  423.     /* spawn SCSI manager - use generic code from "scsiLib.c" */
  424.     pScsiCtrl->scsiMgrId = taskSpawn (sym895ScsiTaskName,
  425.                                       sym895ScsiTaskPriority,
  426.                                       sym895ScsiTaskOptions,
  427.                                       sym895ScsiTaskStackSize*2,
  428.                                       (FUNCPTR) scsiMgr,
  429.                                       (int) pSiop, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  430.     
  431.     if (pScsiCtrl->scsiMgrId != ERROR)
  432.         {
  433.         return (pSiop);
  434.         }
  435.     SCSI_MSG ("sym895CtrlCreate: can't spawn SCSI Manager n",
  436.               0, 0, 0, 0, 0, 0);
  437.     if (pSiop->singleStepSem != NULL)
  438.         (void) semDelete (pSiop->singleStepSem);
  439.     (void) cacheDmaFree ((char *)pSiop);
  440.     return (NULL);
  441.     }
  442. /*******************************************************************************
  443. *
  444. * sym895CtrlInit - initialize a SCSI Controller Structure.
  445. *
  446. * This routine initializes an  SCSI Controller structure, after the structure
  447. * is created with sym895CtrlCreate().  This structure must be initialized
  448. * before the SCSI Controller can be used.  It may be called more than once
  449. * if needed; however, it should only be called while there is no activity on
  450. * the SCSI interface.
  451. *
  452. * A Detailed description of parameters follows.
  453. *
  454. * .IP <pSiop>
  455. * pointer to the SCSI controller structure created with sym895CtrlCreate()
  456. * .IP <scsiCtrlBusId>
  457. * SCSI Bus Id of the SIOP. 
  458. *
  459. * RETURNS OK, or ERROR if parameters are out of range.
  460. *
  461. * ERRORS: N/A
  462. */
  463. STATUS sym895CtrlInit
  464.     (
  465.     FAST SIOP * pSiop,  /* pointer to SCSI Controller structure  */
  466.     UINT scsiCtrlBusId /* SCSI bus ID of this SCSI Controller   */
  467.     )
  468.     {
  469.     volatile int delay;
  470.     SCSI_CTRL *  pScsiCtrl = &pSiop->scsiCtrl;
  471.     /* validate parameters */
  472.     if (pSiop == (SIOP *)NULL)
  473.         return (ERROR);
  474.     if ((scsiCtrlBusId < SCSI_MIN_BUS_ID) || (scsiCtrlBusId > SCSI_MAX_BUS_ID))
  475.         return (ERROR);
  476.     pScsiCtrl->scsiCtrlBusId = scsiCtrlBusId;
  477.     /* Initialise and reset the SCSI Controller */
  478.     if (sym895HwInit (pSiop) == ERROR)
  479.         { 
  480.         SCSI_MSG ("Error in sym895HwInit()n", 0, 0, 0, 0, 0, 0);
  481.         return (ERROR);
  482.         }
  483.     delay = sym895DelayCount;
  484.     sym895DelayCount *= 35; /* First delay must be longer */    
  485.     sym895ScriptStart (pSiop, (SYM895_THREAD *)pScsiCtrl->pIdentThread,
  486.                        SYM895_SCRIPT_WAIT); 
  487.     sym895DelayCount = delay;
  488.     pSiop->state = SYM895_STATE_PASSIVE;
  489.     return (OK);
  490.     }
  491. /*******************************************************************************
  492. *
  493. * sym895HwInit - hardware initialization for the 895 Chip.
  494. *
  495. * This function puts the SIOP in a known quiescent state.  Also, if copying of 
  496. * SCSI scripts is enabled, this routine copies entire SCRIPTS code from host 
  497. * memory to On-Chip SCRIPTS RAM.  This routine does not modify any of the 
  498. * registers that are set by sym895SetHwOptions().  
  499. *
  500. * For details of the register bits initialised here, refer to SYM53C895 data 
  501. * manual Version 3.0.
  502. *
  503. * .IP <pSiop>
  504. * pointer to the SIOP structure
  505. *
  506. * RETURNS: OK, or ERROR if parameters are out of range.
  507. *
  508. * ERRORS: N/A
  509. */
  510. STATUS sym895HwInit
  511.     (
  512.     FAST SIOP * pSiop         /* pointer to the SIOP structure */
  513.     )
  514.     {
  515.     /* local variables for the copy of SCRIPTs */
  516.     ULONG *     dst;          /* pointer for SCRIPTS destination */
  517.     ULONG       nLongs;       /* number of longs to copy across SCRIPTS RAM */
  518.     int         status;       /* status of copying SCRIPTS */
  519.     char  *     src;          /* pointer for SCRIPTS source */
  520.     UINT8       curScid;      /* store for current chip's SCSI ID */
  521.     /* validate the parameters */
  522.     if (pSiop == (SIOP *)NULL)
  523.         return (ERROR);
  524.     /* Soft-Reset the SIOP */
  525.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_ISTAT, SYM895_ISTAT_SOFTRST);
  526.     taskDelay (2);
  527.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_ISTAT,0);
  528.     /* Initialize the Driver default Options for the Chip */
  529.     if (sym895SetHwOptions (pSiop,&pSiop->hwOptions) != OK)
  530.         {
  531.         SCSI_MSG ("sym895SetHwOptions failedn", 0, 0, 0, 0, 0, 0);
  532.         return (ERROR);
  533.         }
  534.    
  535.     /* DMA Manual Mode. Automatic Fetching of scripts disabled */
  536.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_DMODE,
  537.                        SYM895_REG8_READ (pSiop,SYM895_OFF_DMODE) |
  538.                        SYM895_DMODE_MAN);
  539.     /* SYM (NCR)700 compatibility mode turned off */
  540.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_DCNTL,
  541.                        SYM895_REG8_READ (pSiop,SYM895_OFF_DCNTL)| 
  542.                        SYM895_DCNTL_COM);
  543.     /* Check clock period and get the clock division factor */
  544.     if (pSiop->clkPeriod >= SYM895_25MHZ)            /* 16.67 - 25 MHz */
  545.         {
  546.         pSiop->clkDiv = SYM895_16MHZ_ASYNC_DIV;
  547.         }
  548.     else if (pSiop->clkPeriod >= SYM895_3750MHZ)     /* 25.01 MHz  - 37.5MHz */
  549.         {
  550.         pSiop->clkDiv = SYM895_25MHZ_ASYNC_DIV;
  551.         }
  552.     else if (pSiop->clkPeriod >= SYM895_50MHZ)       /* 37.51 MHz  - 50 MHz */
  553.         {
  554.         pSiop->clkDiv = SYM895_3750MHZ_ASYNC_DIV;
  555.         }
  556.     else if (pSiop->clkPeriod >= SYM895_75MHZ)       /* 50.01MHz  - 75 MHz */
  557.         {
  558.         pSiop->clkDiv = SYM895_50MHZ_ASYNC_DIV;
  559.         }
  560.     else if (pSiop->clkPeriod >= SYM895_80MHZ)       /* 75.01MHz  - 80 MHz */
  561.         {
  562.         pSiop->clkDiv = SYM895_75MHZ_ASYNC_DIV;
  563.         }
  564.     else                               /* 75.01 Mhz - 160 Mhz (Quadrapler) */
  565.         {
  566.         pSiop->clkDiv = SYM895_160MHZ_ASYNC_DIV;
  567.         }
  568.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL3,
  569.                        SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL3) |
  570.                        pSiop->clkDiv);
  571.     /* 
  572.      * If disconect/reconnect is enabled, use full arbitration.
  573.      * Always generate parity, check for parity if enabled.
  574.      */
  575.     if ( pSiop->scsiCtrl.disconnect)
  576.         {
  577.         SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL0,
  578.                            SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL0)|
  579.                            (SYM895_SCNTL0_ARB1 | SYM895_SCNTL0_ARB0));
  580.         }
  581.     /* Enable Select with ATN signal asserted */
  582.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL0,
  583.                        SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL0)|
  584.                        (SYM895_SCNTL0_WATN));
  585.     /* Enable parity Checking if enabled*/
  586.     if ( pSiop->isParityCheck) /* if parity Check enabled */
  587.         {
  588.         SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL0,
  589.                            SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL0) |
  590.                            (SYM895_B_PAR));
  591.         }
  592.     /* Set Bus Id */
  593.     curScid = SYM895_REG8_READ (pSiop,SYM895_OFF_SCID) & 0xf0;
  594.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCID, 
  595.                        curScid | pSiop->scsiCtrl.scsiCtrlBusId);
  596.     SYM895_REG16_WRITE (pSiop, SYM895_OFF_RESPID0,
  597.                         1<<pSiop->scsiCtrl.scsiCtrlBusId);
  598.     /* Enable Response to Bus Initiated Selection/Reselection */
  599.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCID, 
  600.                        SYM895_REG8_READ (pSiop,SYM895_OFF_SCID)|
  601.                        (SYM895_SCID_RRE | SYM895_SCID_SRE));
  602.     /* Enable Interrupts - SCSI and DMA */
  603.     /* 
  604.      * Note : SCSI ATN Interrupt is used (in target mode) to signal the
  605.      * assetion of the ATN signal. In initiator mode, it is the phase mismatch
  606.      * interrupt. In target mode, this interrupt is not handled. This is
  607.      * enabled only in Initiator mode.
  608.      */
  609.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN0, 
  610.                        (SYM895_B_SGE | SYM895_B_UDC | 
  611.                        SYM895_B_RST | SYM895_B_PAR));
  612.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN1, 
  613.                        (SYM895_B_STO | SYM895_B_HTH |
  614.                        SYM895_B_SBMC | SYM895_B_GEN));
  615.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN, 
  616.                        (SYM895_B_BF | SYM895_B_ABT | 
  617.                        SYM895_B_SIR | SYM895_B_IID));
  618.     /* Clear DMA FIFO */
  619.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
  620.                        SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) | 
  621.                        SYM895_CTEST3_CLF);
  622.  
  623.     /* 
  624.      * Copy scripts to the on chip script RAM. 
  625.      * Each 895 instruction is 2 longs wide 
  626.      */
  627.     if ((pSiop->isScriptsCopy == TRUE) && (pSiop->siopRamBaseAddress != NULL))
  628.         {
  629.         nLongs = SYM895_INSTRUCTIONS * 2;
  630.         /* Check whether scripts exceed the size of SCRIPT RAM (4K for 895) */
  631.         if (SYM895_SCRIPT_RAM_SIZE < nLongs * sizeof (ULONG))
  632.             {
  633.             SCSI_MSG (" sym895HwInit: Total Scripts length exceeded n",
  634.                       0, 0, 0, 0, 0, 0);
  635.             return (ERROR);
  636.     }
  637.         dst = (ULONG *)pSiop->siopRamBaseAddress;
  638.         src = (char *)sym895Wait;
  639.         /* Now Copy the scripts and validate the copying after checking */
  640.         bcopyLongs ((char *)sym895Wait, (char *)pSiop->siopRamBaseAddress, 
  641.                     nLongs);
  642.         status = bcmp ((char *) sym895Wait, (char *)pSiop->siopRamBaseAddress, 
  643.                       nLongs*4);
  644.         if (status != 0)
  645.             {
  646.             SCSI_MSG (" Copy to Scripts Ram Failed n", 
  647.                       0, 0, 0, 0, 0, 0);
  648.             return (ERROR);
  649.             }
  650.         /* Fill in the script Entries */
  651.         sym895ScriptEntry [SYM895_SCRIPT_WAIT] = (ULONG *) ((UINT) dst);
  652.         sym895ScriptEntry [SYM895_SCRIPT_INIT_START] = 
  653.             (ULONG *) ((UINT)sym895InitStart - (UINT)sym895Wait + (UINT)dst);
  654.         sym895ScriptEntry [SYM895_SCRIPT_INIT_CONTINUE] = 
  655.             (ULONG *) ((UINT)sym895InitContinue - (UINT)sym895Wait + (UINT)dst);
  656.         sym895ScriptEntry [SYM895_SCRIPT_TGT_DISCONNECT] = 
  657.             (ULONG *) ((UINT)sym895TgtDisconnect - (UINT)sym895Wait + (UINT)dst);
  658.         sym895ScriptEntry [SYM895_SCRIPT_DIAG] = 
  659.             (ULONG *) ((UINT)sym895Diag - (UINT)sym895Wait + (UINT)dst);
  660.         }
  661.     else
  662.         {
  663.         sym895ScriptEntry [SYM895_SCRIPT_WAIT] = (ULONG *) (sym895Wait);
  664.         sym895ScriptEntry [SYM895_SCRIPT_INIT_START] = 
  665.             (ULONG *)((UINT)sym895InitStart);
  666.         sym895ScriptEntry [SYM895_SCRIPT_INIT_CONTINUE] = 
  667.             (ULONG *) ((UINT) sym895InitContinue);
  668.         sym895ScriptEntry [SYM895_SCRIPT_TGT_DISCONNECT] = 
  669.             (ULONG *) ((UINT) sym895TgtDisconnect);
  670.         sym895ScriptEntry [SYM895_SCRIPT_DIAG] = 
  671.             (ULONG *) ((UINT) sym895Diag);
  672.         }
  673.     /* HwInit Successful */
  674.     return (OK);
  675.     }
  676. /*******************************************************************************
  677. *
  678. * sym895SetHwOptions - sets the Sym895 chip Options.
  679. *
  680. * This function sets optional bits required for tweaking the performance
  681. * of 895 to the Ultra2 SCSI. The routine should be called with SYM895_HW_OPTIONS
  682. * structure as defined in sym895.h file. 
  683. *
  684. * The input parameters are
  685. *
  686. * .IP <pSiop> 
  687. * pointer to the SIOP structure
  688. * .IP <pHwOptions>
  689. * pointer to the a SYM895_HW_OPTIONS structure.
  690. * .CS
  691. *    struct sym895HWOptions
  692. *    {
  693. *    int    SCLK    : 1;      /@ STEST1:b7,if false, uses PCI Clock for SCSI  @/
  694. *    int    SCE     : 1;      /@ STEST2:b7, enable assertion of SCSI thro SOCL@/
  695. *                             /@ and SODL registers                           @/
  696. *    int    DIF     : 1;      /@ STEST2:b5, enable differential SCSI          @/
  697. *    int    AWS     : 1;      /@ STEST2:b2, Always Wide SCSI                  @/
  698. *    int    EWS     : 1;      /@ SCNTL3:b3, Enable Wide SCSI                  @/
  699. *    int    EXT     : 1;      /@ STEST2:b1, Extend SREQ/SACK filtering        @/
  700. *    int    TE      : 1;      /@ STEST3:b7, TolerANT Enable                   @/
  701. *    int    BL      : 3;      /@ DMODE:b7,b6, CTEST5:b2 : Burst length        @/ 
  702. *                             /@ when set to any of 32/64/128 burst length    @/
  703. *                             /@ transfers, requires the DMA Fifo size to be  @/
  704. *                             /@ 816 bytes (ctest5:b5 = 1).                   @/  
  705. *    int    SIOM    : 1;      /@ DMODE:b5, Source I/O Memory Enable           @/
  706. *    int    DIOM    : 1;      /@ DMODE:b4, Destination I/O Memory Enable      @/
  707. *    int    EXC     : 1;      /@ SCNTL1:b7, Slow Cable Mode                   @/
  708. *    int    ULTRA   : 1;      /@ SCNTL3:b7, Ultra Enable                      @/
  709. *    int    DFS     : 1;      /@ CTEST5:b5, DMA Fifo size 112/816 bytes       @/
  710. *    } SYM895_HW_OPTIONS;
  711. * .CE
  712. *
  713. * This routine should not be called when there is SCSI Bus Activity as 
  714. * this modifies the SIOP Registers.
  715. *
  716. * RETURNS: OK or ERROR if any of the input parameters is not valid.
  717. *
  718. * ERRORS: N/A
  719. *
  720. * SEE ALSO: sym895.h, sym895CtrlCreate()
  721. *
  722. */
  723. STATUS sym895SetHwOptions
  724.     (
  725.     FAST SIOP *          pSiop,         /* pointer to the SIOP structure    */
  726.     SYM895_HW_OPTIONS *  pHwOptions     /* pointer to the Options Structure */
  727.     )
  728.     {
  729.     /* temporary store to hold current register values */
  730.    
  731.     UINT8 dmode;
  732.     UINT8 stest2;
  733.     UINT8 scntl3;
  734.     UINT8 ctest5;
  735.     UINT8 stest1;
  736.     UINT8 stest3;
  737.     UINT8 scntl1;
  738.     /* validate input parameters */
  739.     if ((pSiop == (SIOP *)NULL) || (pHwOptions == (SYM895_HW_OPTIONS *)NULL))
  740.         return (ERROR);
  741.     /* Fill in the SIOP structure with new HwOptions */
  742.     memcpy ((char *)&(pSiop->hwOptions), (char *)pHwOptions,
  743.             sizeof(SYM895_HW_OPTIONS));
  744.     /* store the current values */
  745.     dmode  = SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE);
  746.     stest1 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST1);
  747.     stest2 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2);
  748.     stest3 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST3);
  749.     scntl1 = SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL1);
  750.     scntl3 = SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3);
  751.     ctest5 = SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST5);
  752.     /* Manipulate according to the options set */
  753.     (pHwOptions->DIOM)?
  754.     (dmode |= SYM895_DMODE_DIOM):(dmode &= ~SYM895_DMODE_DIOM);
  755.     (pHwOptions->SIOM)?
  756.     (dmode |= SYM895_DMODE_SIOM):(dmode &= ~SYM895_DMODE_SIOM);
  757.     (pHwOptions->SCLK)?
  758.     (stest1 |= SYM895_STEST1_SCLK):(stest1 &= ~SYM895_STEST1_SCLK);
  759.     (pHwOptions->DIF)?
  760.     (stest2 |= SYM895_STEST2_DIF):(stest2 &= ~SYM895_STEST2_DIF);
  761.     (pHwOptions->SCE)?
  762.     (stest2 |= SYM895_STEST2_SCE):(stest2 &= ~SYM895_STEST2_SCE);
  763.     (pHwOptions->AWS)?
  764.     (stest2 |= SYM895_STEST2_AWS):(stest2 &= ~SYM895_STEST2_AWS);
  765.     (pHwOptions->EXTEND)?
  766.     (stest2 |= SYM895_STEST2_EXT):(stest2 &= ~SYM895_STEST2_EXT);
  767.     (pHwOptions->TE)?
  768.     (stest3 |= SYM895_STEST3_TE):(stest3 &= ~SYM895_STEST3_TE);
  769.     (pHwOptions->EXC)?
  770.     (scntl1 |= SYM895_SCNTL1_EXC):(scntl1 &= ~SYM895_SCNTL1_EXC);
  771.     (pHwOptions->ULTRA)?
  772.     (scntl3 |= SYM895_SCNTL3_ULTRA):(scntl3 &= ~SYM895_SCNTL3_ULTRA);
  773.     (pHwOptions->EWS)?
  774.     (scntl3 |= SYM895_SCNTL3_EWS):(scntl3 &= ~SYM895_SCNTL3_EWS);
  775.     (pHwOptions->DFS)?
  776.     (ctest5 |= SYM895_CTEST5_DFS):(ctest5 &= ~SYM895_CTEST5_DFS);
  777.     /*
  778.      * The Burst lengths 32,64 and 128 transfers are valid only if FIFO 
  779.      * size is set to 816 bytes. Avoid setting CTEST5:BL2 when DMA FIFO 
  780.      * is set to 112 byes (CTEST5:DFS == 0). 
  781.      */
  782.     if (!(pHwOptions->DFS))
  783.         {
  784.         if ((pHwOptions->BL) & 0x04)
  785.             {
  786.             SCSI_MSG("sym895SetHwOptions: Erroneous Burstlength size for 
  787.                      112 byte FIFO n", 0, 0, 0, 0, 0, 0);
  788.             }
  789.         /* Forcing the burst length to a lesser value */
  790.         ctest5 &= ~SYM895_CTEST5_BL2;
  791.         }
  792.     else
  793.         {
  794.         ((pHwOptions->BL) & 0x4)?
  795.         (ctest5 |= SYM895_CTEST5_BL2):(ctest5 &= ~SYM895_CTEST5_BL2);
  796.         }
  797.     ((pHwOptions->BL) & 0x1)?
  798.      (dmode |= SYM895_DMODE_BL0):(dmode &= ~SYM895_DMODE_BL0);
  799.     ((pHwOptions->BL) & 0x2)?
  800.      (dmode |= SYM895_DMODE_BL1):(dmode &= ~SYM895_DMODE_BL1);
  801.     /* Now Update the Registers with user Options */
  802.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE,  dmode);
  803.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, stest1);
  804.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2, stest2);
  805.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST3, stest3);
  806.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL1, scntl1);
  807.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL3, scntl3);
  808.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST5, ctest5); 
  809.     /* 
  810.      * Note that the SCLK bit needs to be reset if Quadrapler is to be 
  811.      * enabled.
  812.      */
  813.     if ((pHwOptions->QEN) && !(stest1 & SYM895_STEST1_SCLK))
  814.         {
  815.         stest1 |= SYM895_STEST1_QEN;
  816.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, stest1);
  817.         /* Poll STEST4:LOCK to ensure that the chip is locked to 160MHz.*/
  818. while (!(SYM895_REG8_READ (pSiop, SYM895_OFF_STEST4) &  
  819.                  SYM895_STEST4_LOCK))
  820.             ;
  821.         /* Halt the SCSI Clock */
  822.         stest3 |= SYM895_STEST3_HSC;
  823.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST3, stest3);
  824.         /* 
  825.          * Set the CCF and SCF bits. Now since the SCF is dependent on the
  826.          * target, a default value is set which can be changed later by
  827.          * sym895ThreadActivate()
  828.          */
  829.         SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL3,
  830.                            SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) | 
  831.                            pSiop->clkDiv);
  832.         /* Set the SCLK Quadrapler select bit */
  833.         stest1 |= SYM895_STEST1_QSEL;
  834.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, stest1);
  835.         /* Clear the halt on SCSI Clock */
  836.         stest3 &= ~SYM895_STEST3_HSC;
  837.         SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST3, stest3);
  838.         }
  839.     return (OK);
  840.     }
  841. /*******************************************************************************
  842. *
  843. * sym895Intr - interrupt service routine for the SCSI Controller.
  844. *
  845. * The first thing to determine is whether the device is generating an interrupt
  846. * If not, then this routine must exit as quickly as possible.
  847. *
  848. * Find the event type corresponding to this interrupt, and carry out any
  849. * actions which must be done before the SCSI Controller is re-started.  
  850. * Determine  whether or not the SCSI Controller is connected to the bus 
  851. * (depending on the event type - see note below).  If not, start a client 
  852. * script if possible or else just make the SCSI Controller wait for something 
  853. * else to happen.
  854. *
  855. * The "connected" variable, at the end of switch statement, reflects the status
  856. * of the currently executing thread. If it is TRUE it means that the thread is
  857. * suspended and must be processed at the task level. Set the state of 
  858. * SIOP to IDLE and leave the control to the SCSI Manager. The SCSI Manager, 
  859. * in turn invokes the driver through a "resume" call.
  860. *
  861. * Notify the SCSI manager of a controller event.
  862. *
  863. * RETURNS N/A
  864. */
  865. void sym895Intr
  866.     (
  867.     SIOP * pSiop        /* pointer to the SIOP structure    */
  868.     )
  869.     {     
  870.     SYM895_EVENT        event;
  871.     SCSI_EVENT    *     pScsiEvent = (SCSI_EVENT *)&event.scsiEvent;
  872.     SCSI_CTRL     *     pScsiCtrl  = (SCSI_CTRL *)pSiop;
  873.     SYM895_THREAD *     pThread    = (SYM895_THREAD *)pSiop->pCurThread;
  874.     BOOL          connected = FALSE;
  875.     BOOL          notify    = TRUE;
  876.     SYM895_STATE  oldState  = (int)(pSiop->state);
  877.     static   UINT32 curBusMode = SYM895_BUSMODE_LVD;
  878.     UINT8    tempBusMode;
  879.     UINT8    stime1;
  880.     CACHE_PIPE_FLUSH();
  881.     /* Save (partial) Controller register context in current thread */
  882.     pThread->nHostFlags = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA0);
  883.     pThread->msgOutStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA1);
  884.     pThread->msgInStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA2);
  885.     pThread->targetId = SYM895_REG8_READ (pSiop, SYM895_OFF_SSID); 
  886.     pThread->busPhase = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA3); 
  887.  
  888.     pThread->sxfer  = SYM895_REG8_READ (pSiop, SYM895_OFF_SXFER);
  889.     pThread->scntl3 = SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3);
  890. #ifdef SCATTER_GATHER
  891.     /* support for scatter gather memory */
  892.     pThread->isScatTransfer = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHC0);
  893.     pThread->totalScatElements = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHC1);
  894.     pThread->noRemaining = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHC2);
  895. #endif
  896.     if ((pScsiEvent->type = sym895EventTypeGet (pSiop)) == ERROR)
  897. return;
  898.  
  899.     SYM895_SCSI_DEBUG_MSG ("sym895Intr: DSA=0x%08x, DSP=0x%08x, type = %d. n",
  900.                            SYM895_REG32_READ(pSiop, SYM895_OFF_DSA),
  901.                            SYM895_REG32_READ(pSiop, SYM895_OFF_DSP),
  902.                            pScsiEvent->type,0,0,0);
  903.     /* Synchronise with single-step routine, if enabled. */
  904.     if (pSiop->isSingleStep)
  905.      semGive (pSiop->singleStepSem);
  906.     if (pScsiEvent->type == SYM895_SINGLE_STEP)
  907.         return;
  908.     
  909.     /* Process the events */
  910.     switch (pScsiEvent->type)
  911.         {
  912.         /*
  913.          * For events where the bus is not connected to a target,
  914.          * set connected=FALSE.
  915.          * For events where the Thread is disconnected / completed
  916.          * set isThreadRunning = FALSE else set it to TRUE
  917.          * For events not requiring scsi manager, set notify = FALSE.
  918.          */
  919.         /* The following are the events generated by the Scripts */
  920.         case SYM895_CMD_COMPLETE       :
  921.         case SYM895_DISCONNECTED       :
  922.              connected = FALSE;
  923.              break;
  924.         case SYM895_MESSAGE_OUT_SENT   :
  925.         case SYM895_MESSAGE_IN_RECVD   :
  926.         case SYM895_EXT_MESSAGE_SIZE   :
  927.         case SYM895_NO_MSG_OUT         :
  928.         case SYM895_SCRIPT_ABORTED     :
  929.              connected = TRUE;
  930.              break;
  931.         case SYM895_PHASE_MISMATCH     :
  932.              event.remCount = sym895RemainderGet (pSiop, pThread->busPhase);  
  933.              connected = TRUE;
  934.              break;
  935.         /* 
  936.          * Folowing result from asynchronous conditions. Not directly from 
  937.          * SCRIPTS 
  938.          */
  939.         case SYM895_READY             :
  940.              connected = FALSE;
  941.              notify = FALSE;
  942.              break;
  943.         case SYM895_SELECTED          :
  944.         case SYM895_RESELECTED        :
  945.              pScsiEvent->busId = (pThread->targetId) & SYM895_SSID_ENC_MASK;
  946.              pScsiEvent->nBytesIdent = 
  947.                         (pThread->nHostFlags & SYM895_FLAGS_IDENTIFY) ? 1 : 0;
  948.              connected = TRUE;
  949.              break;
  950.         case SYM895_SCSI_BUS_RESET     :
  951.              connected = FALSE;
  952.              break;
  953.         case SYM895_BUSMODE_CHANGED    :
  954.              /* Don't run the scripts until, Bus Mode is set properly */
  955.              connected = TRUE;
  956.              /* 
  957.               * Wait for 100 ms before deciding that SCSI bus mode has
  958.               * really changed.It would have been ideal had it been implemented
  959.               * in Hardware.The GEN timer in STIME1 is used for 100ms.
  960.               */
  961.              /* First, reset the timer */
  962.              stime1 = SYM895_REG8_READ (pSiop, SYM895_OFF_STIME1);
  963.              stime1 &= ~SYM895_STIME1_GEN_MASK;
  964.              SYM895_REG8_WRITE (pSiop,SYM895_OFF_STIME1, stime1);
  965.              /* Now, set the timer for 100 MS */
  966.              stime1 |= SYM895_GEN_128MS;
  967.              SYM895_REG8_WRITE (pSiop,SYM895_OFF_STIME1, stime1);
  968.              /* Now wait for the Timer interrupt */
  969.              /* 
  970.               * If another Bus mode change interrupt occurs before 
  971.               * the timer expires, re-initialize the timer .              
  972.               */
  973.              notify = FALSE;
  974.              break;
  975.         case SYM895_GEN_TIMER_EXPIRED  :
  976.              /* Change the Bus mode. */
  977.              tempBusMode = (SYM895_REG8_READ (pSiop, SYM895_OFF_STEST4) & 
  978.                             SYM895_STEST4_SMODE_MASK)>>SYM895_BUSMODE_SHIFT;
  979.              if (tempBusMode == SYM895_BUSMODE_HVD)
  980.                  SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2,
  981.                                     SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2) |
  982.                                     SYM895_STEST2_DIF);
  983.              else if( curBusMode == SYM895_BUSMODE_HVD)
  984.                  SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2,
  985.                                     SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2) & 
  986.                                     ~SYM895_STEST2_DIF);
  987.              curBusMode = tempBusMode;
  988.              /* Please refer to page 2-16, 2-17 of data manual */
  989.              SYM895_REG8_WRITE( pSiop, SYM895_OFF_STEST0,
  990.                                 SYM895_REG8_READ (pSiop, SYM895_OFF_STEST0) |
  991.                                 (tempBusMode << SYM895_BUSMODE_SHIFT));
  992.              /* Now the Bus Mode is set properly.*/
  993.              /* reset the timer */
  994.              stime1 = SYM895_REG8_READ (pSiop, SYM895_OFF_STIME1);
  995.              stime1 &= ~SYM895_STIME1_GEN_MASK;
  996.              SYM895_REG8_WRITE (pSiop,SYM895_OFF_STIME1, stime1);
  997.              /* 
  998.               * If curBusMode is Single-ended check for the register bits 
  999.               * for Quadrupler, Ultra Enable . As these features are valid 
  1000.               * for LVD and HVD, these should be disabled for Single-Ended 
  1001.               * devices. Also, lower down the asynchronous
  1002.               * transfer rate.
  1003.               */
  1004.              if (curBusMode == SYM895_BUSMODE_SE)
  1005.                  {
  1006.                  if ((SYM895_REG8_READ (pSiop, SYM895_OFF_STEST1) & 
  1007.                                         SYM895_STEST1_QEN)) 
  1008.                      {
  1009.                      /* Disable Clock Quadrupler */
  1010.                      SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, 
  1011.                                         SYM895_REG8_READ (pSiop, 
  1012.                                                           SYM895_OFF_STEST1) &
  1013.                                         (~(SYM895_STEST1_QEN |
  1014.                                          SYM895_STEST1_QSEL)));
  1015.                      }
  1016.                  
  1017.                  /* 
  1018.                   * Ultra SCSI transfer rates are not possible with
  1019.                   * single-ended devices. So lower the async. clock
  1020.                   * conversion factor by hard coding to 40Mhz.
  1021.                   */
  1022.                  pSiop->clkPeriod = SYM895_40MHZ;
  1023.                  pSiop->clkDiv = SYM895_3750MHZ_ASYNC_DIV;
  1024.                  SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL3,
  1025.                                     SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) |
  1026.                                     pSiop->clkDiv);
  1027.                  } /* SYM895_BUSMODE_SE */
  1028.              /* If the current bus mode is HVD, Bit5 in STEST2 should be set */
  1029.              else if (curBusMode == SYM895_BUSMODE_HVD)
  1030.                  {
  1031.                  SYM895_REG8_WRITE (pSiop,SYM895_OFF_STEST2,
  1032.                                     SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2)|
  1033.                                     SYM895_STEST2_DIF);
  1034.                  } 
  1035.             /* run the scripts now */
  1036.             connected = FALSE;
  1037.             notify = FALSE;
  1038.             break;
  1039.         /* Following are error conditions, both asynchronous and synchronous */
  1040.         case SYM895_SCSI_TIMEOUT        :
  1041.         case SYM895_HANDSHAKE_TIMEOUT   :
  1042.              connected = FALSE;
  1043.              break;
  1044.         case SYM895_ILLEGAL_PHASE       :
  1045.              connected = TRUE;
  1046.              break;
  1047.         case SYM895_UNEXPECTED_DISCON   :
  1048.              connected = FALSE;
  1049.              break;
  1050.         case SYM895_NO_IDENTIFY         :
  1051.              SCSI_MSG ("sym895Intr: No Valid Identify message at (re)select. n",
  1052.                        0, 0, 0, 0, 0, 0);
  1053.              connected = TRUE;
  1054.              break;
  1055.         case SYM895_SPURIOUS_CMD        :
  1056.              SCSI_MSG(" sym895Intr: Spurious Command Interrupt. n",
  1057.                       0, 0, 0, 0, 0, 0);
  1058.              connected = FALSE;
  1059.              break;
  1060.         case SYM895_FATAL_ERROR         :
  1061.              SCSI_MSG (" sym895Intr: Fatal Error, Restarting SIOP... n",
  1062.                        0, 0, 0, 0, 0, 0);
  1063.              sym895HwInit (pSiop);
  1064.              connected = FALSE;
  1065.              break;
  1066. default     :
  1067.              SCSI_MSG ("sym895Intr: Un known interrupt (%d) n",
  1068.                        pScsiEvent->type, 0 ,0 ,0 ,0 ,0);
  1069.              connected = FALSE;
  1070.              break;
  1071. }
  1072.     /*
  1073.      *  Controller is now idle if possible, make it run a script.
  1074.      *
  1075.      * If a SCSI thread is suspended and must be processed at task-level,
  1076.      * leave the device idle.  It will be re-started by the SCSI manager
  1077.      * calling "sym895Resume()".
  1078.      *
  1079.      * Otherwise, if there's a new SCSI thread to start (i.e., the SCSI
  1080.      * manager has called "sym895Activate()"), start the appropriate script.
  1081.      *
  1082.      * Otherwise, start a script which puts the device into passive mode
  1083.      * waiting for re-selection, selection or a host command.
  1084.      *
  1085.      * In all cases, clear any request to start a new thread.  The only
  1086.      * tricky case is when there was a request pending and the device is
  1087.      * left IDLE.  This should only ever occur when the current event is
  1088.      * selection or reselection, in which case the SCSI manager will retry
  1089.      * the activation request.  (Also see "sym895Activate ()".)
  1090.      */
  1091.     if (connected)
  1092.         {
  1093.      pSiop->state = SYM895_STATE_IDLE;
  1094.         }
  1095.     else if (pSiop->isCmdPending)
  1096.         {
  1097.         sym895ScriptStart (pSiop, pSiop->pNewThread,
  1098.                            SYM895_SCRIPT_INIT_START);
  1099.         pSiop->state = SYM895_STATE_ACTIVE;
  1100.         }
  1101.     else
  1102.         {
  1103.         sym895ScriptStart (pSiop, (SYM895_THREAD *) pScsiCtrl->pIdentThread,
  1104.                            SYM895_SCRIPT_WAIT);
  1105.         pSiop->state = SYM895_STATE_PASSIVE;
  1106.         }
  1107.     pSiop->isCmdPending = FALSE;
  1108.     SYM895_SCSI_DEBUG_MSG ("sym895Intr state %d -> %dn",
  1109.                oldState, pSiop->state, 0, 0, 0, 0);
  1110.     /* Send the event to the SCSI manager to be processed. */
  1111.     if (notify)
  1112.      scsiMgrEventNotify ((SCSI_CTRL *) pSiop, pScsiEvent, sizeof (event));
  1113.     }
  1114. /*******************************************************************************
  1115. *
  1116. * sym895RemainderGet - get the number of bytes remaining in "Data Path" because of
  1117. * phase mismatch.
  1118. *
  1119. * The Information transfer phase which halted because of the mismatch has been
  1120. * saved as a part of the SIOP's register context.
  1121. * 895 has few registers helping us out in calculating how many bytes are 
  1122. * left not transferred because of some error condition.
  1123. * The Registers are.. DFIFO, DBC, SSAT0, SSAT1, SIDx, SODx.
  1124. *
  1125. * DFIFO register contains the number of bytes transferred between DMA core and
  1126. * the SCSI Bus. The DBC register contains the number of bytes transferred 
  1127. * across the HostBus. The difference between these two will give the number of 
  1128. * bytes in the DMA Fifo....But hold on..There are more issues involved.
  1129. * Please refer to chapter 2 of the 895 data manual.
  1130. *
  1131. * RETURNS: number of bytes remained in the data path.
  1132. *
  1133. * Note : This function is called at interrupt level.
  1134. *
  1135. * NOMANUAL
  1136. */
  1137. LOCAL UINT sym895RemainderGet 
  1138.     (
  1139.     SIOP * pSiop,            /* pointer to controller information */
  1140.     UINT   phase             /* phase, terminated by mismatch */
  1141.     )
  1142.     {
  1143.     UINT      remCount;
  1144.     UINT16    tmpCount;
  1145.     UINT16    countFifo;
  1146.     UINT16    fifoMask;
  1147.     /* Read the Number of bytes transferred across the host bus */
  1148.     remCount = SYM895_REG32_READ (pSiop,SYM895_OFF_DBC) & SYM895_COUNT_MASK;
  1149.     /* 
  1150.      * check if the dma fifo is 816 bytes or 112 bytes. 
  1151.      * accordingly the mask being applied will change 
  1152.      */
  1153.  
  1154.     if (SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST5) & SYM895_CTEST5_BL2)
  1155.         fifoMask = SYM895_FIFO_816_MASK;
  1156.     else
  1157.         fifoMask = SYM895_FIFO_112_MASK;
  1158.     tmpCount  = (remCount & fifoMask);
  1159.     countFifo = SYM895_REG8_READ (pSiop,SYM895_OFF_DFIFO);
  1160.     if (fifoMask == SYM895_FIFO_816_MASK) /* Fifo size is 816 bytes */
  1161.         {
  1162.         /* Extract b0,b1 from CTEST5 and concatenate with countfifo.*/
  1163.         countFifo |= ((UINT16)(SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST5) & 
  1164.                                0x03) << 8);
  1165.         }
  1166.     countFifo &= fifoMask;
  1167.     /* Now DMA FIFO byte offset counter is in "countFifo" */
  1168.     tmpCount = (countFifo - remCount) & fifoMask;
  1169.     /* byte count is in "tmpCount" now */
  1170.     /* 
  1171.      * Now it depends on the direction of transfer. To know the direction
  1172.      * of transfer, check the phase.
  1173.      */
  1174.     switch (phase)
  1175.         {
  1176.         case PHASE_DATA_OUT     :
  1177.         case PHASE_MSG_OUT      :
  1178.         case PHASE_COMMAND      :
  1179.             /* Output phases : Check for data in output registers (SODx) */
  1180.             /* 
  1181.              * check the SSTAT0 and SSTAT2 registers to check if any bytes
  1182.              * are left in the SODL/SODR registers.
  1183.              */
  1184.             /* Check to see any data is there in SODL register */
  1185.             if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT0) & SYM895_SSTAT0_OLF)
  1186.                 tmpCount++;
  1187.             if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2) & SYM895_SSTAT2_OLF1)
  1188.                 tmpCount++;
  1189.             /* 
  1190.              * Check to see any data is there in SODR register 
  1191.              * Note that SODR reg. is bypassed for asynchronous transfers
  1192.              */
  1193.             /* if synchronous Send */
  1194.             if (((pSiop->pCurThread->sxfer) & SYM895_SXFER_OFF_MASK) != 0)
  1195.                 {
  1196.                 if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT0) & 
  1197.                                       SYM895_SSTAT0_OLF)
  1198.                     tmpCount++;
  1199.                 if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2) & 
  1200.                                       SYM895_SSTAT2_OLF1)
  1201.                     tmpCount++;
  1202.                 }
  1203.             /* Finally, add this to "remCount" to get the complete count */
  1204.             remCount += tmpCount;
  1205.             break;
  1206.         case PHASE_DATA_IN :
  1207.         case PHASE_MSG_IN :
  1208.         case PHASE_STATUS :
  1209.             /* These are input phases check for data in input registers */
  1210.             /* The following for asynchronous transfers */
  1211.             if (((pSiop->pCurThread->sxfer) & SYM895_SXFER_OFF_MASK) == 0)
  1212.                 {
  1213.                 if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT0) & 
  1214.                                       SYM895_SSTAT0_ILF)
  1215.                     tmpCount++;
  1216.                 if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2) & 
  1217.                                       SYM895_SSTAT2_ILF1)
  1218.                     tmpCount++;
  1219.                 }
  1220.             else
  1221.                 {
  1222. /* 
  1223.                  * For Sync. transfers add the total count, the number of bytes
  1224.  * in the sync FIFO.
  1225.    */
  1226. tmpCount += (((SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT1) & 
  1227.                                                  0xf0)>>4) |
  1228.                              (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2) & 
  1229.                                                 0x10));
  1230.                 }
  1231.                 break;
  1232.         default     :
  1233.             SCSI_MSG ("sym895RemainderGet: Invalid Phase %dn", phase,
  1234.                        0, 0, 0, 0, 0);
  1235.         }
  1236.     /* Clear FiFos */
  1237.     SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
  1238.                        SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3)| 
  1239.                        SYM895_CTEST3_CLF);
  1240.     return (remCount);
  1241.     }
  1242. /*******************************************************************************
  1243. *
  1244. * sym895Event - SCSI Controller event processing routine
  1245. *
  1246. * Parse the event type and act accordingly.  Controller-level events are
  1247. * handled within this function, and the event is then passed to the current
  1248. * thread (if any) for thread-level processing.
  1249. *
  1250. * Note the special case when (re)selection occurs: if there is a current
  1251. * thread when the event occurs, it receives the event (and is assumed to
  1252. * defer itself) before the identification thread is made current.  The
  1253. * event is then forwarded to the identification thread.
  1254. *
  1255. * RETURNS N/A
  1256. */
  1257. LOCAL void sym895Event
  1258.     (
  1259.     SIOP *         pSiop,
  1260.     SYM895_EVENT * pEvent
  1261.     )
  1262.     {
  1263.     SCSI_CTRL  *    pScsiCtrl  = (SCSI_CTRL *)  pSiop;
  1264.     SCSI_EVENT *    pScsiEvent = &pEvent->scsiEvent;
  1265.     SYM895_THREAD * pThread    = (SYM895_THREAD *) pScsiCtrl->pThread;
  1266.  
  1267.     SYM895_SCSI_DEBUG_MSG ("sym895Event:received event %d (thread = 0x%08x)n",
  1268.                            pScsiEvent->type, (int) pThread, 0, 0, 0, 0);
  1269.     /* Do controller-level event processing */
  1270.     switch (pScsiEvent->type)
  1271.         {
  1272.         case SYM895_SELECTED:
  1273.         case SYM895_RESELECTED:
  1274.             /*
  1275.              * Forward event to current thread, if any (it should defer)
  1276.              * then install a reserved thread for identification purposes.
  1277.              */
  1278.          if (pThread != 0)
  1279.                 sym895ThreadEvent (pThread, pEvent);
  1280.          pScsiCtrl->peerBusId = pScsiEvent->busId;
  1281.          pScsiCtrl->pThread = pScsiCtrl->pIdentThread;
  1282.     
  1283.             pScsiCtrl->pThread->role = (pScsiEvent->type == SCSI_EVENT_SELECTED)
  1284.                ? SCSI_ROLE_IDENT_TARG :
  1285.                                        SCSI_ROLE_IDENT_INIT;
  1286.             pThread = (SYM895_THREAD *) pScsiCtrl->pThread;
  1287.             scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED);
  1288.             break;
  1289.         case SYM895_DISCONNECTED:
  1290.         case SYM895_CMD_COMPLETE:
  1291.         case SYM895_UNEXPECTED_DISCON:
  1292.         case SYM895_SCSI_TIMEOUT:
  1293.             pScsiCtrl->peerBusId = NONE;
  1294.          pScsiCtrl->pThread   = 0;
  1295.             scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED);
  1296.    
  1297.             break;
  1298.         case SYM895_SCSI_BUS_RESET:
  1299.             pScsiCtrl->peerBusId = NONE;
  1300.             pScsiCtrl->pThread   = 0;
  1301.             scsiMgrBusReset (pScsiCtrl);
  1302.             break;
  1303.         default:
  1304.             /*
  1305.              * Any other event type is assumed to be thread-specific.
  1306.              * The thread event handler will report an error if it's
  1307.              * not a valid type.
  1308.              */
  1309.             if (pThread == 0)
  1310.                 {
  1311.                 SCSI_MSG ("sym895Event invalid event type (%d)n",
  1312.                           pScsiEvent->type, 0, 0, 0, 0, 0);
  1313.                 }
  1314.             break;
  1315.         }
  1316.     /* If there's a thread on the controller, forward the event to it */
  1317.     if (pThread != 0)
  1318.         sym895ThreadEvent (pThread, pEvent);
  1319.     }
  1320.     
  1321. /******************************************************************************
  1322. *
  1323. * sym895ThreadInit - initialize a client thread structure
  1324. *
  1325. * Initialize the fixed data for a thread (i.e., independent of the command).
  1326. * Called once when a thread structure is first created.
  1327. *
  1328. * RETURNS OK, or ERROR if an error occurs
  1329. *
  1330. * NOMANUAL
  1331. */
  1332. LOCAL STATUS sym895ThreadInit
  1333.     (
  1334.     SIOP *          pSiop,
  1335.     SYM895_THREAD * pThread
  1336.     )
  1337.     {
  1338.     
  1339.     if (scsiThreadInit (&pThread->scsiThread) != OK)
  1340.         return (ERROR);
  1341.     pThread->pShMem = pSiop->pClientShMem;
  1342.     pThread->scntl3 = pSiop->clkDiv;
  1343.     return (OK);
  1344.     }
  1345. /******************************************************************************
  1346. *
  1347. * sym895IdentThreadInit - initialize an identification thread structure
  1348. *
  1349. * Set up pointers and counts for all buffers other than messages.  Also set
  1350. * transfer parameters for asynchronous mode, and update the shared memory
  1351. * area to match this thread.
  1352. *
  1353. * NOTE:
  1354. * The pointers/counts set here are normally never used by the identification
  1355. * thread; however, when an identification thread is aborted, it's possible
  1356. * that the target will attempt to transfer one or more non-message bytes
  1357. * before requesting the abort message out.  To handle this, the thread's
  1358. * pointers and counts all specify a dummy buffer.  There is no re-entrancy
  1359. * problem here because we do not care what data is transferred.  This might
  1360. * be handled more elegantly if there were a special script entry to abort
  1361. * an identification thread.
  1362. *
  1363. * RETURNS: OK, or ERROR if an error occurs
  1364. *
  1365. * NOMANUAL
  1366. */
  1367. LOCAL STATUS sym895IdentThreadInit
  1368.     (
  1369.     SYM895_THREAD * pThread
  1370.     )
  1371.     {
  1372.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1373.     SIOP *        pSiop       = (SIOP *) pScsiThread->pScsiCtrl;
  1374.     static UINT8  dummy;
  1375.     
  1376.     /*
  1377.      * Initialise Pointers and counts in thread
  1378.      */
  1379.     pScsiThread->cmdLength         = 1;
  1380.     pScsiThread->cmdAddress        = &dummy;
  1381.     pScsiThread->dataLength        = 1;
  1382.     pScsiThread->dataAddress       = &dummy;
  1383.     pScsiThread->activeDataLength  = 1;
  1384.     pScsiThread->activeDataAddress = &dummy;
  1385.     pScsiThread->savedDataLength   = 1;
  1386.     pScsiThread->savedDataAddress  = &dummy;
  1387.     pScsiThread->statusLength      = 1;
  1388.     pScsiThread->statusAddress     = &dummy;
  1389.     pScsiThread->identMsgLength    = 1;
  1390.     
  1391.     /*
  1392.      * Initialise SIOP register context in thread
  1393.      */
  1394.     pThread->nHostFlags   = 0;
  1395.     pThread->msgOutStatus = SCSI_MSG_OUT_NONE;
  1396.     pThread->msgInStatus  = SCSI_MSG_IN_NONE;
  1397.     pThread->sxfer = SYM895_ASYNC_SXFER;
  1398.     /*
  1399.      * The value set in scntl3 for the ident message is chosen based on the.
  1400.      * following reasons ...
  1401.      * 1. Ident message is Async by default. So the bits SCFx donot matter now.
  1402.      * 2. The target can be an Ultra SCSI or just FAST SCSI, so can't
  1403.      *    enable those ULTRA bits now, effectively ruling out the possibility
  1404.      *   of using 160/80 MHz SCSI Clocks for ident message.
  1405.      * 3. We chose to hardcode the value of 50 Mhz into scntl3 for ident 
  1406.      *    message. After negotiation, these values will suitably be changed.
  1407.      */
  1408.     pThread->scntl3 = SYM895_3750MHZ_ASYNC_DIV;  /* Hard Code */
  1409.     /* pThread->scntl3 = pSiop->clkDiv; */
  1410.     /* Initialise shared memory area */
  1411.     pThread->pShMem = pSiop->pIdentShMem;
  1412.     
  1413.     sym895SharedMemInit (pSiop, pThread->pShMem);
  1414.     sym895ThreadUpdate (pThread);
  1415.     
  1416.     return (OK);
  1417.     }
  1418. /******************************************************************************
  1419. *
  1420. * sym895SharedMemInit - initialize the fields in a shared memory area
  1421. *
  1422. * Initialise pointers and counts for all message transfers.  These are
  1423. * always directed to buffers provided by the SCSI_CTRL structure.
  1424. *
  1425. * RETURNS: N/A
  1426. *
  1427. * NOMANUAL
  1428. */
  1429. LOCAL void sym895SharedMemInit
  1430.     (
  1431.     SIOP *          pSiop,
  1432.     SYM895_SHARED * pShMem
  1433.     )
  1434.     {
  1435.     /*
  1436.      * Note: All the values being set in the shared memory need to be
  1437.      * 32 bit byte swapped. Actual swapping takes place when, when memory
  1438.      * is big endian (since the SYM895 is a little endian PCI device. 
  1439.      * Otherwise, if memory is little endian then the byte swapping 
  1440.      * does not do anything. The "endianness" is configurable at compile
  1441.      * time.
  1442.      *
  1443.      * Similarly, a PCI offset is added to all addresses so that the
  1444.      * SYM895 PCI chip can get to memory. This value is also configurable
  1445.      * at compile time.
  1446.      */
  1447.     pShMem->identIn.size = SYM895_SWAP_32 (1);
  1448.     pShMem->identIn.addr = (UINT8 *)SYM895_SWAP_32 (SYM895_VIRT_TO_PHYS 
  1449.                                                    (pSiop->scsiCtrl.identBuf));
  1450.     pShMem->msgOut.size = SYM895_SWAP_32 (0); /* set dynamically */
  1451.     pShMem->msgOut.addr = (UINT8 *)SYM895_SWAP_32 (SYM895_VIRT_TO_PHYS 
  1452.                                                   (pSiop->scsiCtrl.msgOutBuf));
  1453.     
  1454.     pShMem->msgIn.size  = SYM895_SWAP_32 (1);
  1455.     pShMem->msgIn.addr  = (UINT8 *)SYM895_SWAP_32 (SYM895_VIRT_TO_PHYS 
  1456.                                                   (pSiop->scsiCtrl.msgInBuf));
  1457.     pShMem->msgInSecond.size = SYM895_SWAP_32 (1);
  1458.     pShMem->msgInSecond.addr = (UINT8 *)SYM895_SWAP_32 (SYM895_VIRT_TO_PHYS 
  1459.                                                      (pSiop->scsiCtrl.msgInBuf)
  1460.                                                      + (UINT) 1);
  1461.     pShMem->msgInRest.size = SYM895_SWAP_32 (0);  /* set dynamically */
  1462.     pShMem->msgInRest.addr = (UINT8 *)SYM895_SWAP_32 (SYM895_VIRT_TO_PHYS
  1463.                                                      (pSiop->scsiCtrl.msgInBuf)
  1464.                                                       + (UINT) 2);
  1465.     }
  1466. /******************************************************************************
  1467. *
  1468. * sym895ThreadActivate - activate a SCSI connection for an initiator thread
  1469. *
  1470. * Set whatever thread/controller state variables need to be set.  Ensure that
  1471. * all buffers used by the thread are coherent with the contents of the
  1472. * system caches (if any).
  1473. *
  1474. * Set transfer parameters for the thread based on what its target device
  1475. * last negotiated.
  1476. *
  1477. * Update the thread context (including shared memory area) and note that
  1478. * there is a new client script to be activated (see "sym895Activate()").
  1479. *
  1480. * Set the thread's state to ESTABLISHED.
  1481. * Do not wait for the script to be activated.  Completion of the script will
  1482. * be signalled by an event which is handled by "sym895Event()".
  1483. *
  1484. * RETURNS OK or ERROR
  1485. *
  1486. * NOMANUAL
  1487. */
  1488. LOCAL STATUS sym895ThreadActivate
  1489.     (
  1490.     SIOP *          pSiop, /* pointer to SIOP structure */
  1491.     SYM895_THREAD * pThread /* pointer to thread structure */
  1492.     )
  1493.     {
  1494.     SCSI_CTRL *   pScsiCtrl   = (SCSI_CTRL *) pSiop;
  1495.     SCSI_THREAD * pScsiThread = &pThread->scsiThread;
  1496.     SCSI_TARGET * pScsiTarget = pScsiThread->pScsiTarget;
  1497.     
  1498.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadActivate: thread 0x%08x activatingn",
  1499.               (int) pThread, 0, 0, 0, 0, 0);
  1500.     /* Ensure buffers used by the thread are coherent with system cache */
  1501.     scsiCacheSynchronize (pScsiThread, SCSI_CACHE_PRE_COMMAND);
  1502.     /* Reset controller state variables set sync xfer parameters */
  1503.     pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE;
  1504.     pScsiCtrl->msgInState  = SCSI_MSG_IN_NONE;
  1505.     
  1506.     /*
  1507.      * A wide transfer is initiated before a synchronous transfer. However,
  1508.      * when a wide transfer has been done the next activation causes the
  1509.      * synchronous transfer to be activated. Another possible but more
  1510.      * complicated way to implement this would be to have both wide and
  1511.      * synchronous negotiations in the same activation or thread i.e.
  1512.      * the same SCSI transaction.
  1513.      */
  1514.     scsiWideXferNegotiate (pScsiCtrl, pScsiTarget, WIDE_XFER_NEW_THREAD);
  1515.     scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD);
  1516.     if (sym895ThreadParamsSet (pThread, pScsiTarget->xferOffset,
  1517.                                pScsiTarget->xferPeriod) != OK)
  1518.         {
  1519.         SYM895_SCSI_DEBUG_MSG ("sym895ThreadActivate failed to set thread  "
  1520.                   "params.n", 0, 0, 0, 0, 0, 0);
  1521.         return (ERROR);
  1522.         }
  1523.     /*
  1524.      *  Concatenate the ident message with a pending 'normal' message out,
  1525.      *  if possible.  This allows the script to send the first message out
  1526.      *  within the same MSG OUT phase as the IDENTIFY message - needed on
  1527.      *  some target systems (e.g. DG Clariion RAID) to avoid the message
  1528.      *  being rejected(!). The identMsg buffer in pSiop structure is 
  1529.      *  initialised here which will be used for the current thread's IdentOut
  1530.      *  buffer.
  1531.      */
  1532.     pSiop->identMsgLength = 0;
  1533.     bcopy ((char *) pScsiThread->identMsg,
  1534.            (char *) pSiop->identMsg,
  1535.            pScsiThread->identMsgLength);
  1536.     pSiop->identMsgLength += pScsiThread->identMsgLength;
  1537.     if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)
  1538.         {
  1539.         bcopy ((char *) pScsiCtrl->msgOutBuf,
  1540.                (char *) pSiop->identMsg + pSiop->identMsgLength,
  1541.                pScsiCtrl->msgOutLength);
  1542.         pSiop->identMsgLength += pScsiCtrl->msgOutLength;
  1543.         }
  1544.     /* Update thread context; activate the thread */
  1545.     sym895ThreadUpdate (pThread);
  1546.     
  1547.     if (sym895Activate (pSiop, pThread) != OK)
  1548.         {
  1549.         SYM895_SCSI_DEBUG_MSG ("sym895ThreadActivate: failed to 
  1550.                                 activate thread.n", 0, 0, 0, 0, 0, 0);
  1551.         return (ERROR);
  1552.         }
  1553.     pScsiCtrl->pThread = pScsiThread;
  1554.     sym895ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
  1555.     
  1556.     return (OK);
  1557.     }
  1558. /******************************************************************************
  1559. *
  1560. * sym895ThreadAbort - abort a thread
  1561. *
  1562. * If the thread is not currently connected, do nothing and return FALSE to
  1563. * indicate that the SCSI manager should abort the thread.
  1564. *
  1565. * If the thread is active, build an ABORT or ABORT TAG message which will be 
  1566. * sent (eventually), causing the target to disconnect. Abort the current 
  1567. * script being run so that this message can be sent. Update the thread state
  1568. * and return TRUE to indicate that the controller driver will handle the abort
  1569. * process. 
  1570. * RETURNS TRUE if the thread is being aborted by this driver (i.e. it is
  1571. * currently active on the controller, else FALSE.
  1572. *
  1573. * NOMANUAL
  1574. */
  1575. LOCAL BOOL sym895ThreadAbort
  1576.     (   
  1577.     SIOP *          pSiop, /* pointer to controller structure */
  1578.     SYM895_THREAD * pThread /* pointer to thread structure     */
  1579.     )
  1580.     {
  1581.     BOOL          tagged;
  1582.     SCSI_CTRL *   pScsiCtrl   = (SCSI_CTRL *)   pSiop;
  1583.     SCSI_THREAD * pScsiThread = &pThread->scsiThread;
  1584.     SYM895_SCSI_DEBUG_MSG ("sym895ThreadAbort: thread 0x%08x (state = %d) "
  1585.               "abortingn", (int)pThread, pScsiThread->state, 0, 0, 0, 0);
  1586.     /* If the requested thread is the not the currently run thread */
  1587.     if (pScsiThread != pScsiCtrl->pThread)
  1588. return (FALSE);
  1589.     
  1590.     switch (pScsiThread->state)
  1591.         {
  1592.         case SCSI_THREAD_INACTIVE:
  1593.         case SCSI_THREAD_WAITING:
  1594.         case SCSI_THREAD_DISCONNECTED:
  1595.             /* If thread not connected, do nothing.*/
  1596.             return (FALSE);
  1597.             break;
  1598.         default:
  1599.             /*
  1600.              * Build an ABORT (or ABORT TAG) message.  When this has been
  1601.              * sent, the target should disconnect.  Mark the thread aborted
  1602.              * and continue until disconnection.
  1603.              */
  1604.             
  1605.             /*  Check whether a tagged message is requested */
  1606.             tagged = (pScsiThread->tagNumber != NONE);
  1607.             pScsiCtrl->msgOutBuf[0] = tagged ? SCSI_MSG_ABORT_TAG :
  1608.                                                SCSI_MSG_ABORT;
  1609.             pScsiCtrl->msgOutLength = 1;
  1610.             pScsiCtrl->msgOutState  = SCSI_MSG_OUT_PENDING;
  1611.             /* Abort the current SCRIPT */
  1612.             sym895Abort (pSiop);
  1613.             /* Update the thread state */  
  1614.          sym895ThreadStateSet (pThread, SCSI_THREAD_ABORTING);
  1615.     break;
  1616.         }
  1617.     return (TRUE);
  1618.     }
  1619. /******************************************************************************
  1620. *
  1621. * sym895ScsiBusControl - miscellaneous low-level SCSI bus control operations
  1622. *
  1623. * Currently supports only the SCSI_BUS_RESET operation; other operations are
  1624. * not used explicitly by the driver because they are carried out automatically
  1625. * by the script program.
  1626. *
  1627. * NOTE after the SCSI bus has been reset, the SIOP generates a
  1628. * SYM895_BUS_RESET event via an interrupt,to be sent to the SCSI manager.
  1629. * See "sym895Intr()".
  1630. *
  1631. * RETURNS OK, or ERROR if an invalid operation is requested.
  1632. *
  1633. * NOMANUAL
  1634. */
  1635. LOCAL STATUS sym895ScsiBusControl
  1636.     (
  1637.     SIOP * pSiop,        /* pointer to controller info               */
  1638.     int    operation     /* bitmask for operation(s) to be performed */
  1639.     )
  1640.     {
  1641.     if (operation & SCSI_BUS_RESET)
  1642.         {
  1643.         sym895ScsiBusReset (pSiop);
  1644.         return (OK);
  1645.         }
  1646.     return (ERROR); /* unknown operation */
  1647.     }
  1648. /******************************************************************************
  1649. *
  1650. * sym895ScsiBusReset - assert the RST line on the SCSI bus 
  1651. *
  1652. * Issue a SCSI Bus Reset command to the SYM 895. This should put all devices
  1653. * on the SCSI bus in an initial quiescent state.
  1654. *
  1655. * The bus reset will generate an interrupt which is handled by the normal
  1656. * ISR (see "sym895Intr()").
  1657. *
  1658. * RETURNS: N/A
  1659. *
  1660. * NOMANUAL
  1661. */
  1662. LOCAL void sym895ScsiBusReset
  1663.     (
  1664.     FAST SIOP * pSiop /* pointer to SIOP info */
  1665.     )
  1666.     {
  1667.     int key;
  1668.     key = intLock ();
  1669.     /* assert the reset bit */
  1670.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL1,
  1671.                        SYM895_REG8_READ(pSiop, SYM895_OFF_SCNTL1) | 
  1672.                        SYM895_SCNTL1_RST);
  1673.    /* do it again to make sure that it took */
  1674.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL1,
  1675.                        SYM895_REG8_READ(pSiop, SYM895_OFF_SCNTL1) | 
  1676.                        SYM895_SCNTL1_RST);
  1677.     intUnlock (key);
  1678.     /* The RST signal should be asserted for a min. duration of 25u sec */
  1679.     taskDelay (1);
  1680.     /* Now clear the Reset signal..(de-assertion) */
  1681.     SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL1,
  1682.                        SYM895_REG8_READ(pSiop, SYM895_OFF_SCNTL1) & 
  1683.                        ~SYM895_SCNTL1_RST);
  1684.     }
  1685. /******************************************************************************
  1686. *
  1687. * sym895XferParamsQuery - get synchronous transfer parameters
  1688. *
  1689. * Updates the synchronous transfer parameters suggested in the call to match
  1690. * the  SYM 895 SCSI Controller's capabilities.  Transfer period is in SCSI units
  1691. * (multiples * of 4 ns).
  1692. *
  1693. * Note: The transfer period is made longer and the offset is made smaller if
  1694. * the SYM895 cannot handle the specified values.
  1695. *
  1696. * RETURNS OK
  1697. */
  1698. LOCAL STATUS sym895XferParamsQuery
  1699.     (
  1700.     SCSI_CTRL * pScsiCtrl,         /* pointer to controller structure */
  1701.     UINT8     * pOffset,           /* max REQ/ACK offset  [in/out]    */
  1702.     UINT8     * pPeriod            /* min transfer period [in/out]    */
  1703.     )
  1704.     {
  1705.     UINT8 unused; 
  1706.     (void)sym895XferParamsCvt ((SIOP *)pScsiCtrl, pOffset, pPeriod, 
  1707.                                &unused, &unused );
  1708.     return (OK);
  1709.     }
  1710.     
  1711. /******************************************************************************
  1712. *
  1713. * sym895XferParamsSet - set transfer parameters
  1714. *
  1715. * Validate the requested parameters, convert to the SYM895 SCSI Controller's 
  1716. * native format and save in the current thread for later use (the chip's
  1717. * registers are not actually set until the next script activation for this 
  1718. * thread).
  1719. *
  1720. * Transfer period is specified in SCSI units (multiples of 4 ns).  An offset
  1721. * of zero specifies asynchronous transfer.
  1722. *
  1723. * RETURNS OK if transfer parameters are OK, else ERROR.
  1724. */
  1725. LOCAL STATUS sym895XferParamsSet
  1726.     (
  1727.     SCSI_CTRL * pScsiCtrl, /* pointer to controller info */
  1728.     UINT8       offset, /* max REQ/ACK offset         */
  1729.     UINT8       period /* min transfer period        */
  1730.     )
  1731.     {
  1732.     SYM895_THREAD * pThread = (SYM895_THREAD *) pScsiCtrl->pThread;
  1733.     return (sym895ThreadParamsSet (pThread, offset, period));
  1734.     }
  1735. /******************************************************************************
  1736. *
  1737. * sym895WideXferParamsQuery - get wide data transfer parameters
  1738. *
  1739. * Updates the wide data transfer parameters suggested in the call to match
  1740. * the SYM895 SCSI Controller's capabilities.  Transfer width is in the units 
  1741. * of the WIDE DATA TRANSFER message's transfer width exponent field. This is
  1742. * an 8 bit field where 0 represents a narrow transfer of 8 bits, 1 represents
  1743. * a wide transfer of 16 bits and 2 represents a wide transfer of 32 bits.
  1744. *
  1745. * NOTE: The transfer width is made smaller if the SYM895 cannot handle the 
  1746. * specified value.
  1747. *
  1748. * RETURNS OK
  1749. */
  1750. LOCAL STATUS sym895WideXferParamsQuery
  1751.     (
  1752.     SCSI_CTRL * pScsiCtrl, /* pointer to controller structure  */
  1753.     UINT8     * xferWidth /* suggested transfer width         */
  1754.     )
  1755.     {
  1756.     if (*xferWidth > SYM895_MAX_XFER_WIDTH)
  1757. *xferWidth = SYM895_MAX_XFER_WIDTH;
  1758.     
  1759.     sym895WideXferParamsSet (pScsiCtrl, *xferWidth);
  1760.     return (OK);
  1761.     }
  1762. /******************************************************************************
  1763. *
  1764. * sym895WideXferParamsSet - set wide transfer parameters
  1765. *
  1766. * Assume valid parameters and set the SYM895's thread parameters to the
  1767. * appropriate values. The actual registers are not written yet, but will
  1768. * be written from the thread values when it is activated.
  1769. *
  1770. * Transfer width is specified in SCSI transfer width exponent units. 
  1771. *
  1772. * RETURNS OK 
  1773. */
  1774. LOCAL STATUS sym895WideXferParamsSet
  1775.     (
  1776.     SCSI_CTRL * pScsiCtrl, /* pointer to controller structure */
  1777.     UINT8       xferWidth  /* wide data transfer width        */
  1778.     )
  1779.     {
  1780.     SYM895_THREAD * pThread = (SYM895_THREAD *) pScsiCtrl->pThread;
  1781.      
  1782.     if ( xferWidth == SCSI_WIDE_XFER_SIZE_NARROW )
  1783.         {
  1784.            pThread->scntl3 &= ~SYM895_SCNTL3_EWS; /* Disable wide SCSI */
  1785.         }
  1786.     else 
  1787.         {
  1788.            pThread->scntl3 |= SYM895_SCNTL3_EWS;  /* Enable wide SCSI */
  1789.         }
  1790.     return (OK);
  1791.     }
  1792. /******************************************************************************
  1793. *
  1794. * sym895ThreadParamsSet - set various parameters for a thread
  1795. *
  1796. * Parameters include transfer offset and period, as well as the ID of the
  1797. * target device.  All of these end up as encoded values stored either in
  1798. * the thread's register context or its associated shared memory area.
  1799. *
  1800. * Transfer period is specified in SCSI units (multiples of 4 ns).  An offset
  1801. * of zero specifies asynchronous transfer.
  1802. *
  1803. * RETURNS OK if parameters are OK, else ERROR.
  1804. *
  1805. * NOMANUAL
  1806. */
  1807. LOCAL STATUS sym895ThreadParamsSet
  1808.     (
  1809.     SYM895_THREAD * pThread,      /* thread to be affected  */
  1810.     UINT8           offset, /* max REQ/ACK offset     */
  1811.     UINT8           period /* min transfer period    */
  1812.     )
  1813.     {
  1814.      
  1815.     SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
  1816.     SIOP *        pSiop       = (SIOP *) pScsiThread->pScsiCtrl;
  1817.     SCSI_TARGET * pScsiTarget = pScsiThread->pScsiTarget;
  1818.     UINT          busId       = pScsiTarget->scsiDevBusId;
  1819.     UINT8         xferWidth   = pScsiTarget->xferWidth;
  1820.      
  1821.     if ( !sym895XferParamsCvt (pSiop, &offset, &period, &pThread->sxfer,
  1822.                                &pThread->scntl3))
  1823.    {
  1824.       errnoSet(S_scsiLib_ILLEGAL_PARAMETER);
  1825.       return  (ERROR); 
  1826.       }
  1827.    
  1828.     /* Check whether WIDE transfer is requested */
  1829.     if ( xferWidth == SCSI_WIDE_XFER_SIZE_DEFAULT )
  1830.         {
  1831.    pThread->scntl3 |= SYM895_SCNTL3_EWS;
  1832.      }
  1833.     pThread->pShMem->device = SYM895_SWAP_32
  1834.                       (
  1835.                       (pThread->sxfer << SYM895_XFER_PARAMS_SHIFT) |
  1836.                       (busId << SYM895_TARGET_BUS_ID_SHIFT)        |
  1837.                       (pThread->scntl3 << 24)
  1838.                       );
  1839.     return (OK);
  1840.     }
  1841. /******************************************************************************
  1842. *
  1843. * sym895XferParamsCvt - convert transfer period from SCSI to SYM 53C895 units
  1844. *
  1845. * Given a "suggested" REQ/ACK offset and transfer period (in SCSI units of
  1846. * 4 ns), return the nearest offset and transfer period the SYM 53C895 is
  1847. * capable of using.  Also return the corresponding values of the SYM 53C895's
  1848. * Synchronous Transfer and Synchronous Bus Control registers.
  1849. *
  1850. * An offset of zero specifies asynchronous transfer, in which case the period
  1851. * is irrelevant.  Otherwise, the offset may be clipped to be within the
  1852. * maximum limit the SYM 53C885 is capable of.
  1853. *
  1854. * The transfer period is normally rounded towards longer periods if the SYM
  1855. * 53C895 is not capable of using the exact specified value.  The period may
  1856. * also be clipped to be within the SYM 53C895's maximum and minimum limits
  1857. * according to its clock period.
  1858. *
  1859. * If either the offset or period need to be clipped, the value FALSE is
  1860. * retuned as this may reflect an error condition.
  1861. *
  1862. * RETURNS: TRUE if input period is within SYM 53C895's range, else FALSE
  1863. *
  1864. * NOMANUAL
  1865. */
  1866. LOCAL BOOL sym895XferParamsCvt
  1867.     (
  1868.     FAST SIOP  * pSiop,         /* pointer to controller info        */
  1869.     FAST UINT8 * pOffset,       /* REQ/ACK offset                    */
  1870.     FAST UINT8 * pPeriod,       /* xfer period, SCSI units (x 4 ns)  */
  1871.     FAST UINT8 * pXferParams, /* corresponding Sync Xfer Reg value */
  1872.     FAST UINT8 * pClockDiv      /* corresponding clock division bits */
  1873.     )
  1874.     {
  1875.     UINT  offset  = (UINT) *pOffset;
  1876.     UINT  period  = (UINT) *pPeriod;
  1877.     UINT  xferp;
  1878.     UINT  sccpDiv;
  1879.     UINT8 clkDiv=1;
  1880.     UINT8 xferParams  = 0; /* initialised to avoid warnings */
  1881.     UINT8 clockDivide = 0; /* initialised to avoid warnings */
  1882.     UINT  sccp; /* Scsi Core Clock Period */
  1883.     if (offset == SCSI_SYNC_XFER_ASYNC_OFFSET)
  1884.         {
  1885.         xferParams  = SYM895_ASYNC_SXFER;
  1886.         clockDivide = pSiop->clkDiv; 
  1887.         offset = SCSI_SYNC_XFER_ASYNC_OFFSET;
  1888.         period = 0;
  1889.         }
  1890.     else
  1891. {
  1892. SYM895_SCSI_DEBUG_MSG ("sym895XferParamsCvt: requested: "
  1893.                                "offset = %d, period = %dn",
  1894.                                 offset, period, 0, 0, 0, 0);
  1895.         /* Default sccpDiv and clkDiv values for SCLK <= 50MHz */
  1896. sccpDiv = 100;
  1897. clkDiv = 1;
  1898.         /* 
  1899.          * For SCLK > 66.7MHz. To acheive ultra 2 rates, Clock Quadrupler must
  1900.          * be turned on (SCLK=160MHz)& clock divider must be set to /1. Also,
  1901.          * the scsi options for a particular target must be set to have minimum
  1902.          * transfer period of 25ns. This can be done using "scsiTargetOptionsSet".
  1903.          */
  1904.         if (pSiop->clkPeriod < SYM895_6666MHZ)
  1905.             {
  1906.     sccpDiv = 100;
  1907.             clkDiv = 1; 
  1908.             }   
  1909.        /* Unless the SCLK is > 50MHz but < 66.7MHz */
  1910.         else if (pSiop->clkPeriod < SYM895_50MHZ) /* then faster than 50MHZ */
  1911.             {
  1912.     sccpDiv = 67;
  1913.             clkDiv = 2;
  1914.             }
  1915.         /* convert all variables to ns */
  1916.         period *= 4; /* ns */
  1917.         sccp = pSiop->clkPeriod / sccpDiv; /* ns */
  1918.         xferp = period / sccp;
  1919. /* adjust xferp to fit the allowable range */
  1920. if (xferp < SYM895_MIN_XFERP)
  1921.     xferp = SYM895_MIN_XFERP;
  1922.         else if (xferp > SYM895_MAX_XFERP) 
  1923.     xferp = SYM895_IDEAL_XFERP;
  1924.         /* update the period using the adjusted xferp */
  1925.         period = xferp * sccp;
  1926.         /* adjust the synchronous offset to fit the allowable range */
  1927. if (offset < SYM895_MIN_SYNC_OFFSET)
  1928.     offset = SYM895_MIN_SYNC_OFFSET;
  1929.         else if (offset > SYM895_MAX_SYNC_OFFSET)
  1930.     offset = SYM895_MAX_SYNC_OFFSET;
  1931.         xferParams = (((UINT8) xferp - SYM895_MIN_XFERP) & 0x07) << 
  1932.                       SYM895_SYNC_XFER_PERIOD_SHIFT; 
  1933.         xferParams |= ((UINT8) offset & 0x1f);
  1934.         /* 
  1935.  * The clock dividers for scntl3 remain fixed because this is a static
  1936.     * value that does not change on a per transfer basis. The divider
  1937.    * is based on the SCLK frequency from the board to the SCSI core 
  1938.    */
  1939. clockDivide = (pSiop->clkDiv);
  1940.      clockDivide = clockDivide | (clkDiv << 4); 
  1941.         /* convert the period back to 4ns units */
  1942.         period /= 4;
  1943.         } /* else */
  1944.     SYM895_SCSI_DEBUG_MSG ("sym895XferParamsCvt: converted to: "
  1945.                            "offset     = %d, period      = %dn"
  1946.                            "xferParams = %x, clockDivide = %xn",
  1947.                            offset, period, xferParams, clockDivide, 0, 0);
  1948.     *pOffset     = offset;
  1949.     *pPeriod     = period;
  1950.     *pXferParams = xferParams;
  1951.     *pClockDiv   = clockDivide;
  1952.     return (TRUE);
  1953.     }
  1954. /******************************************************************************
  1955. *
  1956. * sym895EventTypeGet - parse status registers at interrupt time
  1957. *
  1958. * This routine examines the device state to determine what type of event
  1959. * is pending.  If none is pending then a fatal error code is returned.
  1960. *
  1961. * RETURNS Returns an interrupt (event) type code or SYM895_FATAL_ERROR.
  1962. */
  1963. LOCAL int sym895EventTypeGet
  1964.     (
  1965.     SIOP * pSiop
  1966.     )
  1967.     {
  1968.     int key;
  1969.     UINT8 intrStatus   = 0;
  1970.     UINT8 dmaStatus    = 0;
  1971.     UINT8 scsiStatus_0 = 0;
  1972.     UINT8 scsiStatus_1 = 0;
  1973.     /*
  1974.      * We should be locked in interrupt context while the status
  1975.      * registers are being read so that there is no contention between
  1976.      * a synchronous thread and a bus initiated thread (reselect)
  1977.      */
  1978.     key = intLock (); 
  1979.     CACHE_PIPE_FLUSH();
  1980.     /*
  1981.      * Read the interrupt status register.
  1982.      * For reading the DSTAT, SIST0 and SIST1 registers,
  1983.      * each register should be read with a delay of 12 SCLK delays between
  1984.      * successive reads. Please refer to data manual for additional details
  1985.      */
  1986.     intrStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT);
  1987.     SYM895_SCSI_DEBUG_MSG (" istat is 0x%x..n", intrStatus,0,0,0,0,0);
  1988.     /* Check for the INTF bit and clear it if set */
  1989.     if (intrStatus & SYM895_ISTAT_INTF)
  1990.   SYM895_REG8_WRITE (pSiop,SYM895_OFF_ISTAT, SYM895_ISTAT_INTF);
  1991.     /* check if there is an interrupt */
  1992.     if ((intrStatus & (SYM895_ISTAT_SIP | SYM895_ISTAT_DIP)) != 0)  
  1993. {