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

VxWorks

开发平台:

C/C++

  1. /* mpc107Msg.c - MPC107 Message Unit  support */
  2. /* Copyright 1996-2000 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01a,11sep00,rcs  fix include paths
  8. 01a,26jun00,bri written
  9. */
  10. /*
  11. DESCRIPTION
  12. This module contains routines for the Message Unit interface of MPC107 .
  13. The Message Unit (MU) of MPC107  facilitates communications between
  14. the host processor and peripheral processors in a multiprocessor system .
  15. The Message Unit consists of generic messages registers, doorbell registers
  16. and an an I2O-compliant interface.
  17. .SH INITIALIZATION
  18. If the processor associated with this MPC107 is to be configured as the
  19. host processor ,the Message Unit Interface is initialized by calling
  20. the routine mpc107MsgMessageHostInit().
  21. If the processor associated with this MPC107 is  to be configured as
  22. as a peripheral processor the Message Unit Interface is initialized
  23. by calling the routine mpc107MsgMessagePeripheralInit() .
  24. The user has to specify to which interrupt of the processor these
  25. interrupts are connected.
  26. */
  27. /* includes */
  28. #include "vxWorks.h"
  29. /* #include "config.h" */
  30. #include "sysLib.h"
  31. #include "stdlib.h"
  32. #include "errno.h"
  33. #include "errnoLib.h"
  34. #include "intLib.h"
  35. #include "memLib.h"
  36. #include "drv/multi/mpc107.h"
  37. #include "drv/multi/mpc107Msg.h"
  38. #include "drv/intrCtl/mpc107Epic.h"
  39. /* globals */
  40. UINT32 pciBaseAddr = 0;  /* PCI base address for oubound interface */
  41. /* static file scope locals */
  42. BOOL intHandlerInbound = FALSE;  /* Flag for Inbound Interrupt Handler  */
  43. BOOL intHandlerOutbound = FALSE; /* Flag for Outbound Interrupt Handler */
  44. /* forward Declarations */
  45. void mpc107MessageOutInt (void);
  46. void mpc107MessageInInt (void);
  47. LOCAL void  mpc107MsgWrite (UINT32 pciBar, UINT32 messageRegNum,
  48.                             UINT32 message);
  49. LOCAL ULONG  mpc107MsgRead (UINT32 pciBar, UINT32 messageRegNum );
  50. LOCAL UINT32  mpc107MsgRegMod (UINT32 pciBar, UINT32 ioControlFlag,
  51.                                 UINT32 address, UINT32 wdata1, UINT32 wdata2);
  52. /***************************************************************************
  53. *
  54. * mpc107MsgMessageHostInit -  initializaion  of Message Unit (Host)
  55. *
  56. * This routine initializes the Message Unit for multiprocessor communications
  57. * using  Inbound/Outbound Message Registers and Inbound/Outbound Doorbell
  58. * Registers for the host interface
  59. *
  60. * This routine should be called once during hardware initialization .
  61. *
  62. * This routine should  called before using the Message Unit for Multiprocessor
  63. * communications using  Inbound/Outbound Message Registers  and
  64. * Inbound/Outbound  Doorbell Registers  for the host interface
  65. *
  66. * RETURNS: N/A
  67. */
  68. void mpc107MsgMessageHostInit(void)
  69.     {
  70.     if (!intHandlerInbound) /* If Interrupt handler is not hooked */
  71.         {
  72.         intConnect ((VOIDFUNCPTR*)MPC107_EPIC_MU_INT_VECT,
  73.                                    mpc107MessageInInt, 0);
  74.         /*
  75.          * Setting Flag indicating that Inbound
  76.          * Interrupt handler is hooked
  77.          */
  78.         intHandlerInbound = TRUE;
  79.         /*
  80.          * Enable the Interrupts in the Inbound Message
  81.          * Interrupt Mask Register
  82.          */
  83.         mpc107MsgRegMod (0x0, MPC107_MSG_READ_OR_WRITE, MPC107_MSG_I2O_IMIMR,
  84.                          !(MPC107_MSG_I2O_IM0IM | MPC107_MSG_I2O_IM1IM |
  85.                            MPC107_MSG_I2O_IDIM | MPC107_MSG_I2O_MCIM), 0);
  86.         }
  87.     }
  88. /***************************************************************************
  89. *
  90. * mpc107MsgMessagePeripheralInit - initialization of Message Unit (Peripheral)
  91. *
  92. * This routine initializes the Message Unit for multiprocessor communications
  93. * using Inbound/Outbound Message Registers and Inbound/Outbound Doorbell
  94. * Registers  with MPC107 as a peripheral processor
  95. *
  96. * This routine should  called before using the Message Unit for Multiprocessor
  97. * communications using Inbound/Outbound Message Registers  and
  98. * Inbound/Outbound  Doorbell Registers as a peripheral interface
  99. *
  100. * RETURNS: N/A
  101. */
  102. void mpc107MsgMessagePeripheralInit (void )
  103.     {
  104.     if (!intHandlerOutbound)
  105.         {
  106.         /*
  107.          * The PCI base Address  should be obtained
  108.          * after the PCI auto Config  and assigned to
  109.          * the variable <pciBaseAddr>
  110.          */
  111.         pciBaseAddr = MPC107_PCSRBAR_VAL;
  112.         /*
  113.          * The ISR handlers should be hooked here if
  114.          * it is not already hooked
  115.          */
  116.         intConnect ((VOIDFUNCPTR*)MPC107_EPIC_MU_INT_VECT,
  117.                                mpc107MessageOutInt, 0);
  118.         intHandlerOutbound = TRUE;
  119.         /*
  120.          * Enable the Interrupts in the Outbound Message
  121.          * Interrupt Mask Register
  122.          */
  123.         mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ_OR_WRITE,
  124.                          MPC107_MSG_I2O_PCI_OMIMR, !(MPC107_MSG_I2O_OM0IM |
  125.                          MPC107_MSG_I2O_OM1IM | MPC107_MSG_I2O_ODIM ), 0);
  126.         }
  127.     }
  128. /***************************************************************************
  129. *
  130. * mpc107MsgExtDoorbellInit -  initialization of Extended Doorbell Registers
  131. *
  132. * This routine initializes the Message Unit so that Extended Doorbell
  133. * Registers can be used for communication in a  multiprocessor configuration
  134. *
  135. * This routine should be called before using the Extended Doorbell Registers
  136. * for multiprocessor communication
  137. *
  138. * If the External Doorbell registers are  used for multiprocessor
  139. * communication, then the rest of the Message Unit should not be used
  140. * (or enabled).
  141. *
  142. * RETURNS: OK, or ERROR if the specified interrupt type <cpuIntA> is
  143. * not correct.
  144. */
  145. STATUS mpc107MsgExtDoorbellInit
  146.     (
  147.     UINT32 cpuIntA /* Whether message is for generating INTA (zero) */
  148.                         /* or CPU INT (one)*/
  149.     )
  150.     {
  151.     if (cpuIntA == MPC107_MSG_INTAGEN)
  152.         {
  153.         /*
  154.          * Disable the CPU0 Interrupt  and Enable the INTA Interrupt
  155.          * in the Extended Door Bell Mask Register
  156.          */
  157.         mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ_ANDOR_WRITE,
  158.                          MPC107_MSG_EDBSR, ~(MPC107_MSG_EDBMR_INTAIM_BIT),
  159.                          MPC107_MSG_EDBMR_C0IM_BIT);
  160.         }
  161.     else if (cpuIntA == MPC107_MSG_CP0GEN)
  162.         {
  163.         /*
  164.          * Enable the CPU0 Interrupt  and Disable the INTA Interrupt
  165.          * in the Extended Door Bell Mask Register
  166.          */
  167.         mpc107MsgRegMod (0x0, MPC107_MSG_READ_ANDOR_WRITE,
  168.                          MPC107_MSG_EDBSR,~(MPC107_MSG_EDBMR_C0IM_BIT),
  169.                          MPC107_MSG_EDBMR_INTAIM_BIT);
  170.         }
  171.     else
  172.         {
  173.         errnoSet (EINVAL);
  174.         return (ERROR);
  175.         }
  176.     /*
  177.      * Disable the Interrupts in the
  178.      * Inbound Message Interrupt Mask Register
  179.      */
  180.     mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ_OR_WRITE,
  181.                      MPC107_MSG_I2O_IMIMR, MPC107_MSG_I2O_IM0IM |
  182.                      MPC107_MSG_I2O_IM1IM | MPC107_MSG_I2O_IDIM |
  183.                      MPC107_MSG_I2O_MCIM, 0);
  184.     return (OK);
  185.     }
  186. /***************************************************************************
  187. *
  188. * mpc107MsgMessageWrite  -  write to Message Registers
  189. *
  190. * This routine is used for writing data to the Inbound /Out Bound
  191. * Message Registers.
  192. *
  193. * A remote processor can write a 32 bit message to the Inbound Message Register
  194. * which inturn generates an interrupt (INT to assert) to the local processor
  195. *
  196. * The local processor can write a 32 bit message to the Outbound Message
  197. * Register which in turn  causes the outbound interrupt signal INTA to be
  198. * asserted.
  199. *
  200. * RETURNS: OK, or ERROR if  <inOutBound> is  neither Inbound nor Outbound,
  201. * and  <messageRegNum> is not a valid register.
  202. */
  203. STATUS mpc107MsgMessageWrite
  204.     (
  205.     UINT32  inOutBound,    /* Inbound or Outbound Message Register */
  206.     UINT32  messageRegNum, /* register Number */
  207.     UINT32  message        /* message to be sent */
  208.     )
  209.     {
  210.     ULONG regNum;  /* register number */
  211.     if (inOutBound == MPC107_MSG_INBOUND) /* Inbound Registers */
  212.         {
  213.         if (messageRegNum == MPC107_MSG_REGISTER0)
  214.             {
  215.             regNum = MPC107_MSG_IMR0; /* Inbound Message Register 0 */
  216.             }
  217.         else if (messageRegNum == MPC107_MSG_REGISTER1)
  218.             {
  219.             regNum = MPC107_MSG_IMR1;  /* InBound Message Register 1 */
  220.             }
  221.         else
  222.             {
  223.             errnoSet (EINVAL);
  224.             return (ERROR);            /* Invalid register */
  225.             }
  226.         mpc107MsgRegMod (0x0, MPC107_MSG_WRITE, regNum, message, 0);
  227.         }
  228.     else if (inOutBound == MPC107_MSG_OUTBOUND) /* Outbound Registers */
  229.         {
  230.         if (messageRegNum == MPC107_MSG_REGISTER0)
  231.             {
  232.             regNum = MPC107_MSG_OMR0; /* Outbound Message Register 0 */
  233.             }
  234.         else if (messageRegNum == MPC107_MSG_REGISTER1)
  235.             {
  236.             regNum = MPC107_MSG_OMR1; /* Outbound Message Register 1 */
  237.             }
  238.         else
  239.             {
  240.             errnoSet (EINVAL);
  241.             return (ERROR);            /* Invalid register */
  242.             }
  243.         /* Write the message to the specified register */
  244.         mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE, regNum, message, 0);
  245.         }
  246.     else
  247.         {
  248.         errnoSet (EINVAL);
  249.         return (ERROR);            /* Invalid register */
  250.         }
  251.         return (OK);
  252.     }
  253. /***************************************************************************
  254. *
  255. * mpc107MsgMessageRead - read from Message Registers
  256. *
  257. * This routine is used for reading Inbound/Outbound Message registers .
  258. *
  259. * The Inbound Message register is read  by the local processor .
  260. * The Outbound Message register is read by the remote processor
  261. *
  262. * RETURNS: OK, or ERROR if  <inOutBound> is  neither Inbound nor Outbound,
  263. * and  <messageRegNum> is not a valid register.
  264. */
  265. STATUS mpc107MsgMessageRead
  266.     (
  267.     UINT32  inOutBound,    /* Inbound or Outbound Message Register */
  268.     UINT32  messageRegNum, /* register Number */
  269.     UINT32 * pMessageRead   /* pointer to the buffer to read message */
  270.     )
  271.     {
  272.     ULONG  regNum; /* register */
  273.     if (inOutBound == MPC107_MSG_INBOUND) /* Inbound registers */
  274.         {
  275.         if (messageRegNum == MPC107_MSG_REGISTER0)
  276.             {
  277.             regNum = MPC107_MSG_IMR0; /* Inbound Message Register 0 */
  278.             }
  279.         else if (messageRegNum == MPC107_MSG_REGISTER1)
  280.             {
  281.             regNum = MPC107_MSG_IMR1;  /* InBound Message Register 1 */
  282.             }
  283.         else
  284.             {
  285.             errnoSet (EINVAL);
  286.             return (ERROR);            /* Invalid register */
  287.             }
  288.         * (UINT32 *)pMessageRead  = mpc107MsgRegMod (0x0, MPC107_MSG_READ,
  289.                                                      regNum, 0, 0);
  290.         }
  291.     else if (inOutBound == MPC107_MSG_OUTBOUND) /* Outbound registers */
  292.         {
  293.         if (messageRegNum == MPC107_MSG_REGISTER0)
  294.             {
  295.             regNum = MPC107_MSG_OMR0; /* Outbound Message Register 0 */
  296.             }
  297.         else if (messageRegNum == MPC107_MSG_REGISTER1)
  298.             {
  299.             regNum = MPC107_MSG_OMR1;  /* Outbound Message Register 1 */
  300.             }
  301.         else
  302.             {
  303.             errnoSet (EINVAL);
  304.             return (ERROR);            /* Invalid register */
  305.             }
  306.         * (UINT32 *)pMessageRead = mpc107MsgRegMod (pciBaseAddr,MPC107_MSG_READ,
  307.                                                     regNum, 0, 0);
  308.         }
  309.     else
  310.         {
  311.         errnoSet (EINVAL);
  312.         return (ERROR);            /* Invalid register */
  313.         }
  314.     /* Read the message from the specified register */
  315.     * (UINT32 *)pMessageRead  = mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ,
  316.                                                  regNum, 0, 0);
  317.     return (OK);
  318.     }
  319. /***************************************************************************
  320. *
  321. * mpc107MsgDoorbellWrite -  write to  Doorbell Registers
  322. *
  323. * This routine is used for writing data to the Inbound /Outbound
  324. * Doorbell Registers
  325. *
  326. * A remote processor can set a bit in the Inbound Doorbell Register from
  327. * the PCI bus which inturn generates an interrupt (INT to assert) to the
  328. * local processor. If the Machine Check bit is set then a machine
  329. * check condition is conveyed to the local processor .
  330. *
  331. * The local processor can write to the Outbound Doorbell Register , which
  332. * causes the outbound interrupt signal INTA to be asserted, thus interrupting
  333. * the remote processor.
  334. *
  335. * RETURNS: OK, or ERROR if  <inOutBound> is  neither Inbound nor Outbound .
  336. */
  337. STATUS mpc107MsgDoorbellWrite
  338.     (
  339.     UINT32  inOutBound,   /* whether Inbound or Outbound Message Register */
  340.     UINT32  message,      /* message to be sent */
  341.     UINT32  machineCheck  /* machine Check Bit (zero or one ) This is */
  342.                               /* valid only for Inbound Door Bell */
  343.                               /* Register */
  344.     )
  345.     {
  346.     ULONG regNum;
  347.     if (inOutBound == MPC107_MSG_INBOUND) /* Inbound Doorbell Register */
  348.         {
  349.         regNum = MPC107_MSG_IDBR;
  350.         message |= (machineCheck << MPC107_MSG_IDBR_MC_SHIFT);
  351.         /* Write the message to the specified register */
  352.         mpc107MsgRegMod (0x0, MPC107_MSG_WRITE, regNum, message, 0);
  353.         }
  354.     else if (inOutBound == MPC107_MSG_OUTBOUND) /* Outbound Doorbell Register */
  355.         {
  356.         regNum = MPC107_MSG_ODBR;
  357.         message |= MPC107_MSG_ODBR_DATA_MASK;
  358.         /* Write the message to the specified register */
  359.         mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE, regNum, message, 0);
  360.         }
  361.     else
  362.         {
  363.         errnoSet (EINVAL);
  364.         return (ERROR);
  365.         }
  366.         return (OK);
  367.     }
  368. /***************************************************************************
  369. *
  370. * mpc107MsgDoorbellRead -  read  from  Doorbell Registers
  371. *
  372. * This routine is used for reading data from the Inbound / Outbound
  373. * Doorbell registers
  374. *
  375. * The Inbound Doorbell register is read  by the local proceesor  and the
  376. * bits set in the register are cleared by writing a 1 those bits .
  377. *
  378. * The Outbound Doorbell Register is read by the remote processor  and  the
  379. * bits set in the register are cleared by writing a 1 those bits .
  380. *
  381. * RETURNS: OK, or ERROR if  <inOutBound> is  neither Inbound nor Outbound.
  382. */
  383. STATUS mpc107MsgDoorbellRead
  384.     (
  385.     UINT32 inOutBound,       /* whether Inbound or Outbound Message Reg */
  386.     UINT32 *pMsgDoorbellRead /* data read */
  387.     )
  388.     {
  389.     ULONG       tempReadData; /* data read from the register */
  390.     if (inOutBound == MPC107_MSG_INBOUND) /* Inbound Doorbell Register */
  391.         {
  392.         /* read the inbound doorbell register */
  393.         tempReadData = mpc107MsgRegMod (0x0, MPC107_MSG_READ,
  394.                                              MPC107_MSG_IDBR, 0, 0);
  395.         *(UINT32 *)pMsgDoorbellRead = tempReadData;
  396.         /* clear the bits set in the door bell registers */
  397.         mpc107MsgRegMod (0x0, MPC107_MSG_WRITE, MPC107_MSG_IDBR,
  398.                                                 tempReadData, 0);
  399.         }
  400.     else if (inOutBound == MPC107_MSG_OUTBOUND) /* Outbound Doorbell Register */
  401.         {
  402.         /* read the Outbound doorbell register */
  403.         tempReadData = mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ,
  404.                                                      MPC107_MSG_ODBR, 0, 0);
  405.         *(UINT32 *)pMsgDoorbellRead = tempReadData;
  406.         /* clear the bits set in the door bell registers */
  407.         mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE, MPC107_MSG_ODBR,
  408.                          tempReadData, 0);
  409.         }
  410.     else
  411.         {
  412.         errnoSet (EINVAL);
  413.         return (ERROR);
  414.         }
  415.         return (OK);
  416.     }
  417. /***************************************************************************
  418. *
  419. * mpc107MsgExtDoorbellSetWrite - write to Extended Doorbell Write1 Set Register
  420. *
  421. * This routine is used for writing data to Extended Doorbell Write 1
  422. * Set register  causing an interrupt to be generated .
  423. *
  424. * RETURNS: OK, or ERROR if the specified interrupt type <cpuIntA> is
  425. * not correct.
  426. */
  427. STATUS mpc107MsgExtDoorbellSetWrite
  428.     (
  429.     UINT32 message, /* message to be sent */
  430.     UINT32 cpuIntA  /* whether message is for generating INTA (zero) */
  431.                          /* or CPU Interrupt (One) */
  432.     )
  433.     {
  434.     if (cpuIntA == MPC107_MSG_INTAGEN)
  435.         {
  436.         message = ((message  & MPC107_MSG_GENERAL_LSB_MSK )
  437.                             << MPC107_MSG_EDBW1S_INTA_SHIFT)
  438.                              & MPC107_MSG_EDBW1S_INTA_MSK ;
  439.         }
  440.     else if (cpuIntA == MPC107_MSG_CP0GEN)
  441.         {
  442.         message = ((message  & MPC107_MSG_GENERAL_LSB_MSK )
  443.                             << MPC107_MSG_EDBW1S_CP0_SHIFT)
  444.                              & MPC107_MSG_EDBW1S_CP0_MSK ;
  445.         }
  446.     else
  447.         {
  448.         errnoSet (EINVAL);
  449.         return (ERROR);
  450.         }
  451.     /* Write  the  data to  Extended Doorbell Write 1 Register  */
  452.     mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE, MPC107_MSG_EDBW1S, 0, 0);
  453.     return (OK);
  454.     }
  455. /***************************************************************************
  456. *
  457. * mpc107MsgExtDoorbellClrRead - read Extended Doorbell Write1 Clear Register
  458. *
  459. * This routine is used for reading data from the  Extended Doorbell Write 1
  460. * Clear Register.This register is cleared after reading the data
  461. *
  462. * RETURNS: The data read is returned
  463. */
  464. ULONG mpc107MsgExtDoorbellClrRead (void)
  465.     {
  466.     ULONG tempData ;
  467.     /* Read the data  from Extended Door Bell Write1 Clear Register */
  468.     tempData = mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE,
  469.                                              MPC107_MSG_EDBW1C, 0, 0);
  470.     /* Clear all the bits in the Extended Doorbell Write1 Clear Register */
  471.     mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE,
  472.                                   MPC107_MSG_EDBW1C, tempData, 0);
  473.     return (tempData);
  474.     }
  475. /***************************************************************************
  476. *
  477. * mpc107MsgI2oInit -  initialization  of I20 Interface of Message Unit
  478. *
  479. * This routine sets up the size of the inbound and outbound FIFOs .
  480. * Memory for messages is allocated and the inbound Free Fifo/Outbound Free FIFO
  481. * are initialized with the Message Frame Addresses .
  482. *
  483. * RETURNS: OK, or ERROR if memory allocation has failed.
  484. */
  485. STATUS mpc107MsgI2oInit (void)
  486.     {
  487.     UINT32 * pI2oQbaseAddr;        /* pointer to Circular queue */
  488.     UINT32  tempI2oData;          /* temporary data */
  489.     UINT32  i2oQueueSize;         /* queue size */
  490.     UINT32 * pInboundFreeListBase; /* pointer to Inbound Free List FIFO */
  491.     UINT32 * pOutboundFreeListBase;/* pointer to Outbound Free List FIFO */
  492.     UINT32  tempIndex;            /* index */
  493.     UINT32  tempMfaAddress;       /* temporary MFA address */
  494.     /* Initiailze the Message Unit I20 Control Register */
  495.     mpc107MsgRegMod (0x0, MPC107_MSG_WRITE, MPC107_MSG_I2O_MUCR,
  496.                           MPC107_MSG_I2O_MUCR_DEFAULT, 0);
  497.     tempI2oData = mpc107MsgRegMod (0x0, MPC107_MSG_READ,
  498.                                    MPC107_MSG_I2O_MUCR , 0, 0)
  499.                                    & MPC107_MSG_I2O_CQS;
  500.     switch (tempI2oData & MPC107_MSG_I2O_CQS)
  501.         {
  502.         case MPC107_MSG_I2O_CQS_16K:
  503.             /* FIFO size is 4 K  entries (16 K Bytes) */
  504.             i2oQueueSize = MPC107_MSG_I2O_CQS_16K_SIZE;
  505.             break;
  506.         case MPC107_MSG_I2O_CQS_32K:
  507.              /* FIFO size is 8 K  entries (32 K Bytes) */
  508.             i2oQueueSize = MPC107_MSG_I2O_CQS_32K_SIZE;
  509.             break;
  510.         case MPC107_MSG_I2O_CQS_64K:
  511.             /* FIFO size is 16 K  entries (64 K Bytes) */
  512.             i2oQueueSize = MPC107_MSG_I2O_CQS_64K_SIZE;
  513.             break;
  514.         case MPC107_MSG_I2O_CQS_128K:
  515.              /* FIFO size is 32 K  entries (128 K Bytes) */
  516.              i2oQueueSize = MPC107_MSG_I2O_CQS_128K_SIZE;
  517.             break;
  518.         case MPC107_MSG_I2O_CQS_256K:
  519.             /* FIFO size is 64 K  entries (256 K Bytes) */
  520.             i2oQueueSize = MPC107_MSG_I2O_CQS_256K_SIZE;
  521.             break;
  522.         default:
  523.             /* FIFO size is 4 K  entries (16 K Bytes) */
  524.             i2oQueueSize = MPC107_MSG_I2O_CQS_16K_SIZE;
  525.             break;
  526.         }
  527.     /* Allocate memory for the circular queues */
  528.     pI2oQbaseAddr = (UINT32 *)memalign (MPC107_MSG_I2O_MUCR_QBAR_ALIGN,
  529.                              sizeof(UINT32) * i2oQueueSize * 4 );
  530.     if ((pI2oQbaseAddr) != 0 )  /* If memory allocated */
  531.         {
  532.         /* Initialize the Queue Base Address Register */
  533.         mpc107MsgRegMod (0x0, MPC107_MSG_WRITE, MPC107_MSG_I2O_QBAR,
  534.                         (UINT32)pI2oQbaseAddr, 0);
  535.         /* Pointer to Inbound Free List FIFO base */
  536.         (UINT32 *)pInboundFreeListBase  = (UINT32 *) (pI2oQbaseAddr);
  537.         /* Pointer to Outbound Free List FIFO base */
  538.         (UINT32 *)pOutboundFreeListBase  =(UINT32 *) (pI2oQbaseAddr +
  539.                                                     ((i2oQueueSize) *3));
  540.         /* Initialize the In Bound Free FIFO list with the MFAs  */
  541.         for (tempIndex = 0; tempIndex <i2oQueueSize; tempIndex++)
  542.             {
  543.             tempMfaAddress = ((UINT32)malloc(sizeof(UINT32)) *
  544.                                     MPC107_MSG_I2O_MFRAME_SIZE);
  545.             if ((tempMfaAddress) != 0) /* If memory is allocated */
  546.                 {
  547.                 *((UINT32 *) (pInboundFreeListBase + tempIndex)) =
  548.                                                      tempMfaAddress;
  549.                 }
  550.             else
  551.                 return (ERROR);
  552.             }
  553.         /* Initialize the Out Bound Free FIFO list with the MFAs  */
  554.         for (tempIndex = 0; tempIndex <i2oQueueSize; tempIndex++)
  555.             {
  556.             tempMfaAddress = ((UINT32)malloc(sizeof(UINT32)) *
  557.                                            MPC107_MSG_I2O_MFRAME_SIZE);
  558.             if ((tempMfaAddress) != 0) /* If memory is allocated */
  559.                 {
  560.                 *((UINT32 *) (pOutboundFreeListBase + tempIndex)) =
  561.                                                        tempMfaAddress;
  562.                 }
  563.             else
  564.                 return (ERROR);
  565.             }
  566.         }
  567.         else
  568.             return (ERROR);
  569.     return (OK);
  570.     }
  571. /***************************************************************************
  572. *
  573. * mpc107MsgI2oInboundRead -  read from I2O Inbound Interface
  574. *
  575. * This routine is used by the host processor to read messages posted to
  576. * the I2O Outbound Interface by the external PCI master
  577. *
  578. * RETURNS: N/A
  579. */
  580. void mpc107MsgI2oInboundRead (void)
  581.     {
  582.     UINT32 ** ppTempMfa;     /* pointer to Message Frame pointer */
  583.     UINT32 * pTempReadMfa; /* pointer to Message Frame */
  584.     ULONG  tempIndex;     /* index */
  585.     UINT32  pBuf[MPC107_MSG_I2O_MFRAME_SIZE]; /* buffer for read data */
  586.     /* Read Inbound Post Fifo Tail Pointer Register (IPTPR) to get MFA */
  587.     ppTempMfa = (UINT32 **)mpc107MsgRegMod (0, MPC107_MSG_READ,
  588.                                                MPC107_MSG_I2O_IPTPR, 0, 0);
  589.     pTempReadMfa = *ppTempMfa;
  590.     /* Read the messages */
  591.     for (tempIndex = 0; tempIndex < MPC107_MSG_I2O_MFRAME_SIZE; tempIndex++)
  592.         {
  593.         *((UINT32 *)(pBuf + tempIndex)) =
  594.                             *((UINT32 *)(pTempReadMfa + tempIndex));
  595.         }
  596.     /* Increment the value in Inbound Post FIFO Tail Pointer Reg (IPTPR) */
  597.     mpc107MsgRegMod (0, MPC107_MSG_WRITE, MPC107_MSG_I2O_IPTPR,
  598.                                          (UINT32)(ppTempMfa + 1) , 0);
  599.     /*
  600.      * Return the message to the Inbound Free List Fifo  by
  601.      * writing the MFAs to Inbound Free Fifo Head Pointer Reg
  602.      */
  603.     mpc107MsgRegMod (0, MPC107_MSG_WRITE, MPC107_MSG_I2O_IFHPR,
  604.                                          (UINT32)ppTempMfa, 0);
  605.     }
  606. /***************************************************************************
  607. *
  608. * mpc107MsgI2oOutboundWrite -  write to  I20 Outbound interface
  609. *
  610. * This routine is used by the host processor  to write messages to
  611. * the I2O Outbound Interface .
  612. *
  613. * The  host processor  obtains a free MFA  and  posts  the messages.
  614. *
  615. * RETURNS: N/A
  616. */
  617. void mpc107MsgI2oOutboundWrite
  618.     (
  619.     UINT32 * pBuf  /* pointer to message  to be written */
  620.                       /* to Outbound I2O interface */
  621.     )
  622.     {
  623.     UINT32 ** ppTempMfa;    /* pointer to Message Frame pointer */
  624.     UINT32 ** ppTempOfhpr;  /* pointer to Message Frame pointer */
  625.     UINT32 * pTempWriteMfa;/* pointer to Message Frame */
  626.     ULONG  tempIndex;    /* index */
  627.     /* Read Outbound Free Fifo Tail Pointer Reg (OFTPR)  to Get MFA */
  628.     ppTempMfa = (UINT32 **) mpc107MsgRegMod (0, MPC107_MSG_READ,
  629.                                                 MPC107_MSG_I2O_OFTPR, 0, 0);
  630.     /* Read Outbound Free Fifo Head Pointer Register (OFHPR)  to Get MFA */
  631.     ppTempOfhpr = (UINT32 **) mpc107MsgRegMod (0, MPC107_MSG_READ,
  632.                                                   MPC107_MSG_I2O_OFHPR, 0, 0);
  633.     if (ppTempMfa != ppTempOfhpr) /* If the FIFO is not empty */
  634.         {
  635.         pTempWriteMfa = *ppTempMfa;
  636.         /* Write the message in the Message Frame */
  637.         for (tempIndex = 0; tempIndex < MPC107_MSG_I2O_MFRAME_SIZE; tempIndex++)
  638.             {
  639.             *((UINT32 *)(pTempWriteMfa + tempIndex)) =
  640.                                      *((UINT32 *)(pBuf+ tempIndex));
  641.             }
  642.         /* Write the MFA to Outbound Post Fifo Head Pointer Reg OPHPR */
  643.         mpc107MsgRegMod (0, MPC107_MSG_WRITE,
  644.                             MPC107_MSG_I2O_OPHPR,(UINT32) ppTempMfa, 0);
  645.         }
  646.     }
  647. /***************************************************************************
  648. *
  649. * mpc107MsgI2oOutboundRead -  read  from  I20 Outbound interface
  650. *
  651. * This routine is used by the external PCI master to read messages posted to
  652. * the I2O Outbound Interface  by the host processor .
  653. *
  654. * RETURNS: N/A
  655. */
  656. void mpc107MsgI2oOutboundRead (void)
  657.     {
  658.     UINT32 **ppTempMfa;    /* pointer to Message Frame pointer */
  659.     UINT32 *pTempReadMfa;  /* pointer to Message Frame */
  660.     ULONG tempIndex;       /* index  */
  661.     UINT32 pBuf[MPC107_MSG_I2O_MFRAME_SIZE]; /* buffer to read data */
  662.     /*
  663.      * Read Outbound Fifo Queue Port Register (OFQPR)  to get the MFA
  664.      * While FIFO is not empty
  665.      */
  666.      while((ppTempMfa = (UINT32 **)mpc107MsgRegMod(pciBaseAddr, MPC107_MSG_READ,
  667.                                       MPC107_MSG_I2O_PCI_OFQPR, 0, 0)) !=
  668.                                       (UINT32 **)MPC107_MSG_I2O_FIFO_EMPTY)
  669.         {
  670.         /* Read the messages  */
  671.         pTempReadMfa  = *ppTempMfa;
  672.         for (tempIndex = 0; tempIndex < MPC107_MSG_I2O_MFRAME_SIZE; tempIndex++)
  673.             {
  674.             *((UINT32 *)(pBuf+ tempIndex)) =
  675.                       *((UINT32 *)(pTempReadMfa + tempIndex));
  676.             /* Write the MFA to Outbound Fifo Queue Port Register (OFQPR) */
  677.             mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE,
  678.                             MPC107_MSG_I2O_PCI_OFQPR,(UINT32) ppTempMfa, 0);
  679.             }
  680.         }
  681.     }
  682. /***************************************************************************
  683. *
  684. * mpc107MsgI2oInboundWrite -  write  to  I20 Inbound interface
  685. *
  686. * This routine is used by the external PCI master for writing messages to
  687. * the I2O Inbound Interface .
  688. *
  689. * The external PCI master obtains a free MFA  and  posts  the messages.
  690. *
  691. * RETURNS: OK, or ERROR if free MFAs are not available.
  692. */
  693. STATUS mpc107MsgI2oInboundWrite
  694.     (
  695.     UINT32 * pBuf  /* pointer to message to be written to the Inbound */
  696.                       /* I2O interface */
  697.     )
  698.     {
  699.     UINT32 ** ppTempMfa;      /* pointer to Message Frame pointer */
  700.     UINT32 * pTempWriteMfa;  /* pointer to Message Frame  */
  701.     ULONG  tempIndex;      /* index */
  702.     /* Read Inbound Fifo Queue Port Register  to Get MFA */
  703.     ppTempMfa = (UINT32 **)mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ,
  704.                                             MPC107_MSG_I2O_PCI_IFQPR, 0, 0);
  705.     /* Check to see if the Inbound interface has free MFAs  */
  706.     if (ppTempMfa == (UINT32 **)MPC107_MSG_I2O_NO_FREE_MFA)
  707.         {
  708.         return(ERROR) ;  /* No free MFAs */
  709.         }
  710.     else  /* Free MFAs are available */
  711.         {
  712.         pTempWriteMfa =  *(ppTempMfa) ;
  713.         /* Write the message in the Message Frame */
  714.         for (tempIndex = 0; tempIndex < MPC107_MSG_I2O_MFRAME_SIZE;
  715.                             tempIndex++)
  716.             {
  717.             *(UINT32 *)(pTempWriteMfa + tempIndex) =
  718.                                       *(UINT32 *)(pBuf + tempIndex);
  719.             }
  720.         /* Write the MFA to the Inbound Fifo Queuue Port Register  */
  721.         mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_WRITE,
  722.                          MPC107_MSG_I2O_PCI_IFQPR, (UINT32)ppTempMfa, 0);
  723.         return (OK);
  724.         }
  725.    }
  726. /***************************************************************************
  727. *
  728. * mpc107MessageInInt - ISR for interrupts from the Inbound Message Unit
  729. *
  730. * This routine services the Inbound Message,Inbound Doorbell and
  731. * Inbound I2O interrupts .
  732. *
  733. * RETURNS: N/A
  734. */
  735. void mpc107MessageInInt (void)
  736.     {
  737.      ULONG  tempStatusData; /* interrupt status register contents */
  738.      ULONG  tempMaskData;   /* interrupt Mask register contents */
  739.      UINT32  pMessageRead;   /* data read */
  740.      /* Read the Inbound Message Interrupt Status Register */
  741.     tempStatusData = mpc107MsgRegMod (0x0,MPC107_MSG_READ,
  742.                                           MPC107_MSG_I2O_IMISR, 0, 0);
  743.     /* Read the Inbound Message Interrupt Mask Register */
  744.     tempMaskData = mpc107MsgRegMod (0x0, MPC107_MSG_READ ,
  745.                                          MPC107_MSG_I2O_IMIMR, 0, 0);
  746.     /* Inbound Message 0 Interrupt */
  747.     if ((tempStatusData & MPC107_MSG_I2O_IM0I & MPC107_MSG_I2O_IM0IM) != 0)
  748.         {
  749.         mpc107MsgMessageRead (MPC107_MSG_INBOUND ,
  750.                               MPC107_MSG_REGISTER0 , &pMessageRead);
  751.         }
  752.     /* Inbound Message 1 Interrupt */
  753.     if ((tempStatusData & MPC107_MSG_I2O_IM1I & MPC107_MSG_I2O_IM1IM) !=0 )
  754.         {
  755.          mpc107MsgMessageRead (MPC107_MSG_INBOUND ,
  756.                                MPC107_MSG_REGISTER1 , &pMessageRead);
  757.         }
  758.     /* Inbound Doorbell  Interrupt */
  759.     if ((tempStatusData & MPC107_MSG_I2O_IDI & MPC107_MSG_I2O_IDIM) !=0 )
  760.         {
  761.         mpc107MsgDoorbellRead (MPC107_MSG_INBOUND,&pMessageRead);
  762.         }
  763.     /* Inbound Doorbell  Register Machine Check */
  764.     if ((tempStatusData & MPC107_MSG_I2O_MCI & MPC107_MSG_I2O_MCIM) != 0)
  765.         {
  766.         }
  767.     /* Inbound Post Queue interrupt ,indicating  MFA in IFQPR */
  768.     if ((tempStatusData & MPC107_MSG_I2O_IPQI & MPC107_MSG_I2O_IPQIM) !=0 )
  769.         {
  770.            mpc107MsgI2oInboundRead();
  771.         }
  772.     /* Inbound Post List Overflow  */
  773.     if ((tempStatusData & MPC107_MSG_I2O_IPOI & MPC107_MSG_I2O_IPOIM) != 0)
  774.         {
  775.         }
  776.    /* Outbound Post List Overflow  */
  777.     if ((tempStatusData & MPC107_MSG_I2O_OFOI & MPC107_MSG_I2O_OFOIM) != 0)
  778.         {
  779.         }
  780.     /* Clear the interrupts */
  781.     mpc107MsgRegMod (0x0,MPC107_MSG_WRITE,
  782.                          MPC107_MSG_I2O_IMISR, tempStatusData, 0);
  783.     }
  784. /***************************************************************************
  785. *
  786. * mpc107MessageOutInt - ISR for the interrupts  from Outbound Message Unit
  787. *
  788. * This routine services the Outbound Message,Outbound Doorbell and
  789. * Outbound I2O interrupts .
  790. *
  791. * RETURNS: N/A
  792. */
  793. void mpc107MessageOutInt (void)
  794.     {
  795.      ULONG  tempStatusData; /* interrupt status register contents */
  796.      ULONG  tempMaskData;   /* interrupt Mask register contents */
  797.      UINT32  pMessageRead;
  798.     /* Read the Outbound Message Interrupt Status Register */
  799.     tempStatusData = mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ,
  800.                                       MPC107_MSG_I2O_PCI_OMISR, 0, 0);
  801.     /* Read the Outbound Message Interrupt Mask Register */
  802.     tempMaskData = mpc107MsgRegMod (pciBaseAddr, MPC107_MSG_READ ,
  803.                                     MPC107_MSG_I2O_PCI_OMIMR, 0, 0);
  804.     /* Outbound Message 0 Interrupt */
  805.     if ((tempStatusData & MPC107_MSG_I2O_OM0I & MPC107_MSG_I2O_OM0IM) != 0)
  806.         {
  807.         mpc107MsgMessageRead (MPC107_MSG_OUTBOUND ,
  808.                               MPC107_MSG_REGISTER0 , &pMessageRead);
  809.         }
  810.     /* Outbound Message 1 Interrupt */
  811.     if ((tempStatusData & MPC107_MSG_I2O_OM1I & MPC107_MSG_I2O_OM1IM) != 0)
  812.         {
  813.          mpc107MsgMessageRead (MPC107_MSG_OUTBOUND ,
  814.                                MPC107_MSG_REGISTER1 , &pMessageRead);
  815.         }
  816.     /* Outbound Doorbell  Interrupt */
  817.     if ((tempStatusData & MPC107_MSG_I2O_ODI & MPC107_MSG_I2O_ODIM) != 0)
  818.         {
  819.         mpc107MsgDoorbellRead (MPC107_MSG_OUTBOUND, &pMessageRead);
  820.         }
  821.     /* Outbound Post Queue interrupt ,indicating  MFA in OFQPR */
  822.     if ((tempStatusData & MPC107_MSG_I2O_OPQI & MPC107_MSG_I2O_OPQIM) != 0)
  823.         {
  824.            mpc107MsgI2oOutboundRead();
  825.         }
  826.     /* Clear the interrupts */
  827.     mpc107MsgRegMod (pciBaseAddr,MPC107_MSG_WRITE,
  828.                      MPC107_MSG_I2O_PCI_OMISR, tempStatusData, 0);
  829.     }
  830. /***************************************************************************
  831. *
  832. * mpc107MsgRegMod - i2o Registers In/OutLong and/or-ing wrapper.
  833. *
  834. * The purpose of this function is to perform and, or and
  835. * and/or i2oPciIn/OutLong operations with syncronization.
  836. *
  837. * RETURNS: The data  for read operations.
  838. */
  839. LOCAL UINT32 mpc107MsgRegMod
  840.     (
  841.     UINT32  pciBar,        /* Zero for EUMBBAR or a base Address */
  842.                                /* for PCI access */
  843.     UINT32  ioControlFlag, /* input/ouput control flag */
  844.                                /* 0, write */
  845.                                /* 1, read */
  846.                                /* 2, read/modify/write (ORing) */
  847.                                /* 3, read/modify/write (ANDing) */
  848.                                /* 4, read/modify/write (AND/ORing) */
  849.     UINT32  address,       /* address of device register  */
  850.     UINT32  wdata1,        /* data item 1 for read/write operation */
  851.     UINT32  wdata2         /* data item 2 for read/write operation */
  852.     )
  853.     {
  854.     UINT32 i2oTempData;
  855.     if (ioControlFlag == MPC107_MSG_WRITE) /* Write */
  856.         {
  857.         /*
  858.          * Data wdata1 is to be written in
  859.          * the register specified by address
  860.          */
  861.         mpc107MsgWrite (pciBar, address, wdata1);
  862.         }
  863.     else if (ioControlFlag == MPC107_MSG_READ) /* Read */
  864.         {
  865.         /*
  866.          * Data wdata1 is read from the register
  867.          * specified by address
  868.          */
  869.         i2oTempData = mpc107MsgRead (pciBar, address);
  870.         }
  871.     else if (ioControlFlag == MPC107_MSG_READ_OR_WRITE) /* Read OR write */
  872.         {
  873.         /*
  874.          * Data wdata1 is bitwise ORed with the data
  875.          * read from the register specified by address
  876.          * and the resultant  data is written to the
  877.          * register
  878.          */
  879.         i2oTempData = mpc107MsgRead (pciBar, address);
  880.         SYNC;
  881.         i2oTempData |= wdata1;
  882.         mpc107MsgWrite (pciBar, address, i2oTempData);
  883.         }
  884.     else if (ioControlFlag == MPC107_MSG_READ_AND_WRITE)  /* Read AND Write */
  885.         {
  886.         /*
  887.          * Data wdata1 is bitwise ANDed with the data
  888.          * read from the register specified by address
  889.          * and the resultant  data is written to the
  890.          * register
  891.          */
  892.         i2oTempData = mpc107MsgRead (pciBar, address);
  893.         SYNC;
  894.         i2oTempData &= wdata1;
  895.         mpc107MsgWrite (pciBar, address, i2oTempData);
  896.         }
  897.      else if (ioControlFlag == MPC107_MSG_READ_ANDOR_WRITE)
  898.         {
  899.         /*
  900.          * Data wdata1 is bitwise ANDed with the data
  901.          * read from the register specified by address
  902.          * and  data wdata2 is bitwise ORed  ,
  903.          * and the resultant  data is written to the register
  904.          */
  905.         i2oTempData = mpc107MsgRead (pciBar, address);
  906.         SYNC;
  907.         i2oTempData &= wdata1;
  908.         i2oTempData |= wdata2;
  909.         mpc107MsgWrite (pciBar, address, i2oTempData);
  910.         }
  911.     SYNC;
  912.     return (i2oTempData);
  913.     }
  914. /***************************************************************************
  915. *
  916. * mpc107MsgWrite - write data to  Message Unit Registers
  917. *
  918. * This routine writes the data in the specified Register
  919. * added to the offset  specified by the base address register .
  920. *
  921. * RETURNS: N/A
  922. */
  923. LOCAL void mpc107MsgWrite
  924.     (
  925.     UINT32  pciBar,        /* Zero for EUMBBAR or a base Address */
  926.                                /* for PCI access */
  927.     UINT32  messageRegNum, /* Message Register Number */
  928.     UINT32  message        /* Message */
  929.     )
  930.     {
  931.     if ((pciBar) != 0)
  932.         {
  933.         *(UINT32 *)(pciBar + messageRegNum) = MPC107LONGSWAP(message);
  934.         }
  935.     else
  936.         {
  937.         MPC107EUMBBARWRITE (messageRegNum, message);
  938.         }
  939.     }
  940. /***************************************************************************
  941. *
  942. * mpc107MsgRead - read data from  Message Unit Registers
  943. *
  944. * This routine  reads  the data in the specified Register  added to the offset
  945. * specified by the base address register.
  946. *
  947. * RETURNS: The data read from the register is returned
  948. */
  949. LOCAL ULONG mpc107MsgRead
  950.     (
  951.     UINT32  pciBar,        /* zero for EUMBBAR or a base Address */
  952.                                /* for PCI access */
  953.     UINT32  messageRegNum  /* message register number */
  954.     )
  955.     {
  956.     if ((pciBar) != 0)
  957.         {
  958.         return (*(UINT32 *)(pciBar + messageRegNum));
  959.         }
  960.     else
  961.         {
  962.         return (MPC107EUMBBARREAD(messageRegNum));
  963.         }
  964.     }