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

VxWorks

开发平台:

C/C++

  1. /* pccDma.c - Peripheral Channel Controller (PCC) DMA library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02g,24apr02,pmr  SPR 74390: added include of header fcntlcom.h for O_RDONLY.
  8. 02f,18nov96,dds  SPR 7398: removed the calls to cacheInvalidate & cacheFlush
  9.                  for SCSI-2. This is handled in scsi2Lib.c
  10. 02e,18nov96,dds  removed the calls to cacheInvalidate & cacheFlush
  11.                  for SCSI-2. This is handled in scsi2Lib.c
  12. 02d,11oct96,dds  merged from vxw5_3_x.scsi2 branch.
  13. 02c,19aug96,dds  removed compiler warnings.
  14. 02b,22may96,dds  added code to transfer the contents of the DMA holding
  15.                  register to memory during a sysScsiDmaAbort(). During
  16.  a tape read 1,2 or 3 bytes get left in the DMA holding
  17.  register. 
  18. 02a,10aug95,jds  integrated changes for dma routines for SCSI-2. Should be
  19.  compatible for both SCSI-1 and SCSI-2.
  20. 01g,06jun96,wlf  doc: cleanup; (per jds) sysScsiDmaAbort() made NOMANUAL.
  21. 01f,12nov94,dzb  fixed c&p error.
  22. 01e,12oct93,jds  merged SCSI1 pccDma.c 
  23. 01d,09aug93,ccc  added SCSI disconnect support.
  24. 01c,27jul92,ccc  added cache support for SCSI DMA routines.
  25. 01b,11jul92,ccc  fixed function headers, and changed READ and WRITE
  26.  to O_RDONLY and O_WRONLY.
  27. 01a,11jun92,ccc  created by moving routines from mv147 sysLib.c, ansified.
  28. */
  29. /*
  30. DESCRIPTION
  31. These routines provide DMA transfer for the PCC chip on the mv147.
  32. */
  33. #ifndef INCLUDE_SCSI2
  34. #ifdef INCLUDE_SCSI_DMA
  35. #include "cacheLib.h"
  36. #include "sys/fcntlcom.h"
  37. #define DMA_FUNCTION_CODE (0x5 << 24)
  38. /*******************************************************************************
  39. *
  40. * sysScsiDmaTransfer - start the DMA data transfer
  41. *
  42. * This routines initializes the DMA, and starts the transfer
  43. *
  44. * NOMANUAL
  45. */
  46. void sysScsiDmaTransfer
  47.     (
  48.     UINT8 *pBuffer, /* ptr to the data buffer  */
  49.     int    bufLength, /* number of bytes to xfer */
  50.     int    direction /* direction of transfer   */
  51.     )
  52.     {
  53.     *SCSI_PCC_DMA_ADRS = (long) pBuffer;
  54.     *SCSI_DMA_BYTE_COUNT = (long) (bufLength | DMA_FUNCTION_CODE);
  55.     if (direction == O_RDONLY)
  56. {
  57. cacheInvalidate (DATA_CACHE, pBuffer, bufLength);
  58. *SCSI_DMA_CSR = DMA_CSR_ENABLE | DMA_CSR_READ;
  59. }
  60.     else
  61. {
  62. cacheFlush (DATA_CACHE, pBuffer, bufLength);
  63. *SCSI_DMA_CSR = DMA_CSR_ENABLE | DMA_CSR_WRITE;
  64. }
  65.     }
  66. /********************************************************************************
  67. *
  68. * sysWdDmaBytesIn - input SCSI data bytes using on-board DMA
  69. *
  70. * This routine gets passed to the wd33c93CtrlCreate() call when DMA should
  71. * be used for SCSI DATA IN transfers.
  72. *
  73. * RETURNS: OK or ERROR.
  74. *
  75. * SEE ALSO: wd33c93Lib
  76. *
  77. * NOMANUAL
  78. */
  79. STATUS sysWdDmaBytesIn
  80.     (
  81.     SCSI_PHYS_DEV *pScsiPhysDev,       /* ptr to phys dev info    */
  82.     UINT8 *pBuffer,                    /* ptr to the data buffer  */
  83.     int bufLength                      /* number of bytes to xfer */
  84.     )
  85.     {
  86.     FAST WD_33C93_SCSI_CTRL *pSbic;     /* ptr to SBIC info */
  87.     pSbic = (WD_33C93_SCSI_CTRL *) pScsiPhysDev->pScsiCtrl;
  88.     *pSbic->pAdrsReg = SBIC_REG_CONTROL;
  89.     *pSbic->pRegFile = SBIC_CTRL_DMA_BYTE;
  90.     if (bufLength != 1)
  91.         {
  92.         if (sbicXferCountSet (pSbic, (UINT) bufLength) == ERROR)
  93.             return (ERROR);
  94.  
  95.         sbicCommand (pSbic, SBIC_CMD_XFER_INFO);
  96.         }
  97.     else
  98.         sbicCommand (pSbic, SBIC_CMD_XFER_INFO | SBIC_CMD_SING_BYTE_XFER);
  99.     sysScsiDmaTransfer (pBuffer, bufLength, O_RDONLY); 
  100.     return (OK);
  101.     }
  102.  
  103. /********************************************************************************
  104. *
  105. * sysWdDmaBytesOut - output SCSI data bytes using on-board DMA
  106. *
  107. * This routine passes control to wd33c93CtrlCreate() when DMA should
  108. * be used for SCSI DATA OUT transfers.
  109. *
  110. * RETURNS: OK or ERROR.
  111. *
  112. * SEE ALSO: wd33c93Lib
  113. *
  114. * NOMANUAL
  115. */
  116.  
  117. STATUS sysWdDmaBytesOut
  118.     (
  119.     SCSI_PHYS_DEV *pScsiPhysDev,       /* ptr to phys dev info    */
  120.     UINT8 *pBuffer,                    /* ptr to the data buffer  */
  121.     int bufLength                      /* number of bytes to xfer */
  122.     )
  123.     {
  124.     FAST WD_33C93_SCSI_CTRL *pSbic;     /* ptr to SBIC info */
  125.  
  126.     pSbic = (WD_33C93_SCSI_CTRL *) pScsiPhysDev->pScsiCtrl;
  127.  
  128.     *pSbic->pAdrsReg = SBIC_REG_CONTROL;
  129.     *pSbic->pRegFile = SBIC_CTRL_DMA_BYTE;
  130.  
  131.     if (bufLength != 1)
  132.         {
  133.         if (sbicXferCountSet (pSbic, (UINT) bufLength) == ERROR)
  134.             return (ERROR);
  135.  
  136.         sbicCommand (pSbic, SBIC_CMD_XFER_INFO);
  137.         }
  138.     else
  139.         sbicCommand (pSbic, SBIC_CMD_XFER_INFO | SBIC_CMD_SING_BYTE_XFER);
  140.     sysScsiDmaTransfer (pBuffer, bufLength, O_WRONLY);
  141.     return (OK);
  142.     }
  143.  
  144. /********************************************************************************
  145. *
  146. * sysScsiDmaIntr - MVME147 SCSI DMA interrupt routine
  147. *
  148. * This routine connects to the interrupt vector when handling SCSI DMA
  149. * operations.
  150. *
  151. * RETURNS: N/A.
  152. *
  153. * NOMANUAL
  154. */
  155.  
  156. void sysScsiDmaIntr
  157.     (
  158.     WD_33C93_SCSI_CTRL *pSbic     /* ptr to SBIC info */
  159.     )
  160.     {
  161.     FAST char dmaIntCtrl;
  162.     FAST char dmaCsr;
  163.  
  164.     dmaIntCtrl = *SCSI_DMA_INT_CTL;
  165.     dmaCsr     = *SCSI_DMA_CSR;
  166.  
  167.     if (scsiIntsDebug)
  168.         {
  169.         logMsg ("sysScsiDmaIntr called.n", 0, 0, 0, 0, 0, 0);
  170.  
  171.         logMsg ("SCSI_DMA_INT_CTL (0x20) = 0x%02xn", dmaIntCtrl,
  172. 0, 0, 0, 0, 0);
  173.  
  174.         logMsg ("SCSI_DMA_CSR     (0x21) = 0x%02xn", *SCSI_DMA_CSR,
  175. 0, 0, 0, 0, 0);
  176.         }
  177.  
  178.     if (dmaCsr & DMA_INT_CTL_PENDING)
  179.         {
  180.         *SCSI_DMA_INT_CTL = dmaIntCtrl |
  181.                             DMA_INT_CTL_CLEAR;  /* reset interrupt */
  182.  
  183.         *SCSI_DMA_CSR     = DMA_CSR_DISABLE;    /* disable DMA */
  184.         }
  185.     else
  186.         logMsg ("DMA not DONE.n", 0, 0, 0, 0, 0, 0);
  187.     }
  188.        
  189. #endif /* INCLUDE_SCSI_DMA */
  190. #endif  /* #ifndef INCLUDE_SCSI2 */
  191. #ifdef INCLUDE_SCSI2
  192. #define SCSI_DMA_HOLDING_REG      ((long *) (PCC_BASE_ADRS +  0x0c))
  193. #ifdef INCLUDE_SCSI
  194. LOCAL BOOL sysScsiBusWasReset   = FALSE;
  195. LOCAL UINT bufferLength; /* original length of current dma operation */
  196. #endif /* INCLUDE_SCSI */
  197. #ifdef INCLUDE_SCSI_DMA
  198. #include "cacheLib.h"
  199. #include "sys/fcntlcom.h"
  200. #define DMA_FUNCTION_CODE (0x5 << 24)
  201. LOCAL BOOL sysScsiDmaInProgress = FALSE;
  202. /*******************************************************************************
  203. *
  204. * sysScsiDmaStart - start DMA transfer to/from on-board SCSI controller
  205. *
  206. * This routine gets passed to the wd33c93CtrlCreate() call when DMA should
  207. * be used for SCSI DATA IN and DATA out transfers.
  208. *
  209. * Starts the DMA transfer and returns immediately (i.e., without waiting for
  210. * the transfer to complete).  May be called only at task level.
  211. *
  212. * Note that the SCSI library is responsible for properly serialising all SCSI
  213. * DMA operations (in particular, starts and aborts) so it is an error for this
  214. * routine to be called if a transfer is already in progress.
  215. *
  216. * RETURNS: OK | ERROR.
  217. *
  218. * NOMANUAL
  219. */
  220. STATUS sysScsiDmaStart
  221.     (
  222.     int    arg,                         /* call-back argument (ignored) */
  223.     UINT8 *pBuffer,                     /* ptr to the data buffer */
  224.     UINT   bufLength,                   /* number of bytes to xfer */
  225.     int    direction                    /* 0 => read, <>0 => write */
  226.     )
  227.     {
  228.     SCSI_DEBUG_MSG ("sysScsiDmaStart: %d bytes %sn", bufLength,
  229.                     (direction == READ) ? (int)"in" : (int)"out", 0, 0, 0, 0);
  230.     if ((bufLength == 0) || (bufLength > 0x00ffffff))
  231.         {
  232.         SCSI_DEBUG_MSG ("sysScsiDmaStart: invalid byte count (%u)n",
  233.                         bufLength, 0, 0, 0, 0, 0);
  234.         return (ERROR);
  235.         }
  236.     bufferLength = bufLength;
  237.     /*
  238.      *  No interrupt lock needed here as there is no way a DMA interrupt can
  239.      *  occur unless a transfer is already in progress (in which case we
  240.      *  don't touch anything).
  241.      */
  242.     if (sysScsiDmaInProgress)
  243.         {
  244.         SCSI_DEBUG_MSG ("sysScsiDmaStart: DMAC already in usen",
  245. 0, 0, 0, 0, 0, 0);
  246.         return (ERROR);
  247.         }
  248.     sysScsiDmaInProgress = TRUE;
  249.     *SCSI_PCC_DMA_ADRS   = (long) pBuffer;
  250.     *SCSI_DMA_BYTE_COUNT = (long) (bufLength | DMA_FUNCTION_CODE);
  251.     if (direction == O_RDONLY)
  252.         {
  253.         *SCSI_DMA_CSR = DMA_CSR_ENABLE | DMA_CSR_READ;
  254.         }
  255.     else
  256.         {
  257.         *SCSI_DMA_CSR = DMA_CSR_ENABLE | DMA_CSR_WRITE;
  258.         }
  259.     return (OK);
  260.     }
  261. /*******************************************************************************
  262. *
  263. * sysScsiDmaAbort - abort current DMA transfers to or from the SCSI controller
  264. *
  265. * This routine gets passed to wd33c93CtrlCreate() when DMA should
  266. * be used for SCSI data-in and data-out transfers.
  267. *
  268. * If a DMA transfer is in progress when this routine is called, it is
  269. * aborted with a write to the DMAC CSR.  This routine can be called at task or
  270. * interrupt level.
  271. *
  272. * NOTE: The SCSI library never calls this routine without the successful return
  273. * of a prior call to sysScsiDmaStart().
  274. *
  275. * RETURNS: OK or ERROR.
  276. *
  277. * NOMANUAL
  278. */
  279. STATUS sysScsiDmaAbort
  280.     (
  281.     int arg                            /* call-back argument (ignored) */
  282.     )
  283.     {
  284.     int lockKey;
  285.     char *memLoc;
  286.     UINT bytesToXfer;
  287.     union
  288. {
  289. long holdRegLong;
  290. char holdRegBytes[4];
  291. } holdReg;
  292.     int i=0;
  293.  
  294.     SCSI_INT_DEBUG_MSG ("sysScsiDmaAbort:n", 0, 0, 0, 0, 0, 0);
  295.  
  296.     lockKey = intLock ();      /* avoid race with DMA complete ISR */
  297.  
  298.     /* Bytes to tranfer from the DMA holding register to memory */
  299.     bytesToXfer =  (bufferLength - (*SCSI_DMA_BYTE_COUNT & 0x00ffffff)) % 4;
  300.     holdReg.holdRegLong = *((long *) SCSI_DMA_HOLDING_REG);
  301.     memLoc = (char *) (*SCSI_PCC_DMA_ADRS);
  302.     while (bytesToXfer--)
  303. {
  304. *memLoc++ = holdReg.holdRegBytes[i++];
  305. }
  306.  
  307.     if (sysScsiDmaInProgress)
  308. {
  309. *SCSI_DMA_CSR = (char) DMA_CSR_DISABLE;
  310. sysScsiDmaInProgress = FALSE;
  311. }
  312.  
  313.     intUnlock (lockKey);
  314.  
  315.     return (OK);
  316.     }
  317. /********************************************************************************
  318. *
  319. * sysScsiDmaIntr - MVME147 SCSI DMA interrupt routine
  320. *
  321. * This routine connects to the interrupt vector when handling SCSI DMA
  322. * operations.
  323. *
  324. * RETURNS: N/A.
  325. *
  326. * NOMANUAL
  327. */
  328.  
  329. void sysScsiDmaIntr
  330.     (
  331.     WD_33C93_SCSI_CTRL *pSbic     /* ptr to SBIC info */
  332.     )
  333.     {
  334.     int lockKey;
  335.     FAST char dmaIntCtrl;
  336.     FAST char dmaCsr;
  337.  
  338.     dmaIntCtrl = *SCSI_DMA_INT_CTL;
  339.     dmaCsr     = *SCSI_DMA_CSR;
  340.  
  341.     if (scsiIntsDebug)
  342.         {
  343.         logMsg ("sysScsiDmaIntr called.n", 0, 0, 0, 0, 0, 0);
  344.  
  345.         logMsg ("SCSI_DMA_INT_CTL (0x20) = 0x%02xn", dmaIntCtrl,
  346. 0, 0, 0, 0, 0);
  347.  
  348.         logMsg ("SCSI_DMA_CSR     (0x21) = 0x%02xn", *SCSI_DMA_CSR,
  349. 0, 0, 0, 0, 0);
  350.         }
  351.  
  352.     if (dmaCsr & DMA_INT_CTL_PENDING)
  353.         {
  354.         *SCSI_DMA_INT_CTL = dmaIntCtrl |
  355.                             DMA_INT_CTL_CLEAR;  /* reset interrupt */
  356.         }
  357.     else
  358.         logMsg ("DMA not DONE.n", 0, 0, 0, 0, 0, 0);
  359.     lockKey = intLock (); /* avoid rate with DMA abort */
  360.     if (sysScsiDmaInProgress)
  361. {
  362. *SCSI_DMA_CSR = DMA_CSR_DISABLE; /* disable DMA */
  363. sysScsiDmaInProgress = FALSE;
  364. }
  365.     intUnlock (lockKey);
  366.     }
  367. #endif  /* INCLUDE_SCSI_DMA */
  368. #endif /* INCLUDE_SCSI2 */