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

VxWorks

开发平台:

C/C++

  1. /* wd33c93Lib2.c - WD33C93 SCSI-Bus Interface Controller library (SCSI-2) */
  2. /* Copyright 1984-1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02h,03mar99,dat  added init of wideXfer to FALSE. SPR 24089
  8. 02h,11jan99,aeg  added semTerminate () in wd33c93CtrlCreateScsi2 ().
  9. 02g,29oct96,dgp  doc: editing for newly published SCSI libraries
  10. 02f,06may96,jds  and more doc tweaks...
  11. 02e,01may96,jds  yet more doc tweaks...
  12. 02d,13nov95,jds  more doc tweaks
  13. 02c,20sep95,jdi  doc tweaks.
  14. 02b,20jul95,jds  changed wd33c93Intr to sbicIntr to keep it consistent with
  15.  previous incarnations of this driver. Integrated into 
  16.  vxWorks5.2
  17. 03a,16mar95,ihw  major modifications to work with generic SCSI thread manager
  18. 02g,14jan94,ihw  ANSI-fied and generally smartened up to v5.1 standard
  19. 02f,19jul92,ihw  improved support for disconnect/reconnect
  20. 02e,17jul92,ihw  added sync. points in sbicBytes{In,Out}()
  21. 02d,01jul92,ihw  modifications to support synchronous transfer
  22. 02c,04oct91,ihw  fixed problem with reselection (interrupt lock-out)
  23. 02b,19jun91,ihw  extensive modifications for disconnect/reconnect support
  24. 02a,06jun91,ihw  modifications for multiple-initiator support
  25. 01e,02oct90,jcc  UTINY became UINT8; changes in sem{Give, Take}() calls 
  26.  since SEM_ID's became SEMAPHORE's in various structures;
  27.  malloc() became calloc() in wd33c93CtrlCreate(); miscellaneous.
  28. 01d,21sep90,jcc  misc. cleanup for 5.0 release.
  29. 01c,10aug90,dnw  added forward declarations for VOID functions.
  30. 01b,18jul90,jcc  made semTake() calls 5.0 compatible; clean-up.
  31. 01a,28feb90,jcc  written
  32. */
  33. /*
  34. DESCRIPTION
  35. This library contains part of the I/O driver for the Western Digital WD33C93 
  36. family of SCSI-2 Bus Interface Controllers (SBIC).  It is designed to work 
  37. with scsi2Lib. The driver routines in this library depend on the
  38. SCSI-2 ANSI specification; for general driver routines and for overall SBIC
  39. documentation, see wd33c93Lib.
  40. USER-CALLABLE ROUTINES
  41. Most of the routines in this driver are accessible only through the I/O
  42. system.  The only exception in this portion of the driver is
  43. wd33c93CtrlCreateScsi2(), which creates a controller structure.
  44. INCLUDE FILES
  45. wd33c93.h, wd33c93_2.h
  46. SEE ALSO: scsiLib, scsi2Lib, wd33c93Lib, 
  47. .pG "I/O System"
  48. */
  49. #include "vxWorks.h"
  50. #define WD33C93_2_LOCAL_FUNCS
  51. #include "drv/scsi/wd33c93_2.h"
  52. #undef WD33C93_2_LOCAL_FUNCS
  53. #include "errnoLib.h"
  54. #include "intLib.h"
  55. #include "logLib.h"
  56. #include "msgQLib.h"
  57. #include "semLib.h"
  58. #include "stdio.h"
  59. #include "stdlib.h"
  60. #include "tickLib.h"
  61. #define WD_33C93_MAX_BYTES_PER_XFER  ((UINT) 0xffffff)
  62. typedef WD_33C93_SCSI_CTRL SBIC;
  63. /* globals */
  64. int wd33c93XferDoneSemOptions  = SEM_Q_PRIORITY;
  65. char *wd33c93ScsiTaskName      = SCSI_DEF_TASK_NAME;
  66. int   wd33c93ScsiTaskOptions   = SCSI_DEF_TASK_OPTIONS;
  67. int   wd33c93ScsiTaskPriority  = SCSI_DEF_TASK_PRIORITY;
  68. int   wd33c93ScsiTaskStackSize = SCSI_DEF_TASK_STACK_SIZE;
  69. IMPORT SCSI_CTRL *pSysScsiCtrl;
  70. /* forward declarations */
  71. LOCAL STATUS sbicDevSelect (SCSI_CTRL *pScsiCtrl, int devBusId,
  72.     UINT selTimeOut, UINT8 *msgBuf, UINT msgLen);
  73. LOCAL STATUS sbicBusControl (SCSI_CTRL *pScsiCtrl, int operation);
  74. LOCAL STATUS sbicXferParamsQuery (SCSI_CTRL *pScsiCtrl, UINT8 *pOffset,
  75.                                             UINT8 *pPeriod);
  76. LOCAL STATUS sbicXferParamsSet (SCSI_CTRL *pScsiCtrl, UINT8 offset,
  77.                       UINT8 period);
  78. LOCAL int sbicInfoXfer (SCSI_CTRL *pScsiCtrl, int phase, UINT8 *pBuf, UINT bufLength);
  79. LOCAL void sbicSelTimeOutCvt (SBIC *pSbic, UINT timeOutInUsec,
  80.                      UINT *pTimeOutSetting);
  81. LOCAL BOOL   sbicXferParamsCvt (SBIC  *pSbic, UINT8 *pOffset, UINT8 *pPeriod,
  82. UINT8 *pXferParams);
  83. LOCAL STATUS sbicXferCountSet (SBIC *pSbic, UINT count);
  84. LOCAL void sbicXferCountGet (SBIC *pSbic, UINT *pCount);
  85. LOCAL void sbicCommand (SBIC *pSbic, UINT8 cmdCode);
  86. LOCAL void sbicHwInit (SBIC *pSbic);
  87. LOCAL void sbicPostResetInit (SBIC *pSbic);
  88. LOCAL void sbicRegRead (SBIC *pSbic, UINT8 regAdrs, int  *pDatum);
  89. LOCAL void sbicRegWrite (SBIC *pSbic, UINT8 regAdrs, UINT8 datum);
  90. LOCAL void sbicIntr (SBIC *);
  91. WD_33C93_SCSI_CTRL *wd33c93CtrlCreateScsi2 ( FAST UINT8 *sbicBaseAdrs, 
  92.        int regOffset, UINT clkPeriod, FUNCPTR sysScsiBusReset,
  93.        int sysScsiResetArg, UINT sysScsiDmaMaxBytes,
  94.        FUNCPTR sysScsiDmaStart, FUNCPTR sysScsiDmaAbort,
  95.        int sysScsiDmaArg);
  96. LOCAL STATUS wd33c93CtrlInit (FAST SBIC *pSbic, FAST int scsiCtrlBusId,
  97.               FAST UINT defaultSelTimeOut);
  98. LOCAL STATUS wd33c93Show ( FAST SCSI_CTRL *pScsiCtrl);
  99. /*******************************************************************************
  100. *
  101. * wd33c93Scsi2IfInit - initialize the SCSI-2 interface to wd33c93
  102. *
  103. * NOMANUAL
  104. */
  105. void wd33c93Scsi2IfInit ()
  106.     {
  107.     /* create table */
  108.     wd33c93IfTblInit ();
  109.     /* initialize table */
  110.     pWd33c93IfTbl->sbicCommand       = (FUNCPTR) sbicCommand;
  111.     pWd33c93IfTbl->sbicIntr          = (FUNCPTR) sbicIntr;
  112.     pWd33c93IfTbl->sbicRegRead       = (FUNCPTR) sbicRegRead;
  113.     pWd33c93IfTbl->sbicRegWrite      = (FUNCPTR) sbicRegWrite;
  114.     pWd33c93IfTbl->sbicXferCountGet  = (FUNCPTR) sbicXferCountGet;
  115.     pWd33c93IfTbl->sbicXferCountSet  = (FUNCPTR) sbicXferCountSet;
  116.     pWd33c93IfTbl->wd33c93CtrlInit   = (FUNCPTR) wd33c93CtrlInit;
  117.     pWd33c93IfTbl->wd33c93Show       = (FUNCPTR) wd33c93Show;
  118.     }
  119. /*******************************************************************************
  120. *
  121. * wd33c93CtrlCreateScsi2 - create and partially initialize an SBIC structure
  122. *
  123. * This routine creates an SBIC data structure and must be called before using
  124. * an SBIC chip.  It must be called exactly once for a specified SBIC.
  125. * Since it allocates memory for a structure needed by all routines in
  126. * wd33c93Lib2, it must be called before any other routines in the library.
  127. * After calling this routine, at least one call to wd33c93CtrlInit() must
  128. * be made before any SCSI transaction is initiated using the SBIC.
  129. *
  130. * NOTE: Only the non-multiplexed processor interface is supported.
  131. *
  132. * A detailed description of the input parameters follows:
  133. * .iP `sbicBaseAdrs'
  134. * the address at which the CPU would access the lowest 
  135. * (AUX STATUS) register of the SBIC.
  136. * .iP `regOffset'
  137. * the address offset (bytes) to access consecutive registers.
  138. * (This must be a power of 2, for example, 1, 2, 4, etc.)
  139. * .iP `clkPeriod'
  140. * the period in nanoseconds of the signal to SBIC CLK input.
  141. * .iP "`sysScsiBusReset' and `sysScsiResetArg'"
  142. * the board-specific routine to pulse the SCSI bus RST signal.
  143. * The specified argument is passed to this routine when it is called.
  144. * It may be used to identify the SCSI bus to be reset, if there is a
  145. * choice.  The interface to this routine is of the form:
  146. * .CS
  147. *     void xxBusReset 
  148. *         (
  149. *         int arg;              /@ call-back argument @/ 
  150. *         )
  151. * .CE
  152. * .iP "`sysScsiDmaMaxBytes', `sysScsiDmaStart', `sysScsiDmaAbort', and `sysScsiDmaArg'"
  153. * board-specific routines to handle DMA transfers to and from the SBIC;
  154. * if the maximum DMA byte count is zero, programmed I/O is used.
  155. * Otherwise, non-NULL function pointers to DMA start and abort routines
  156. * must be provided.
  157. * The specified argument is passed to these routines when they are
  158. * called; it may be used to identify the DMA channel to use, for example.
  159. * Note that DMA is implemented only during SCSI data in/out phases.
  160. * The interface to these DMA routines must be of the form:
  161. * .CS
  162. *     STATUS xxDmaStart 
  163. *         (
  164. *         int arg;              /@ call-back argument           @/
  165. *         UINT8 *pBuffer;             /@ ptr to the data buffer       @/
  166. *         UINT bufLength;             /@ number of bytes to xfer      @/
  167. *      int direction;           /@ 0 = SCSI->mem, 1 = mem->SCSI @/
  168. *         )
  169. *
  170. *     STATUS xxDmaAbort
  171. *         (
  172. *         int arg;              /@ call-back argument @/
  173. *         )
  174. * .CE
  175. *
  176. * RETURNS: A pointer to the SBIC structure, or NULL if memory is 
  177. * insufficient or the parameters are invalid.
  178. */
  179. WD_33C93_SCSI_CTRL *wd33c93CtrlCreateScsi2
  180.     (
  181.     FAST UINT8 *sbicBaseAdrs,      /* base address of the SBIC              */
  182.     int         regOffset,      /* address offset between SBIC registers */
  183.     UINT        clkPeriod,      /* period of the SBIC clock (nsec)       */
  184.     FUNCPTR     sysScsiBusReset,     /* function to reset SCSI bus            */
  185.     int         sysScsiResetArg,     /* argument to pass to above function    */
  186.     UINT        sysScsiDmaMaxBytes,  /* maximum byte count using DMA          */
  187.     FUNCPTR     sysScsiDmaStart,     /* function to start SCSI DMA transfer   */
  188.     FUNCPTR     sysScsiDmaAbort,     /* function to abort SCSI DMA transfer   */
  189.     int         sysScsiDmaArg      /* argument to pass to above functions   */
  190.     )
  191.     {
  192.     FAST SBIC *pSbic; /* ptr to SBIC info */
  193.     /* verify input parameters */
  194.     if ((regOffset == 0) || (clkPeriod == 0))
  195. return ((SBIC *) NULL);
  196.     
  197.     if ((sysScsiDmaMaxBytes != 0) &&
  198. ((sysScsiDmaStart == NULL) || (sysScsiDmaAbort == NULL)))
  199. return ((SBIC *) NULL);
  200.     
  201.     /* calloc the controller info structure; return NULL if unable */
  202.     if ((pSbic = (SBIC *) calloc (1, sizeof (SBIC))) == NULL)
  203.         return ((SBIC *) NULL);
  204.     /*
  205.      *  Set up sizes of event and thread structures.  Must be done before
  206.      * calling "scsiCtrlInit()".
  207.      *
  208.      * Since this controller uses standard event and thread structures,
  209.      * it could simply leave these values set to 0 (i.e., use default).
  210.      */
  211.     pSbic->scsiCtrl.eventSize  = sizeof (SCSI_EVENT);
  212.     pSbic->scsiCtrl.threadSize = sizeof (SCSI_THREAD);
  213.     
  214.     /* leave transact, event and thread management routines as default */
  215.     /* fill in driver-specific routines for scsiLib interface */
  216.     pSbic->scsiCtrl.scsiDevSelect       = sbicDevSelect;
  217.     pSbic->scsiCtrl.scsiInfoXfer        = sbicInfoXfer;
  218.     pSbic->scsiCtrl.scsiBusControl      = sbicBusControl;
  219.     pSbic->scsiCtrl.scsiXferParamsQuery = sbicXferParamsQuery;
  220.     pSbic->scsiCtrl.scsiXferParamsSet   = (FUNCPTR)sbicXferParamsSet;
  221.     pSbic->scsiCtrl.wideXfer = FALSE;
  222.     pSbic->scsiCtrl.scsiWideXferParamsQuery = NULL;
  223.     pSbic->scsiCtrl.scsiWideXferParamsSet   = NULL;
  224.     /* fill in driver-specific variables for scsiLib interface */
  225.     if ((sysScsiDmaMaxBytes != 0) &&
  226. (sysScsiDmaMaxBytes <= WD_33C93_MAX_BYTES_PER_XFER))
  227. pSbic->scsiCtrl.maxBytesPerXfer = sysScsiDmaMaxBytes;
  228.     else
  229. pSbic->scsiCtrl.maxBytesPerXfer = WD_33C93_MAX_BYTES_PER_XFER;
  230.     /* fill in generic SCSI info for this controller */
  231.     scsiCtrlInit (&pSbic->scsiCtrl);
  232.     /* initialize SBIC info transfer synchronisation semaphore */
  233.     if (semBInit (&pSbic->xferDoneSem, wd33c93XferDoneSemOptions, SEM_EMPTY)
  234.          == ERROR)
  235. {
  236. SCSI_MSG ("wd33c93CtrlCreate: semBInit of xferDoneSem failedn",
  237.   0, 0, 0, 0, 0, 0);
  238. (void) free ((char *) pSbic);
  239. return ((WD_33C93_SCSI_CTRL *) NULL);
  240. }
  241.   
  242.     /* initialise state variables */
  243.     pSbic->state       = SBIC_STATE_IDLE;
  244.     pSbic->initPending = FALSE;
  245.     pSbic->xferPending = FALSE;
  246.     
  247.     /* fill in SBIC specific data for this controller */
  248.     pSbic->clkPeriod   = clkPeriod;
  249.     pSbic->pAdrsReg    = sbicBaseAdrs;
  250.     pSbic->pAuxStatReg = sbicBaseAdrs;
  251.     pSbic->pRegFile    = sbicBaseAdrs + regOffset;
  252.     /* fill in board-specific SCSI bus reset and DMA xfer routines */
  253.     pSbic->sysScsiDmaStart = sysScsiDmaStart;
  254.     pSbic->sysScsiDmaAbort = sysScsiDmaAbort;
  255.     pSbic->sysScsiDmaArg   = sysScsiDmaArg;
  256.     pSbic->sysScsiBusReset = sysScsiBusReset;
  257.     pSbic->sysScsiResetArg = sysScsiResetArg;
  258.     
  259.     /* spawn SCSI manager - use generic code from "scsiLib.c" */
  260.     pSbic->scsiCtrl.scsiMgrId = taskSpawn (wd33c93ScsiTaskName,
  261.                         wd33c93ScsiTaskPriority,
  262.                         wd33c93ScsiTaskOptions,
  263.                         wd33c93ScsiTaskStackSize,
  264.                         (FUNCPTR) scsiMgr,
  265.                         (int) pSbic,
  266.    0, 0, 0, 0, 0, 0, 0, 0, 0);
  267.     if (pSbic->scsiCtrl.scsiMgrId == ERROR)
  268. {
  269. SCSI_MSG ("wd33c93CtrlCreate: can't spawn SCSI manager taskn",
  270.   0, 0, 0, 0, 0, 0);
  271. semTerminate (&pSbic->xferDoneSem);
  272. free ((char *) pSbic);
  273. return ((SBIC *) NULL);
  274. }
  275.     return (pSbic);
  276.     }
  277. /*******************************************************************************
  278. *
  279. * wd33c93CtrlInit - initialize user specifiable fields in an SBIC structure
  280. *
  281. * After an SBIC structure is created with wd33c93CtrlCreate(2), but
  282. * before using the SBIC, it must be initialized by calling this routine.
  283. * It may be called more than once if desired.  However, it should only be
  284. * called while there is no activity on the SCSI interface.
  285. *
  286. * A detailed description of the input parameters follows:
  287. * .iP `pSbic'
  288. * pointer to the WD_33C93_SCSI_CTRL structure created with wd33c93CtrlCreate(2).
  289. * .iP `scsiCtrlBusId'
  290. * the SCSI bus ID of the SBIC; somewhat arbitrary, seven (7),
  291. * or highest priority, is conventional.  Must be in range 0 - 7.
  292. * .iP `defaultSelTimeOut'
  293. * the timeout (in microsec) for selecting a SCSI device
  294. * attached to this controller; called default since the
  295. * timeout may be specified per device.
  296. * The recommended value zero (0)
  297. * specifies SCSI_DEF_SELECT_TIMEOUT (250 millisec).
  298. * Values over the maximum timeout period specify the maximum,
  299. * which is approximately 2 seconds (depending on SBIC clock
  300. * period).  See also Western Digital documentation.
  301. *
  302. * RETURNS: OK, or ERROR if out-of-range parameter(s).
  303. */
  304. LOCAL STATUS wd33c93CtrlInit
  305.     (
  306.     FAST SBIC *pSbic, /* ptr to SBIC info */
  307.     FAST int  scsiCtrlBusId, /* SCSI bus ID of this SBIC */
  308.     FAST UINT defaultSelTimeOut /* default dev. select timeout (microsec) */
  309.     )
  310.     {
  311.     /* verify scsiCtrlBusId and enter legal value in SBIC structure */
  312.     if (scsiCtrlBusId < SCSI_MIN_BUS_ID || scsiCtrlBusId > SCSI_MAX_BUS_ID)
  313. return (ERROR);
  314.     else
  315. pSbic->scsiCtrl.scsiCtrlBusId = scsiCtrlBusId;
  316.     if (defaultSelTimeOut == 0)
  317. pSbic->defSelTimeOut = SCSI_DEF_SELECT_TIMEOUT;
  318.     else
  319. pSbic->defSelTimeOut = defaultSelTimeOut;
  320.     sbicHwInit (pSbic);  /* initialize the SBIC hardware */
  321.     return (OK);
  322.     }
  323. /*******************************************************************************
  324. *
  325. * sbicDevSelect - attempt to select a SCSI device
  326. *
  327. * Initiate selection of the specified SCSI target, asserting ATN if there is
  328. * an identification message to be sent.  Return immediately; do not wait for
  329. * the selection to complete.  (This will be notified by an asynchronous
  330. * message posted in the controller's event queue).
  331. *
  332. * There is a race condition inherent in SCSI between the synchronous
  333. * activation of a thread (i.e., execution of this routine) and asynchronous
  334. * activation of a thread as a result of selection or reselection.  The SCSI
  335. * manager is designed to take account of this, and assumes that either the
  336. * new thread has been successfully activated or a (re)selection has taken
  337. * place, as determined by the next event it receives.  In the case when
  338. * (re)selection occurs, the current activation request is deferred and
  339. * retried later.
  340. *
  341. * Therefore, a SELECT command is issued only if the controller is currently
  342. * IDLE (waiting for (re)selection or a host command).  If the controller is
  343. * CONNECTED, (re)selection is assumed to have already occurred.  Note that
  344. * this is not an error condition; there is no way for the caller to reliably
  345. * distinguish the two cases, because even if the thread appears to have been
  346. * activated it may yet be "pre-empted" by (re)selection.
  347. *
  348. * The controller should never be in SELECT_PENDING state.  If it is, the
  349. * SCSI manager has tried to activate multiple concurrent threads on the
  350. * controller, which indicates a major (software) disaster.
  351. *
  352. * NOTE: Interrupt locking is required to ensure that the correct action
  353. * is taken once the controller state has been checked.
  354. *
  355. * RETURNS: OK, or ERROR if the controller is in an invalid state (this
  356. * indicates a major software failure).
  357. */
  358. LOCAL STATUS sbicDevSelect
  359.     (
  360.     SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info     */
  361.     int        devBusId, /* SCSI bus ID of device to select */
  362.     UINT       selTimeOut, /* select t-o period (usec)        */
  363.     UINT8     *msgBuf, /* ptr to identification message   */
  364.     UINT       msgLen      /* maximum number of message bytes */
  365.     )
  366.     {
  367.     FAST SBIC *pSbic; /* ptr to SBIC info             */
  368.     int        lockKey; /* saved interrupt lock key     */
  369.     UINT8      selectCmd;    /* actual SELECT command to use */
  370.     STATUS     status;
  371.     pSbic = (SBIC *) pScsiCtrl;
  372.     /* reject attempts to select self */
  373.     
  374.     if (devBusId == pScsiCtrl->scsiCtrlBusId)
  375. {
  376. errnoSet (S_scsiLib_ILLEGAL_BUS_ID);
  377.         return (ERROR);
  378. }
  379.     /* convert timeout period to SBIC units, in place */
  380.     
  381.     sbicSelTimeOutCvt (pSbic, selTimeOut, &selTimeOut);
  382.     selectCmd = (msgLen != 0) ? SBIC_CMD_SEL_ATN : SBIC_CMD_SELECT;
  383.     
  384.     /*
  385.      * Check SBIC is IDLE, then issue SELECT command.  Must be done with
  386.      * interrupts locked to avoid races with the reselection ISR.
  387.      *
  388.      * If the controller is not IDLE, do not issue a select command.  Just
  389.      * return - there must be a (re)selection event pending which will be
  390.      * handled exactly as if it occurred just after the select command was
  391.      * issued.
  392.      */
  393.     lockKey = intLock ();
  394.     switch (pSbic->state)
  395. {
  396. case SBIC_STATE_IDLE:
  397.     pSbic->state = SBIC_STATE_SELECT_PENDING;
  398.     sbicRegWrite (pSbic, SBIC_REG_DEST_ID,   (UINT8) devBusId);
  399.     sbicRegWrite (pSbic, SBIC_REG_TO_PERIOD, (UINT8) selTimeOut);
  400.     sbicCommand  (pSbic, selectCmd);
  401.     status = OK;
  402.     break;
  403. case SBIC_STATE_CONNECTED:
  404.     status = OK;
  405.     break;
  406. case SBIC_STATE_SELECT_PENDING:
  407. default:
  408.     status = ERROR;
  409.     break;
  410. }
  411.     intUnlock (lockKey);
  412.     if (status != OK)
  413. {
  414. SCSI_DEBUG_MSG ("sbicDevSelect: invalid controller state (%d)n",
  415.      pSbic->state, 0, 0, 0, 0, 0);
  416. }
  417.     return (status);
  418.     }
  419. /*******************************************************************************
  420. *
  421. * sbicBusControl - miscellaneous low-level SCSI bus control operations
  422. *
  423. * Allows the caller to:-
  424. *
  425. *   - assert the SCSI ATN signal (indicating a message out is available)
  426. *   - negate the SCSI ACK signal (indicating a message in has been read)
  427. *
  428. * The "operation" parameter is a bitmask which allows any combination of these
  429. * functions to be carried out with a single call.  Note that the order in
  430. * which things are done is important: ATN is asserted (if specified) before
  431. * ACK is negated.  (This allows an incoming SCSI message to be rejected.)
  432. *
  433. * NOTE: since the SBIC is not connected to the SCSI bus RST signal, a board-
  434. * specific function is used to implement the BUS_RESET command.  As a result
  435. * of calling this function, something must notify the SCSI manager task that
  436. * a bus reset has occurred ...
  437. *
  438. * RETURNS: OK (no error conditions)
  439. */
  440. LOCAL STATUS sbicBusControl
  441.     (
  442.     SCSI_CTRL *pScsiCtrl, /* ptr to SBIC info                         */
  443.     int        operation /* bitmask for operation(s) to be performed */
  444.     )
  445.     {
  446.     FAST SBIC *pSbic = (SBIC *) pScsiCtrl;
  447.     if (operation & SCSI_BUS_RESET)
  448. (*pSbic->sysScsiBusReset) (pSbic->sysScsiResetArg);
  449.     if (operation & SCSI_BUS_ASSERT_ATN)
  450. sbicCommand (pSbic, SBIC_CMD_SET_ATN);
  451.     if (operation & SCSI_BUS_NEGATE_ACK)
  452.      sbicCommand (pSbic, SBIC_CMD_NEG_ACK);
  453.     return (OK);
  454.     }
  455. /*******************************************************************************
  456. *
  457. * sbicXferParamsQuery - get (synchronous) transfer parameters
  458. *
  459. * Updates the synchronous transfer parameters suggested in the call to match
  460. * the SBIC's capabilities.  Transfer period is in SCSI units (multiples of
  461. * 4 ns).
  462. *
  463. * Note: the transfer period is made longer and the offset is made smaller if
  464. * the SBIC cannot handle the specified values.
  465. *
  466. * RETURNS: OK
  467. */
  468. LOCAL STATUS sbicXferParamsQuery
  469.     (
  470.     SCSI_CTRL *pScsiCtrl, /* ptr to SBIC info             */
  471.     UINT8     *pOffset, /* max REQ/ACK offset  [in/out] */
  472.     UINT8     *pPeriod /* min transfer period [in/out] */
  473.     )
  474.     {
  475.     UINT8 unused;
  476.     (void) sbicXferParamsCvt ((SBIC *) pScsiCtrl, pOffset, pPeriod, &unused);
  477.     
  478.     return (OK);
  479.     }
  480.     
  481. /*******************************************************************************
  482. *
  483. * sbicXferParamsSet - set transfer parameters
  484. *
  485. * Programs the SBIC to use the specified transfer parameters.  An offset
  486. * of zero specifies asynchronous transfer (period is then irrelevant).
  487. * Transfer period is in SCSI units (multiples of 4 ns).
  488. *
  489. * RETURNS: OK if transfer parameters are OK, else ERROR.
  490. */
  491. LOCAL STATUS sbicXferParamsSet
  492.     (
  493.     SCSI_CTRL *pScsiCtrl, /* ptr to SBIC info       */
  494.     UINT8      offset, /* max REQ/ACK offset     */
  495.     UINT8      period /* min transfer period    */
  496.     )
  497.     {
  498.     FAST SBIC *pSbic = (SBIC *) pScsiCtrl;
  499.     UINT8      xferParams;
  500.     
  501.     if (!sbicXferParamsCvt (pSbic, &offset, &period, &xferParams))
  502. { /* should never happen */
  503. errnoSet (S_scsiLib_ILLEGAL_PARAMETER);
  504. return (ERROR);
  505. }
  506.     sbicRegWrite (pSbic, SBIC_REG_SYNC_XFER, xferParams);
  507.     return (OK);
  508.     }
  509. /*******************************************************************************
  510. *
  511. * sbicInfoXfer - transfer information bytes to/from target via SCSI bus
  512. *
  513. * Executes a "Transfer Info" command to read (write) bytes from (to) the
  514. * SCSI bus.  If the transfer phase is DATA IN or DATA OUT and there is a
  515. * DMA routine available, DMA is used - otherwise it's a tight programmed
  516. * i/o loop.
  517. *
  518. * Returns when the transfer has completed; i.e., the last byte has been
  519. * received (sent) and ACK is still asserted in the case of MESSAGE IN
  520. * transfers, or a request for a new information transfer has occurred (for
  521. * all other types of transfer).
  522. *
  523. * The returned value is the number of bytes actually transferred across the
  524. * SCSI bus.  In the case of DATA phases, this may be less than the requested
  525. * transfer length because the target may change the information phase "early"
  526. * (to send a message in, for example).  For non-DATA transfers, if the byte
  527. * count transferred is not what was asked for, it is probably an error
  528. * condition (left to the caller's discretion).
  529. *
  530. * RETURNS: Number of bytes transferred across SCSI bus, or ERROR.
  531. */
  532. LOCAL int sbicInfoXfer
  533.     (
  534.     FAST SCSI_CTRL *pScsiCtrl,       /* ptr to SCSI controller info       */
  535.     int             phase,        /* SCSI phase being transferred      */
  536.     FAST UINT8     *pBuf, /* ptr to byte buffer for i/o        */
  537.     UINT            bufLength /* number of bytes to be transferred */
  538.     )
  539.     {
  540.     FAST SBIC  *pSbic; /* ptr to SBIC info                  */
  541.     FAST UINT8  auxStatus; /* SBIC auxiliary status             */
  542.     UINT        bytesLeft; /* bytes not transferred across bus  */
  543.     int         direction; /* input (READ) or output (WRITE)    */
  544.     BOOL        usingDMA; /* using DMA for this transfer ?     */
  545.     pSbic = (SBIC *) pScsiCtrl;
  546.     SCSI_DEBUG_MSG ("sbicInfoXfer: phase = %d, buf = 0x%x, length = %dn",
  547.     phase, (int) pBuf, bufLength, 0, 0, 0);
  548.     /*
  549.      * Set transfer count, issue Transfer Info command
  550.      */
  551.     if (sbicXferCountSet (pSbic, (UINT) bufLength) != OK)
  552. {
  553.      errnoSet (S_scsiLib_ILLEGAL_PARAMETER);
  554. return (ERROR);
  555. }
  556.     sbicCommand (pSbic, SBIC_CMD_XFER_INFO);
  557.     /*
  558.      * Identify phase, set transfer mode accordingly
  559.      */
  560.     switch (phase)
  561. {
  562.      case SCSI_DATA_OUT_PHASE:
  563.     direction = WRITE;
  564.     usingDMA  = (pSbic->sysScsiDmaStart != NULL);
  565.     break;
  566.     
  567.      case SCSI_DATA_IN_PHASE:
  568.     direction = READ;
  569.     usingDMA  = (pSbic->sysScsiDmaStart != NULL);
  570.     break;
  571. case SCSI_COMMAND_PHASE:
  572.      case SCSI_MSG_OUT_PHASE:
  573.     direction = WRITE;
  574.     usingDMA  = FALSE;
  575.     break;
  576.     
  577. case SCSI_STATUS_PHASE:
  578.      case SCSI_MSG_IN_PHASE:
  579.     direction = READ;
  580.     usingDMA  = FALSE;
  581.     break;
  582.         default:
  583.     SCSI_MSG ("sbicInfoXfer: invalid bus phase (%d)n",
  584.       phase, 0, 0, 0, 0, 0);
  585.     return (ERROR);
  586. }
  587.     
  588.     /*
  589.      * Start DMA, if used, or programmed i/o loop to transfer data
  590.      */
  591.     pSbic->xferPending = TRUE;
  592.     
  593.     if (usingDMA)
  594. {
  595.         if ((*pSbic->sysScsiDmaStart) (pSbic->sysScsiDmaArg,
  596.        pBuf,
  597.        bufLength,
  598.        direction) != OK)
  599.     {
  600.     SCSI_MSG ("sbicInfoXfer: unable to start DMA transfern",
  601.       0, 0, 0, 0, 0, 0);
  602.     return (ERROR);
  603.     }
  604. }
  605.     else if (direction == READ)
  606. {
  607.      *pSbic->pAdrsReg = SBIC_REG_DATA;
  608.      while ((auxStatus = *pSbic->pAuxStatReg) & SBIC_AUX_STAT_BUSY)
  609.     {
  610.     if (auxStatus & SBIC_AUX_STAT_DBUF_READY)
  611.      *pBuf++ = *pSbic->pRegFile;
  612.     }
  613. }
  614.     else /* (direction == WRITE) */
  615. {
  616.      *pSbic->pAdrsReg = SBIC_REG_DATA;
  617.      while ((auxStatus = *pSbic->pAuxStatReg) & SBIC_AUX_STAT_BUSY)
  618.     {
  619.     if (auxStatus & SBIC_AUX_STAT_DBUF_READY)
  620.      *pSbic->pRegFile = *pBuf++;
  621.     }
  622. }
  623.     /*
  624.      * Wait for transfer to complete: find out how many bytes transferred,
  625.      *  abort DMA transfer if necessary.
  626.      */
  627.     semTake (&pSbic->xferDoneSem, WAIT_FOREVER);
  628.     
  629.     sbicXferCountGet (pSbic, &bytesLeft);
  630.     
  631.     if (bytesLeft > bufLength)
  632. {
  633. SCSI_MSG ("sbicInfoXfer: invalid count (len = 0x%0x, left = 0x%0x)n",
  634. bufLength, bytesLeft, 0, 0, 0, 0);
  635. return (ERROR);
  636. }
  637.     if (usingDMA && (bytesLeft > 0))
  638. (*pSbic->sysScsiDmaAbort) (pSbic->sysScsiDmaArg);
  639.     SCSI_DEBUG_MSG ("sbicInfoXfer: transferred %d of %d byte(s)n",
  640.     bufLength - bytesLeft, bufLength, 0, 0, 0, 0);
  641.     
  642.     return (bufLength - bytesLeft);
  643.     }
  644. /*******************************************************************************
  645. *
  646. * sbicSelTimeOutCvt - convert a select timeout from usec to SBIC units 
  647. *
  648. * The conversion formula is given on p. 11 of the Western Digital WD33C93
  649. * manual. Note that 0 specifies the default setting of 250 usec. Also,
  650. * the SBIC accepts up to a 8-bit timeout, so a maximum value of 0xff is
  651. * returned in *pTimeOutSetting.
  652. */
  653. LOCAL void sbicSelTimeOutCvt
  654.     (
  655.     SBIC      *pSbic,      /* ptr to SBIC info */
  656.     FAST UINT  timeOutInUsec, /* timeout in microsecs */
  657.     FAST UINT *pTimeOutSetting /* ptr to result */
  658.     )
  659.     {
  660.     FAST UINT tempSelTimeOut; /* temp. select timeout setting */
  661.     if (timeOutInUsec == (UINT) 0)
  662. timeOutInUsec = pSbic->defSelTimeOut;
  663.     tempSelTimeOut = (timeOutInUsec / (80 * pSbic->clkPeriod)) + 1; 
  664.     if (tempSelTimeOut > 0xff)
  665. tempSelTimeOut = 0xff;
  666.     *pTimeOutSetting = tempSelTimeOut;
  667.     }
  668. /*******************************************************************************
  669. * sbicXferParamsCvt - convert transfer period from SCSI to SBIC units
  670. *
  671. * Given a "suggested" REQ/ACK offset and transfer period (in SCSI units of
  672. * 4 ns), return the nearest offset and transfer period the SBIC is capable of
  673. * using.  Also return the corresponding value of the SBIC's Synchronous
  674. * Transfer register.
  675. *
  676. * An offset of zero specifies asynchronous transfer, in which case the period
  677. * is irrelevant.  Otherwise, the offset may be clipped to be within the
  678. * maximum limit the SBIC is capable of.
  679. *
  680. * The transfer period is normally rounded towards longer periods if the SBIC
  681. * is not capable of using the exact specified value.  The period may also be
  682. * clipped to be within the SBIC's maximum and minimum limits according to its
  683. * clock period.
  684. *
  685. * If either the offset or period need to be clipped, the value FALSE is
  686. * retuned as this may reflect an error condition.
  687. *
  688. * Currently assumes that the SBIC is a 33C93, not a 33C93A (i.e. fixed clock
  689. * divider of 2) - see 33C93A data sheet pp 9, 13 and 14 for further details.
  690. *
  691. * RETURNS: TRUE if input period is within SBIC's range, else FALSE
  692. */
  693. LOCAL BOOL sbicXferParamsCvt
  694.     (
  695.     FAST SBIC  *pSbic, /* ptr to SBIC info                  */
  696.     FAST UINT8 *pOffset, /* REQ/ACK offset                    */
  697.     FAST UINT8 *pPeriod, /* xfer period, SCSI units (x 4 ns)  */
  698.     FAST UINT8 *pXferParams /* corresponding Sync Xfer Reg value */
  699.     )
  700.     {
  701.     UINT8 offset  = *pOffset;
  702.     UINT8 period  = *pPeriod;
  703.     BOOL  inRange = TRUE;
  704.     UINT8 xferParams;
  705.     
  706.     if (offset == SCSI_SYNC_XFER_ASYNC_OFFSET)
  707. xferParams = SBIC_SYNC_XFER_PARAMS_ASYNC;
  708.     else
  709. {
  710. UINT clkCycles;
  711. /*
  712.  *  Round (and perhaps clip) transfer period to suit SBIC
  713.  *
  714.  *  Note: split into two stages to avoid associativity problems,
  715.  *   and careful to round up rather than truncate result.
  716.  */
  717. clkCycles  = (period * 4) + (pSbic->clkPeriod - 1);
  718. clkCycles /= pSbic->clkPeriod;
  719. if (clkCycles < SBIC_MIN_XFER_PERIOD)
  720.     {
  721.     clkCycles = SBIC_MIN_XFER_PERIOD;
  722.     inRange   = FALSE;
  723.     }
  724. else if (clkCycles > SBIC_MAX_XFER_PERIOD)  /* very unlikely ! */
  725.     {
  726.     clkCycles = SBIC_MAX_XFER_PERIOD;
  727.     inRange   = FALSE;
  728.     }
  729. period = (clkCycles * pSbic->clkPeriod) / 4;
  730. /*
  731.  *  Clip offset (if necessary) to suit SBIC
  732.  */
  733.      if (offset > SBIC_MAX_REQ_ACK_OFFSET)
  734.     {
  735.     offset  = SBIC_MAX_REQ_ACK_OFFSET;
  736.     inRange = FALSE;
  737.     }
  738. /*
  739.  *  Merge offset and cycles to form Sync. Transfer Reg. contents
  740.  */
  741. if (clkCycles == SBIC_MAX_XFER_PERIOD)
  742.     clkCycles = 0;
  743. xferParams = (clkCycles << SBIC_SYNC_XFER_PERIOD_SHIFT) | offset;
  744. }
  745.     *pOffset     = offset;
  746.     *pPeriod     = period;
  747.     *pXferParams = xferParams;
  748.     return (inRange);
  749.     }
  750. /*******************************************************************************
  751. *
  752. * sbicXferCountSet - load the SBIC transfer counter with the specified count 
  753. *
  754. * RETURNS: OK if count is in range 0 - 0xffffff, otherwise ERROR.
  755. *
  756. * NOMANUAL
  757. */
  758. LOCAL STATUS sbicXferCountSet
  759.     (
  760.     FAST SBIC *pSbic, /* ptr to SBIC info */
  761.     FAST UINT count /* count value to load */
  762.     )
  763.     {
  764.     if (count > WD_33C93_MAX_BYTES_PER_XFER)
  765.         return (ERROR);
  766.     *pSbic->pAdrsReg = SBIC_REG_XFER_COUNT_MSB;
  767.     
  768.     *pSbic->pRegFile = (UINT8) ((count >> 16) & 0xff);
  769.     *pSbic->pRegFile = (UINT8) ((count >>  8) & 0xff);
  770.     *pSbic->pRegFile = (UINT8) ( count        & 0xff);
  771.     
  772.     return (OK);
  773.     }
  774. /*******************************************************************************
  775. *
  776. * sbicXferCountGet - fetch the SBIC transfer count 
  777. *
  778. * The value of the transfer counter is copied to *pCount.
  779. *
  780. * NOMANUAL
  781. */
  782. LOCAL void sbicXferCountGet
  783.     (
  784.     FAST SBIC *pSbic, /* ptr to SBIC info */
  785.     FAST UINT *pCount /* ptr to returned value */
  786.     )
  787.     {
  788.     FAST UINT tempCount;
  789.     *pSbic->pAdrsReg = SBIC_REG_XFER_COUNT_MSB;
  790.     
  791.     tempCount  = ((UINT) *pSbic->pRegFile) << 16;
  792.     tempCount |= ((UINT) *pSbic->pRegFile) << 8;
  793.     tempCount |=  (UINT) *pSbic->pRegFile;
  794.     
  795.     *pCount = (int) tempCount;
  796.     }
  797. /*******************************************************************************
  798. *
  799. * sbicCommand - write a command code to the SBIC Command Register
  800. *
  801. * NOMANUAL
  802. */
  803. LOCAL void sbicCommand
  804.     (
  805.     SBIC *pSbic, /* ptr to SBIC info */
  806.     UINT8 cmdCode /* new command code */
  807.     )
  808.     {
  809.     while (*pSbic->pAuxStatReg & SBIC_AUX_STAT_CMD_IN_PROG)
  810. ;
  811.     *pSbic->pAdrsReg = SBIC_REG_COMMAND;
  812.     *pSbic->pRegFile = cmdCode;
  813.     }
  814. /*******************************************************************************
  815. *
  816. * sbicIntr - interrupt service routine for the SBIC
  817. *
  818. * NOMANUAL
  819. */
  820. LOCAL void sbicIntr
  821.     (
  822.     SBIC *pSbic /* ptr to SBIC info */
  823.     )
  824.     {
  825.     UINT8 scsiStatus;
  826.     int   targetId;
  827.     SBIC_STATE state;
  828.     SCSI_EVENT event;
  829.     int  busPhase     = NONE;    /* init. to prevent a warning */
  830.     BOOL initComplete = FALSE;
  831.     BOOL xferComplete = FALSE;
  832.     event.type = NONE;
  833.     /*
  834.      * Read SCSI status register and "decode" into state transitions etc.
  835.      */
  836.     *pSbic->pAdrsReg = SBIC_REG_SCSI_STATUS;
  837.     scsiStatus       = *pSbic->pRegFile;
  838.     state = pSbic->state;
  839.     SCSI_INT_DEBUG_MSG ("SBIC Interrupt: code = 0x%02x (state = %d)n",
  840. scsiStatus, state, 0, 0, 0, 0);
  841.     /*
  842.      * Parse SBIC SCSI status; generate state info (don't change state yet !)
  843.      */
  844.     if (scsiStatus & STAT_PHASE_REQ)
  845. {
  846. busPhase    = (int) (scsiStatus & STAT_MCI_BITS);
  847. scsiStatus |= STAT_MCI_BITS;
  848. }
  849.     /*
  850.      * If the target disconnects after an info transfer but before a new
  851.      * phase has been requested, the 33C93 appears to generate a normal
  852.      * disconnect interrupt rather than an unexpected disconnect.  To keep
  853.      * the ISR logic clean, we convert this to an unexpected disconnect.
  854.      */
  855.     if ((scsiStatus == STAT_SERV_REQ_DISCON) && pSbic->xferPending)
  856. {
  857. scsiStatus = STAT_TERM_UNEXP_DISCON;
  858. }
  859.     
  860.     switch (scsiStatus)
  861. {
  862. /*  Group: Reset */
  863. case STAT_SUCC_RESET:
  864.     initComplete = TRUE;
  865.     state        = SBIC_STATE_IDLE;
  866.     break;
  867. /*  Group: Successful Completion */
  868. case STAT_SUCC_SELECT:
  869.     /* assert (state == SBIC_STATE_SELECT_PENDING); */
  870.     /* Select command completed successfully */
  871.     
  872.          sbicRegRead (pSbic, SBIC_REG_DEST_ID, &targetId);
  873.     event.type        = SCSI_EVENT_CONNECTED;
  874.     event.busId       = targetId & 0x07;
  875.     event.nBytesIdent = 0;
  876.     state = SBIC_STATE_CONNECTED;
  877.     break;
  878. case STAT_SUCC_XFER_MCI:
  879.     /* assert (state == SBIC_STATE_CONNECTED); */
  880.     /* current transfer completed: req for new phase */
  881.     
  882.     event.type  = SCSI_EVENT_XFER_REQUEST;
  883.     event.phase = busPhase;
  884.     
  885.     xferComplete = TRUE;
  886.     break;
  887. /*  Group: Paused/Aborted */
  888. case STAT_PAUSE_MSG_IN:
  889.     /* assert (state == SBIC_STATE_CONNECTED); */
  890.     /* current msg in transfer completed: ack asserted */
  891.     
  892.     xferComplete = TRUE;
  893.     break;
  894. /*  Group: Terminated */
  895. case STAT_TERM_UNEXP_DISCON:
  896.     /* assert (state == SBIC_STATE_CONNECTED); */
  897.     /* current transfer terminated due to disconnection */
  898.     
  899.     event.type = SCSI_EVENT_DISCONNECTED;
  900.     
  901.     xferComplete = TRUE;
  902.     state = SBIC_STATE_IDLE;
  903.     break;
  904.     
  905. case STAT_TERM_TIMEOUT:
  906.     /* assert (pSbic->state == SBIC_STATE_SELECT_PENDING); */
  907.     /* Select command timed out */
  908.     event.type = SCSI_EVENT_TIMEOUT;
  909.     
  910.     state = SBIC_STATE_IDLE;
  911.     break;
  912. case STAT_TERM_UNX_PHASE:
  913.     /* assert (state == SBIC_STATE_CONNECTED); */
  914.     /* current transfer terminated by req for new phase */
  915.     
  916.     event.type  = SCSI_EVENT_XFER_REQUEST;
  917.     event.phase = busPhase;
  918.     xferComplete = TRUE;
  919.     break;
  920. /*  Group: Service Required */
  921.     
  922. case STAT_SERV_REQ_RESELECT:
  923.          sbicRegRead (pSbic, SBIC_REG_SOURCE_ID, &targetId);
  924.     event.type        = SCSI_EVENT_RESELECTED;
  925.     event.busId       = targetId & 0x07;
  926.     event.nBytesIdent = 0;
  927.     state = SBIC_STATE_CONNECTED;
  928.     break;
  929.     
  930. case STAT_SERV_REQ_DISCON:
  931.     /* assert (state == SBIC_STATE_CONNECTED); */
  932.     event.type = SCSI_EVENT_DISCONNECTED;
  933.     state = SBIC_STATE_IDLE;
  934.     break;
  935. case STAT_SERV_REQ_ASSERTED:
  936.     /* assert (state == SBIC_STATE_CONNECTED); */
  937.     event.type  = SCSI_EVENT_XFER_REQUEST;
  938.     event.phase = busPhase;
  939.     break;
  940.     
  941. default:
  942.     logMsg ("Unexpected SBIC Interrupt, Code = 0x%02x (state = %d)n",
  943.     scsiStatus, state, 0, 0, 0, 0);
  944.     break;
  945. }
  946.     /*
  947.      * Handle state transition, if any
  948.      */
  949.     if (state != pSbic->state)
  950. {
  951. SCSI_INT_DEBUG_MSG ("SBIC state transition: %d -> %dn",
  952.     pSbic->state, state, 0, 0, 0, 0);
  953. pSbic->state = state;
  954.      }
  955.     /*
  956.      * Synchronize with task-level code
  957.      */
  958.     if (initComplete && pSbic->initPending)
  959. {
  960.         pSbic->initPending = FALSE;
  961. sbicPostResetInit (pSbic);
  962. }
  963.     if (xferComplete && pSbic->xferPending)
  964. {
  965. pSbic->xferPending = FALSE;
  966. semGive (&pSbic->xferDoneSem);
  967. }
  968.     /*
  969.      * Post event to SCSI manager for further processing
  970.      */
  971.     if (event.type != NONE)
  972. scsiMgrEventNotify ((SCSI_CTRL *)pSbic, &event, sizeof (event));
  973.     }
  974. /*******************************************************************************
  975. *
  976. * sbicHwInit - initialize the SBIC to a known state
  977. *
  978. * This routine puts the SBIC into a known quiescent state.  It does *not*
  979. * reset the SCSI bus (and any other devices thereon).
  980. *
  981. * The reselection interrupt is enabled iff the "disconnect" flag is set in
  982. * the SCSI controller data structure.  DMA transfers are enabled iff there is
  983. * a DMA transfer function in the SCSI controller data structure.
  984. *
  985. * NOTE: the SBIC does not preserve its entire register context over a software
  986. * reset so the initialisation is completed in the reset interrupt handler.
  987. * If the routine is called at task level, it waits until this processing has
  988. * been completed (a busy wait, as it's only a few microseconds).  If it is
  989. * called from interrupt level, it does *not* wait for the reset to complete.
  990. * Be warned !
  991. */
  992. LOCAL void sbicHwInit
  993.     (
  994.     SBIC *pSbic /* ptr to an SBIC structure */
  995.     )
  996.     {
  997.     pSbic->initPending = TRUE;
  998.     
  999.     sbicRegWrite (pSbic, SBIC_REG_OWN_ID, (UINT8) pSbic->scsiCtrl.scsiCtrlBusId);
  1000.     sbicCommand  (pSbic, SBIC_CMD_RESET);
  1001.     if (!intContext ())
  1002. {
  1003.         /*
  1004.       *  Wait for "reset" command to finish.  Busy wait on flag set by
  1005.          *  reset interrupt handler - shouldn't be more than a few microsecs,
  1006.          *  but don't wait more than SBIC_MAX_RESET_WAIT clock ticks in any
  1007.  *  case.
  1008.       */
  1009. ULONG timeOut = tickGet () + SBIC_MAX_RESET_WAIT;
  1010.      while (pSbic->initPending && (tickGet () < timeOut))
  1011.     ;
  1012.         if (pSbic->initPending)
  1013.     logMsg ("sbicHwInit: initialisation command not completed !n",
  1014.     0, 0, 0, 0, 0, 0);
  1015.         }
  1016.     }
  1017. /******************************************************************************
  1018. *
  1019. * sbicPostResetInit - SBIC post-reset initialisation
  1020. *
  1021. * This routine completes the SBIC initialisation started in "sbicHwInit ()".
  1022. * It is called at interrupt level after the software reset command has
  1023. * completed.
  1024. */
  1025. LOCAL void sbicPostResetInit
  1026.     (
  1027.     FAST SBIC *pSbic /* ptr to SBIC info */
  1028.     )
  1029.     {
  1030.     
  1031.     UINT8 srcIdVal = pSbic->scsiCtrl.disconnect ?
  1032.                SBIC_SRC_ID_RESEL_ENABLE : 0x00;
  1033.     
  1034.     UINT8 ctrlVal  = (pSbic->sysScsiDmaStart != NULL) ?
  1035.                SBIC_CONTROL_DMA_ENABLE : 0x00;
  1036.     
  1037.     sbicRegWrite (pSbic, SBIC_REG_SOURCE_ID, srcIdVal);
  1038.     sbicRegWrite (pSbic, SBIC_REG_CONTROL,   ctrlVal);
  1039.     }
  1040. /*******************************************************************************
  1041. *
  1042. * sbicRegRead - Get the contents of a specified SBIC register
  1043. */
  1044. LOCAL void sbicRegRead
  1045.     (
  1046.     SBIC *pSbic, /* ptr to an SBIC structure    */
  1047.     UINT8 regAdrs, /* address of register to read */
  1048.     int  *pDatum /* buffer for return value     */
  1049.     )
  1050.     {
  1051.     *pSbic->pAdrsReg = regAdrs;
  1052.     *pDatum = (int) *pSbic->pRegFile;
  1053.     }
  1054. /*******************************************************************************
  1055. *
  1056. * sbicRegWrite - write a value to a specified SBIC register
  1057. *
  1058. * NOMANUAL
  1059. */
  1060. LOCAL void sbicRegWrite
  1061.     (
  1062.     SBIC *pSbic, /* ptr to an SBIC structure     */
  1063.     UINT8 regAdrs, /* address of register to write */
  1064.     UINT8 datum /* value to be written          */
  1065.     )
  1066.     {
  1067.     *pSbic->pAdrsReg = regAdrs;
  1068.     *pSbic->pRegFile = datum;
  1069.     }
  1070. /*******************************************************************************
  1071. *
  1072. * wd33c93Show - Display values of all readable wd33c93 chip registers
  1073. *
  1074. * Only for use during debugging.
  1075. *
  1076. * RETURNS: OK | ERROR.
  1077. */
  1078. LOCAL STATUS wd33c93Show
  1079.     (
  1080.     FAST SCSI_CTRL *pScsiCtrl /* ptr to SCSI controller info */
  1081.     )
  1082.     {
  1083.     FAST int ix;
  1084.     FAST SBIC *pSbic; /* ptr to SBIC info */
  1085.     if (pScsiCtrl == NULL)
  1086.         {
  1087.         if (pSysScsiCtrl != NULL)
  1088.             pScsiCtrl = pSysScsiCtrl;
  1089.         else
  1090.             {
  1091.             printErr ("No SCSI controller specified.n");
  1092.             return (ERROR);
  1093.             }
  1094.         }    
  1095.     pSbic = (SBIC *) pScsiCtrl;
  1096.     for (ix = SBIC_REG_OWN_ID; ix <= SBIC_REG_COMMAND; ix++)
  1097. {
  1098.         *pSbic->pAdrsReg = (UINT8) ix;
  1099. printf ("REG #%02x = 0x%02xn", ix, *pSbic->pRegFile);
  1100. }
  1101.     return (OK);
  1102.     }