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

VxWorks

开发平台:

C/C++

  1. /* mpc107I2c.c - MPC107 I2C support */
  2. /* Copyright 1996-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01d,15sep01,dat  Use of vxDecGet routine
  8. 01c,11sep00,rcs  fix include paths
  9. 01b,22jun00,bri  updated to WindRiver coding standards.
  10. 01a,18jun00,bri  created - based on  Kahlua I2C driver.
  11. */
  12. /*
  13. DESCRIPTION
  14. This module contains routines for the I2C  interface of MPC107.
  15. The I2C interface is a two-wire, bidirectional serial bus that provides
  16. a simple, efficient way to exchange data between integrated circuit(IC) devices.
  17. The I2C interface allows the MPC107 to exchange data with other I 2 C devices
  18. such as microcontrollers, EEPROMs, real-time clock devices, A/D converters,
  19. and LCDs.
  20. This module provides the routines  for writing/reading  data to/from
  21. the I2C interface with MPC107 as a "master"  device .
  22. The routine mpc107i2cWrite() is used for writing  data to an EEPROM type
  23. slave device .
  24. The routine mpc107i2cRead() is used for reading data from an EEPROM type
  25. slave device .
  26. Support for other I2C slave devices can be added easily by using the
  27. routines provided in this module .
  28. Reading/writing data from/to the I2C interface with MPC107 as a "slave" device
  29. are not supported in this module .
  30. However, additional I2C bus controllers can be easily be added as required.
  31. .SH INITIALIZATION
  32. The routine mpc107I2cInit() should be called to  initialize the
  33. IIC interface.
  34. The user has to specify the the following parameters for
  35. programming the I2C Frequency Divider Register (I2CFDR):
  36. .IP DFFSR
  37. Specifies the Digital filter frequency sampling rate of the I2C interface.
  38. DFFSR can be changed by changing MPC107_DFFSR_DATA in the header file.
  39. .IP FDR
  40. Specifies the Frequency divider ratio.FDR can be changed by changing
  41. MPC107_FDR_DATA in the header file .
  42. .LP
  43. The user has to specify the the following parameters for
  44. programming the I2C Address Register (I2CADR) :
  45. .IP ADDR
  46. Specifies the  Slave address used by the I2C interface when MPC107 is configured
  47. as a slave.ADDR can be changed by changing MPC107_ADR_DATA in the header file
  48. .LP
  49. Refer to MPC107 users manual for further details about the values
  50. to be programmed in the I2C registers .
  51. */
  52. /* includes */
  53. #include "vxWorks.h"
  54. #include "sysLib.h"
  55. #include "stdlib.h"
  56. #include "drv/multi/mpc107.h"
  57. #include "drv/multi/mpc107I2c.h"
  58. #include "drv/intrCtl/mpc107Epic.h"
  59. /* globals  */
  60. /* static file scope locals */
  61. BOOL i2cDoRepeatStart = FALSE;    /* Repeat start */
  62. /* forward Declarations */
  63. LOCAL INT32 mpc107i2cCycleStart (void);
  64. LOCAL void mpc107i2cCycleStop (void);
  65. LOCAL void  mpc107i2cCycleRead (UCHAR* data);
  66. LOCAL void  mpc107i2cCycleWrite (UCHAR data);
  67. LOCAL INT32  mpc107i2cCycleAckIn (void);
  68. LOCAL void  mpc107I2cCycleDelay (UINT milliSec);
  69. LOCAL UINT32  mpc107GetDec (void);
  70. LOCAL UINT32  mpc107I2cRegRdWrMod (UINT32 operation , UINT32 address ,
  71.                                      UINT32 data1, UINT32 data2);
  72. LOCAL VOID  mpc107I2cDoOperation (UINT32 deviceAddress,
  73.                                       MPC107_I2C_CMD_PCKT * pI2cCmdPacket);
  74. /***************************************************************************
  75. *
  76. * mpc107I2cInit - initialize the IIC interface
  77. *
  78. * This routine initializes the IIC Interface.
  79. *
  80. * The  "Frequency Divider Register" is initialized depending on
  81. * the clock frequency.The slave address is also programmed. The IIC
  82. * interface is programmed to be in Master/Receive Mode with interrupts disabled.
  83. * After all the initialization is done  the IIC interface is enabled.
  84. * This routine must be called before the user can use the IIC interface to
  85. * read /write data.
  86. *
  87. * RETURNS: N/A
  88. */
  89. void mpc107I2cInit (void)
  90.     {
  91.     /* Update the frequency divider register */
  92.     mpc107I2cRegRdWrMod(MPC107_I2C_WRITE, MPC107_I2C_I2CFDR,
  93.                            MPC107_I2CFDR_DEFAULT, 0);
  94.     SYNC;
  95.     /* Update the I2CADR to define the slave address for this device */
  96.     mpc107I2cRegRdWrMod(MPC107_I2C_WRITE, MPC107_I2C_I2CADR,
  97.                             MPC107_I2CADR_DEFAULT, 0);
  98.     SYNC;
  99.     /*
  100.      * Update  control register to select Master
  101.      * Receive mode  and interrupt-disabled
  102.      */
  103.     mpc107I2cRegRdWrMod(MPC107_I2C_WRITE, MPC107_I2C_I2CCR,
  104.                             MPC107_I2CCR_DEFAULT,0);
  105.     SYNC;
  106.     /* Enable the I2C interface     */
  107.     mpc107I2cRegRdWrMod(MPC107_I2C_READ_OR_WRITE, MPC107_I2C_I2CCR,
  108.                         MPC107_I2CCR_MEN,0);
  109.     SYNC;
  110.     }
  111. /***************************************************************************
  112. *
  113. * mpc107i2cRead -  read  from the slave device on IIC bus
  114. *
  115. * This routine  reads the specified number of bytes from the specified slave
  116. * device with MPC107 as the master  .
  117. *
  118. * RETURNS: OK, or Error on a bad request
  119. */
  120. INT32 mpc107i2cRead
  121.     (
  122.     UINT32  deviceAddress, /* Device I2C  bus address */
  123.     UINT32  numBytes, /* number of Bytes to read */
  124.     char * pBuf /* pointer to buffer to receive data */
  125.     )
  126.     {
  127.     MPC107_I2C_CMD_PCKT  i2cCmdPacket; /* command packet */
  128.     /* Check for a bad request. */
  129.     if (numBytes == 0)
  130.         {
  131.         return (ERROR);
  132.         }
  133.     /* Build command packet. */
  134.     i2cCmdPacket.command = MPC107_I2C_READOP;
  135.     i2cCmdPacket.status = 0;
  136.     i2cCmdPacket.memoryAddress = (UINT32)pBuf;
  137.     i2cCmdPacket.nBytes = numBytes;
  138.     mpc107I2cDoOperation(deviceAddress, (MPC107_I2C_CMD_PCKT *)&i2cCmdPacket);
  139.     /* Return the appropriate status. */
  140.     return (i2cCmdPacket.status);
  141.     }
  142. /***************************************************************************
  143. *
  144. * mpc107i2cWrite - write to the slave device on IIC bus
  145. *
  146. * This routine is used to write the specified number of
  147. * bytes to the specified slave device with  MPC 107 as a master
  148. *
  149. * RETURNS: OK, or ERROR on a bad request.
  150. */
  151. INT32 mpc107i2cWrite
  152.     (
  153.     UINT32  deviceAddress, /* Devices I2C bus address */
  154.     UINT32  numBytes, /* number of bytes to write */
  155.     char * pBuf /* pointer to buffer of send data */
  156.     )
  157.     {
  158.     MPC107_I2C_CMD_PCKT  i2cCmdPacket; /* command packet */
  159.     /* Check for a NOP request. */
  160.     if (numBytes == 0)
  161.         {
  162.         return (ERROR);
  163.         }
  164.         /* Build command packet. */
  165.     i2cCmdPacket.command = MPC107_I2C_WRITOP;
  166.     i2cCmdPacket.status = 0;
  167.     i2cCmdPacket.memoryAddress = (UINT32)pBuf;
  168.     i2cCmdPacket.nBytes = numBytes;
  169.     /* Take ownership, call driver, release ownership. */
  170.      mpc107I2cDoOperation(deviceAddress, (MPC107_I2C_CMD_PCKT *)&i2cCmdPacket);
  171.     /* Return the appropriate status. */
  172.     return (i2cCmdPacket.status);
  173.     }
  174. /***************************************************************************
  175. *
  176. * mpc107i2cCycleRead - perform I2C "read" cycle
  177. *
  178. * This routine is used to  perform a read from the I2C bus .
  179. *
  180. * RETURNS: N/A
  181. */
  182. LOCAL void mpc107i2cCycleRead
  183.     (
  184.     UCHAR * pReadDataBuf /* pointer to read data buffer */
  185.     )
  186.     {
  187.     UINT32 readData = 0;
  188.     mpc107I2cCycleDelay (1);
  189.     /*
  190.      * Configure the I2C interface into receive mode(MTX=0) and set
  191.      * the interface  to NOT acknowledge(TXAK=1) the incoming data on
  192.      * the 9th clock cycle.
  193.      * This is required when doing random reads of a I2C device.
  194.      */
  195.     mpc107I2cRegRdWrMod(MPC107_I2C_READ_ANDOR_WRITE,
  196.                         MPC107_I2C_I2CCR,~(MPC107_I2CCR_MTX),
  197.                         MPC107_I2CCR_TXAK);
  198.     SYNC;
  199.     mpc107I2cCycleDelay (1);
  200.     /* Perform  a  "dummy read". This latches the data off the I2C  bus. */
  201.     mpc107I2cRegRdWrMod(MPC107_I2C_READ,MPC107_I2C_I2CDR, 0, 0);
  202.     SYNC;
  203.     mpc107I2cCycleDelay (1);
  204.     /* Perform the actual read */
  205.     readData = mpc107I2cRegRdWrMod(MPC107_I2C_READ, MPC107_I2C_I2CDR, 0, 0);
  206.     SYNC;
  207.     *pReadDataBuf = (UCHAR)readData; /* copy the read data */
  208.     return;
  209.     }
  210. /***************************************************************************
  211. *
  212. * mpc107i2cCycleWrite - perform I2C "write" cycle
  213. *
  214. * This routine is used is to perform a write to the I2C bus.
  215. * Data is written to the I2C interface .
  216. *
  217. * RETURNS: N/A
  218. */
  219. LOCAL void mpc107i2cCycleWrite
  220.     (
  221.     UCHAR writeData /* character to write */
  222.     )
  223.     {
  224.     mpc107I2cCycleDelay (1);
  225.     /*
  226.      * Write the requested data to the data register, which will cause
  227.      * it to be transmitted on the I2C bus.
  228.      */
  229.     mpc107I2cRegRdWrMod(MPC107_I2C_WRITE, MPC107_I2C_I2CDR, writeData, 0);
  230.     SYNC;
  231.     mpc107I2cCycleDelay (1);
  232.     return;
  233.     }
  234. /***************************************************************************
  235. *
  236. * mpc107i2cCycleAckIn - perform I2C "acknowledge-in" cycle
  237. *
  238. * This routine is used to perform an I2C acknowledge-in  on the bus.
  239. *
  240. * RETURNS: OK, or ERROR if timed out waiting for an ACK .
  241. */
  242. LOCAL STATUS mpc107i2cCycleAckIn (void)
  243.     {
  244.     UINT32  statusReg = 0;
  245.     UINT32  timeOutCount;
  246.     /*
  247.      * wait until an *internal* device interrupt has been generated, then
  248.      * clear it.  if it is not received, return with an error.
  249.      * we are polling, so NO processor interrupt is generated.
  250.      */
  251.     for (timeOutCount = 100; timeOutCount; timeOutCount--)
  252.         {
  253.         mpc107I2cCycleDelay (1);
  254.         statusReg = mpc107I2cRegRdWrMod(MPC107_I2C_READ, MPC107_I2C_I2CSR,0,0);
  255.         SYNC;
  256.         if ((statusReg & MPC107_I2CSR_MIF) != 0)
  257.             {
  258.             mpc107I2cRegRdWrMod(MPC107_I2C_READ_AND_WRITE,
  259.                                 MPC107_I2C_I2CSR,~(MPC107_I2CSR_MIF),0);
  260.             SYNC;
  261.             break;
  262.             }
  263.         }
  264.     if (timeOutCount == 0)
  265.         {
  266.         return (ERROR);
  267.         }
  268.     return (OK);
  269.     }
  270. /***************************************************************************
  271. *
  272. * mpc107i2cCycleStart - perform I2C "start" cycle
  273. *
  274. * This routine is used is to perform an I2C start cycle.
  275. *
  276. * RETURNS: OK, or ERROR if timed out waiting for the IIC bus to be free.
  277. */
  278. LOCAL STATUS mpc107i2cCycleStart (void)
  279.     {
  280.     UINT32  timeOutCount;
  281.     UINT32  statusReg = 0;
  282.     /*
  283.      * if this is a repeat start, then set the required bits and return.
  284.      * this driver ONLY supports one repeat start between the start cycle and
  285.      * stop cycles.
  286.      */
  287.     if(i2cDoRepeatStart)  /* If a repeat start */
  288.         {
  289.         mpc107I2cCycleDelay (1);
  290.         mpc107I2cRegRdWrMod(MPC107_I2C_READ_OR_WRITE, MPC107_I2C_I2CCR,
  291.                     (MPC107_I2CCR_RSTA | MPC107_I2CCR_MSTA |
  292.                      MPC107_I2CCR_MTX),0);
  293.         SYNC;
  294.         mpc107I2cCycleDelay (1);
  295.         i2cDoRepeatStart = FALSE;  /* one repeat start only, so clear this */
  296.         return(OK);
  297.         }
  298.     /*
  299.      * wait until the I2C bus is free.  if it doesn't become free
  300.      * within a *reasonable* amount of time, exit with an error.
  301.      */
  302.     for (timeOutCount = 10; timeOutCount; timeOutCount--)
  303.         {
  304.         mpc107I2cCycleDelay (1);
  305.         statusReg = mpc107I2cRegRdWrMod(MPC107_I2C_READ,
  306.                                         MPC107_I2C_I2CSR, 0, 0);
  307.         SYNC;
  308.         if ((statusReg & MPC107_I2CSR_MBB) == 0)
  309.             {
  310.             break;
  311.             }
  312.         }
  313.     if (timeOutCount == 0)
  314.         {
  315.         return (ERROR);
  316.         }
  317.     /*
  318.      * since this is the first time through, generate a START(MSTA) and
  319.      * place the I2C interface into a master transmitter mode(MTX).
  320.      */
  321.     mpc107I2cRegRdWrMod(MPC107_I2C_READ_OR_WRITE, MPC107_I2C_I2CCR,
  322.                        (MPC107_I2CCR_MTX | MPC107_I2CCR_MSTA),0);
  323.     SYNC;
  324.     mpc107I2cCycleDelay (1);
  325.     /*
  326.      * The first time through, set "i2cDoRepeatStart".  If this routine
  327.      * is called again BEFORE a STOP is sent, then we are doing a
  328.      * "dummy write", which sets the devices internal byte pointer
  329.      * to the byte we intend to read.
  330.      */
  331.     i2cDoRepeatStart = TRUE;
  332.     return (OK);
  333.     }
  334. /***************************************************************************
  335. *
  336. * mpc107i2cCycleStop - perform I2C "stop" cycle
  337. *
  338. * This routine is used is to perform an I2C stop cycle.
  339. *
  340. * RETURNS: N/A
  341. */
  342. LOCAL void mpc107i2cCycleStop (void)
  343.     {
  344.     mpc107I2cCycleDelay (1);
  345.     /*
  346.      * turn off MSTA bit(which will generate a STOP bus cycle)
  347.      * turn off MTX bit(which places the I2C interface into receive mode
  348.      * turn off TXAK bit(which allows 9th clock cycle acknowledges)
  349.      */
  350.     mpc107I2cRegRdWrMod(MPC107_I2C_READ_AND_WRITE, MPC107_I2C_I2CCR,
  351.                        (~(MPC107_I2CCR_MTX  | MPC107_I2CCR_MSTA |
  352.                           MPC107_I2CCR_TXAK)), 0);
  353.     SYNC;
  354.     mpc107I2cCycleDelay (1);
  355.     /* Clear the global I2C "Repeat Start" flag.*/
  356.     i2cDoRepeatStart = FALSE;
  357.     return ;
  358.     }
  359. /***************************************************************************
  360. *
  361. * mpc107i2cRegRdWrMod - i2c Registers In/OutLong and/or-ing wrapper.
  362. *
  363. * The purpose of this routine is to perform AND, OR, and
  364. * AND/OR  or In/Out operations with syncronization.
  365. *
  366. * RETURNS: The data read for read operations.
  367. */
  368. LOCAL UINT32 mpc107I2cRegRdWrMod
  369.     (
  370.     UINT32  ioControlFlag,  /* input/ouput control flag         */
  371.                                 /* 0, write                         */
  372.                                 /* 1, read                          */
  373.                                 /* 2, read/modify/write (ORing)     */
  374.                                 /* 3, read/modify/write (ANDing)    */
  375.                                 /* 4, read/modify/write (AND/ORing) */
  376.     UINT32  address,        /* address of device register       */
  377.     UINT32  wdata1,         /* data item 1 for read/write operation */
  378.     UINT32  wdata2          /* data item 2 for read/write operation */
  379.     )
  380.     {
  381.     UINT32 i2cTempData = 0;
  382.     if (ioControlFlag == MPC107_I2C_WRITE)  /* Write */
  383.         {
  384.         /*
  385.          * Data <wdata1> is to be written in
  386.          * the register specified by <address>
  387.          */
  388.        MPC107EUMBBARWRITE(address, wdata1);
  389.         }
  390.     else if (ioControlFlag == MPC107_I2C_READ) /* Read */
  391.         {
  392.         /* Data is read from the register  specified by <address> */
  393.         i2cTempData =MPC107EUMBBARREAD(address);
  394.         }
  395.     else if (ioControlFlag == MPC107_I2C_READ_OR_WRITE) /* Read OR Write */
  396.         {
  397.         /*
  398.          * Data <wdata1> is bitwise ORed with the data read
  399.          * from the register specified by <address>  and the
  400.          * resultant  data is written to the register
  401.          */
  402.         i2cTempData =MPC107EUMBBARREAD(address) | wdata1 ;
  403.         SYNC;
  404.         MPC107EUMBBARWRITE(address, i2cTempData);
  405.         }
  406.     else if (ioControlFlag == MPC107_I2C_READ_AND_WRITE)  /* Read AND Write */
  407.         {
  408.         /*
  409.          * Data <wdata1> is bitwise ANDed with the data read
  410.          * from the register specified by address  and the
  411.          * resultant  data is written to the  register
  412.          */
  413.         i2cTempData =MPC107EUMBBARREAD(address) & wdata1;
  414.         SYNC;
  415.         MPC107EUMBBARWRITE(address, i2cTempData);
  416.         }
  417.     else if (ioControlFlag == MPC107_I2C_READ_ANDOR_WRITE)/* Read ANDOR write */
  418.         {
  419.         /*
  420.          * Data <wdata1> is bitwise ANDed with the data read
  421.          * from the register specified by <address> and  data
  422.          * <wdata2> is bitwise ORed, and the resultant  data
  423.          * is written to the register
  424.          */
  425.         i2cTempData =MPC107EUMBBARREAD(address);
  426.         SYNC;
  427.         i2cTempData &= wdata1;
  428.         i2cTempData |= wdata2;
  429.         MPC107EUMBBARWRITE(address, i2cTempData);
  430.         }
  431.     SYNC;
  432.     return (i2cTempData);
  433.     }
  434. /***************************************************************************
  435. *
  436. * mpc107I2cDoOperation - i2c do operation
  437. *
  438. * The  purpose of this routine is to execute the operation as specified
  439. * by the passed command packet.
  440. *
  441. * RETURNS: N/A
  442. */
  443. LOCAL VOID mpc107I2cDoOperation
  444.     (
  445.     UINT32  deviceAddress, /* device I2C bus address */
  446.     MPC107_I2C_CMD_PCKT * pI2cCmdPacket /* pointer to command packet */
  447.     )
  448.     {
  449.     INT32  byteCount; /* byte counter */
  450.     INT32  statusVariable; /* local status variable */
  451.     UCHAR * pWriteData; /* pointer to write data buffer */
  452.     /* Command interface to stop.  This is for previous error exits. */
  453.     mpc107i2cCycleStop ();
  454.     if (pI2cCmdPacket->command == MPC107_I2C_READOP) /* read operation  */
  455.         {
  456.         statusVariable = 0;
  457.         for (byteCount = 0; byteCount < pI2cCmdPacket->nBytes; byteCount++)
  458.             {
  459.             /* Start cycle */
  460.             if ((mpc107i2cCycleStart ()) != 0)
  461.                 {
  462.                 statusVariable = MPC107_I2C_ERR_CYCLE_START;
  463.                 break;
  464.         }
  465.             /* Write the device address */
  466.             mpc107i2cCycleWrite (deviceAddress);
  467.             if ((mpc107i2cCycleAckIn ()) != 0)
  468.                 {
  469.                 statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  470.                 break;
  471.         }
  472.             /* Write the byte offset */
  473.             mpc107i2cCycleWrite (byteCount);
  474.             if ((mpc107i2cCycleAckIn ()) != 0)
  475.                 {
  476.                 statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  477.                 break;
  478.         }
  479.             /* Write the device address */
  480.             mpc107i2cCycleWrite (deviceAddress |
  481.                                     MPC107_I2C_DEVICE_READ_ENABLE);
  482.     if ((mpc107i2cCycleAckIn ()) != 0)
  483.                 {
  484.                 statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  485.                 break;
  486.         }
  487.             /* Read the data from the IIC interface */
  488.     mpc107i2cCycleRead ((UCHAR *)
  489.                                (pI2cCmdPacket->memoryAddress + byteCount));
  490.                 {
  491.                 statusVariable = MPC107_I2C_ERR_CYCLE_READ;
  492.                 break;
  493.         }
  494.             /* Generate the Stop Cycle */
  495.     mpc107i2cCycleStop () ;
  496.             }
  497.         /* update the caller's command packet with status of the operation */
  498.         pI2cCmdPacket->status = statusVariable;
  499.         }
  500.     /*
  501.      * write operation for each byte
  502.      * perform the byte write operation, a delay must be
  503.      * exercised following each byte write
  504.      */
  505.     if (pI2cCmdPacket->command == MPC107_I2C_WRITOP)
  506.         {
  507.         /* Initialize pointer to caller's write data buffer. */
  508.         pWriteData = (UCHAR *)pI2cCmdPacket->memoryAddress;
  509.         /* Write the specified number of bytes from the EEPROM. */
  510.         statusVariable = 0;
  511.         for (byteCount = 0; byteCount < pI2cCmdPacket->nBytes; byteCount++)
  512.             {
  513.             /* Generate the Start Cycle */
  514.             if ((mpc107i2cCycleStart ()) != 0)
  515.                 {
  516.                 statusVariable = MPC107_I2C_ERR_CYCLE_START;
  517.                 break;
  518.         }
  519.             /* Write the device address */
  520.             mpc107i2cCycleWrite (deviceAddress);
  521.             if ((mpc107i2cCycleAckIn ()) != 0)
  522.                {
  523.                statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  524.                break;
  525.        }
  526.             /* Write the byte offset */
  527.             mpc107i2cCycleWrite (byteCount);
  528.             if ((mpc107i2cCycleAckIn()) != 0)
  529.                {
  530.                statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  531.                break;
  532.        }
  533.             /* Write the device address */
  534.             mpc107i2cCycleWrite (deviceAddress);
  535.     if ((mpc107i2cCycleAckIn ()) != 0)
  536.                 {
  537.                 statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  538.                 break;
  539.         }
  540.             /* Write the data */
  541.     mpc107i2cCycleWrite (*(pWriteData + byteCount));
  542.     if ((mpc107i2cCycleAckIn ()) != 0)
  543.                 {
  544.                 statusVariable = MPC107_I2C_ERR_CYCLE_ACKIN;
  545.                 break;
  546.         }
  547.             /* Generate the Stop Cycle */
  548.             mpc107i2cCycleStop ();
  549.             }
  550.         /* update the caller's command packet with status of the operation */
  551.         pI2cCmdPacket->status = statusVariable;
  552.         }
  553.     }
  554. /***************************************************************************
  555. *
  556. * mpc107I2cCycleDelay() - delay for the specified amount of time (MS)
  557. *
  558. * This routine will delay for the specified amount of time by counting
  559. * decrementer ticks.
  560. *
  561. * This routine is not dependent on a particular rollover value for
  562. * the decrementer, it should work no matter what the rollover
  563. * value is.
  564. *
  565. * A small amount of count may be lost at the rollover point resulting in
  566. * the mpc107I2cCycleDelay() causing a slightly longer delay than requested.
  567. *
  568. * This routine will produce incorrect results if the delay time requested
  569. * requires a count larger than 0xffffffff to hold the decrementer
  570. * elapsed tick count.  For a System Bus Speed of 67 MHZ this amounts to
  571. * about 258 seconds.
  572. *
  573. * RETURNS: N/A
  574. */
  575. LOCAL void mpc107I2cCycleDelay
  576.     (
  577.     UINT        delay            /* length of time in MS to delay */
  578.     )
  579.     {
  580.     register UINT32  oldval;      /* decrementer value */
  581.     register UINT32  newval;      /* decrementer value */
  582.     register UINT32  totalDelta;  /* Dec. delta for entire delay period */
  583.     register UINT32  decElapsed;  /* cumulative decrementer ticks */
  584.     /* Calculate delta of decrementer ticks for desired elapsed time. */
  585.     totalDelta = ((MPC107_DEFAULT_BUS_CLOCK / 4) / 1000) * delay;
  586.     /*
  587.      * Now keep grabbing decrementer value and incrementing "decElapsed" until
  588.      * we hit the desired delay value.  Compensate for the fact that we may
  589.      * read the decrementer at 0xffffffff before the interrupt service
  590.      * routine has a chance to set in the rollover value.
  591.      */
  592.     decElapsed = 0;
  593.     oldval = mpc107GetDec ();
  594.     while (decElapsed < totalDelta)
  595.         {
  596.         newval = mpc107GetDec();
  597.         if ( MPC107_DELTA(oldval,newval) < 1000 )
  598.             decElapsed += MPC107_DELTA(oldval,newval);  /* no rollover */
  599.         else
  600.             if (newval > oldval)
  601.                 decElapsed += abs((INT32)oldval);  /* rollover */
  602.         oldval = newval;
  603.         }
  604.   }
  605. /***************************************************************************
  606. *
  607. * mpc107GetDec - read from the Decrementer register SPR22.
  608. *
  609. * This routine will read the contents the decrementer (SPR22)
  610. *
  611. * From a C point of view, the routine is defined as follows:
  612. *
  613. * UINT32 mpc107GetDec()
  614. *
  615. * RETURNS: value of SPR22 (in r3)
  616. */
  617. LOCAL UINT32 mpc107GetDec(void)
  618.     {
  619.     return vxDecGet ();
  620.     }