patch-2.4.19 linux-2.4.19/arch/mips/galileo-boards/ev64120/i2o.c
Next file: linux-2.4.19/arch/mips/galileo-boards/ev64120/int-handler.S
Previous file: linux-2.4.19/arch/mips/galileo-boards/ev64120/dma.c
Back to the patch index
Back to the overall index
- Lines: 690
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/mips/galileo-boards/ev64120/i2o.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -urN linux-2.4.18/arch/mips/galileo-boards/ev64120/i2o.c linux-2.4.19/arch/mips/galileo-boards/ev64120/i2o.c
@@ -0,0 +1,689 @@
+/* i2o.c - Drivers for the I2O */
+
+/* Copyright - Galileo technology. */
+
+/*includes*/
+
+#include <linux/module.h>
+
+#ifdef __linux__
+#include <asm/galileo-boards/evb64120A/core.h>
+#include <asm/galileo-boards/evb64120A/i2o.h>
+#else
+#include "Core.h"
+#include "i2o.h"
+#endif
+
+/********************************************************************
+* getInBoundMessage - When the GT is configured for I2O support
+* it can receive a message from an agent on the pci bus.
+* This message is a 32 bit wide and can be read by
+* the CPU.
+* The messaging unit contains two sets of registers
+* so, actually it can receive a 64 bit message.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: Data received from the remote agent.
+*********************************************************************/
+unsigned int getInBoundMessage(I2O_MESSAGE_REG messageRegNum)
+{
+ unsigned int regValue;
+
+ GT_REG_READ(INBOUND_MESSAGE_REGISTER0_CPU_SIDE + 4 * messageRegNum,
+ ®Value);
+ return (regValue);
+}
+
+
+/********************************************************************
+* checkInboundIntAndClear - When a message is received an interrupt is
+* generated, to enable polling instead the use of
+* an interrupt handler the user can use this fuction.
+* You will need to mask the incomming interrupt for
+* proper use.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: true if the corresponding bit in the cause register is set otherwise
+* false.
+*********************************************************************/
+bool checkInBoundIntAndClear(I2O_MESSAGE_REG messageRegNum)
+{
+ unsigned int regValue;
+
+ GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value);
+ /* clears bit 0 for message register 0 or bit 1 for message register 1 */
+ GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE,
+ BIT1 * messageRegNum);
+ switch (messageRegNum) {
+ case MESSAGE_REG_0:
+ if (regValue & BIT0)
+ return true;
+ break;
+ case MESSAGE_REG_1:
+ if (regValue & BIT1)
+ return true;
+ break;
+ }
+ return false;
+}
+
+/********************************************************************
+* sendOutBoundMessage - When the GT is configured for I2O support
+* it can send a message to an agent on the pci bus.
+* This message is a 32 bit wide and can be read by
+* the PCI agent.
+* The messaging unit contains two sets of registers
+* so, actually it can send a 64 bit message.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* unsigned int message - Message to be sent.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool sendOutBoundMessage(I2O_MESSAGE_REG messageRegNum,
+ unsigned int message)
+{
+ GT_REG_WRITE(OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE +
+ 4 * messageRegNum, message);
+ return true;
+}
+
+/********************************************************************
+* checkOutboundInt - When the CPU sends a message to the Outbound
+* register it generates an interrupt which is refelcted on
+* the Outbound Interrupt cause register, the interrupt can
+* be cleard only by the PCI agent which read the message.
+* After sending the message you can acknowledge it by
+* monitoring the corresponding bit in the cause register.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: true if the corresponding bit in the cause register is set otherwise
+* false.
+*********************************************************************/
+bool outBoundMessageAcknowledge(I2O_MESSAGE_REG messageRegNum)
+{
+ unsigned int regValue;
+
+ GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value);
+ switch (messageRegNum) {
+ case MESSAGE_REG_0:
+ if (regValue & BIT0)
+ return true;
+ break;
+ case MESSAGE_REG_1:
+ if (regValue & BIT1)
+ return true;
+ break;
+ }
+ return false;
+}
+
+/********************************************************************
+* maskInBoundMessageInterrupt - Mask the inbound interrupt, when masking
+* the interrupt you can work in polling mode
+* using the checkInboundIntAndClear function.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool maskInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
+{
+ switch (messageRegNum) {
+ case MESSAGE_REG_0:
+ SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT0);
+ break;
+ case MESSAGE_REG_1:
+ SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT1);
+ break;
+ }
+ return true;
+}
+
+/********************************************************************
+* enableInBoundMessageInterrupt - unMask the inbound interrupt.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool enableInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
+{
+ switch (messageRegNum) {
+ case MESSAGE_REG_0:
+ RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT0);
+ break;
+ case MESSAGE_REG_1:
+ RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT1);
+ break;
+ }
+ return true;
+}
+
+/********************************************************************
+* maskOutboundMessageInterrupt - Mask the out bound interrupt, when doing so
+* the PCI agent needs to poll on the interrupt
+* cause register to monitor an incoming message.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool maskOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
+{
+ switch (messageRegNum) {
+ case MESSAGE_REG_0:
+ SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT0);
+ break;
+ case MESSAGE_REG_1:
+ SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT1);
+ break;
+ }
+ return true;
+}
+
+/********************************************************************
+* enableOutboundMessageInterrupt - Mask the out bound interrupt, when doing so
+* the PCI agent needs to poll on the interrupt
+* cause register to monitor an incoming message.
+*
+* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool enableOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
+{
+ switch (messageRegNum) {
+ case MESSAGE_REG_0:
+ RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT0);
+ break;
+ case MESSAGE_REG_1:
+ RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ BIT1);
+ break;
+ }
+ return true;
+}
+
+/********************************************************************
+* initiateOutBoundDoorBellInt - Setting a bit in this register to '1' by the
+* CPU generates a PCI interrupt (if it is not masked by
+* the Outbound interrupt Mask register)
+* Only the PCI agent which recieved the interrupt can
+* clear it, only after clearing all the bits the
+* interrupt will be de-asserted.
+*
+* INPUTS: unsigned int data - Requested interrupt bits.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool initiateOutBoundDoorBellInt(unsigned int data)
+{
+ GT_REG_WRITE(OUTBOUND_DOORBELL_REGISTER_CPU_SIDE, data);
+ return true;
+}
+
+/********************************************************************
+* readInBoundDoorBellInt - Read the in bound door bell interrupt cause
+* register.
+*
+* OUTPUT: N/A.
+* RETURNS: The 32 bit interrupt cause register.
+*********************************************************************/
+unsigned int readInBoundDoorBellInt()
+{
+ unsigned int regData;
+ GT_REG_READ(INBOUND_DOORBELL_REGISTER_CPU_SIDE, ®Data);
+ return regData;
+}
+
+/********************************************************************
+* clearInBoundDoorBellInt - An interrupt generated by a PCI agent through
+* the in bound door bell mechanisem can be cleared
+* only by the CPU. The interrupt will be de-asserted
+* only if all the bits which where set by the PCI
+* agent are cleared.
+*
+* INPUTS: unsigned int data - Bits to be cleared.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool clearInBoundDoorBellInt(unsigned int data)
+{
+ GT_REG_WRITE(INBOUND_DOORBELL_REGISTER_CPU_SIDE, data);
+ return true;
+}
+
+/********************************************************************
+* isInBoundDoorBellInterruptSet - Check if Inbound Doorbell Interrupt is set,
+* can be used for polling mode.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true if the corresponding bit in the cause register is set otherwise
+* false.
+*********************************************************************/
+bool isInBoundDoorBellInterruptSet()
+{
+ unsigned int regData;
+
+ GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data);
+ return (regData & BIT2);
+}
+
+/********************************************************************
+* isOutBoundDoorBellInterruptSet - Check if out bound Doorbell Interrupt is
+* set, can be used for acknowledging interrupt
+* handling by the agent who recieived the
+* interrupt.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true if the corresponding bit in the cause register is set otherwise
+* false.
+*********************************************************************/
+bool isOutBoundDoorBellInterruptSet()
+{
+ unsigned int regData;
+
+ GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data);
+ return (regData & BIT2);
+}
+
+/********************************************************************
+* maskInboundDoorBellInterrupt - Mask the Inbound Doorbell Interrupt.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool maskInBoundDoorBellInterrupt()
+{
+ SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
+ return true;
+}
+
+/********************************************************************
+* enableInboundDoorBellInterrupt - unMask the Inbound Doorbell Interrupt.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool enableInBoundDoorBellInterrupt()
+{
+ RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
+ return true;
+}
+
+/********************************************************************
+* maskOutboundDoorBellInterrupt - Mask the Outbound Doorbell Interrupt.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool maskOutBoundDoorBellInterrupt()
+{
+ SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
+ return true;
+}
+
+/********************************************************************
+* enableOutboundDoorBellInterrupt - unMask the Outbound Doorbell Interrupt.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool enableOutBoundDoorBellInterrupt()
+{
+ RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
+ return true;
+}
+
+/********************************************************************
+* circularQueueEnable - Initialize the I2O messaging mechanism.
+*
+* INPUTS: CIRCULE_QUEUE_SIZE cirQueSize - Bits 5:1 in the:
+* Queue Control Register, Offset 0x50 (0x1c50).
+* Defines the queues size (refer to the data sheet
+* for more information)
+* unsigned int queueBaseAddr - The base address for the first queue.
+* The other queues base Address will be determined as follows:
+* Inbound Free = queueBaseAddr
+* Inbound Post = queueBaseAddr + cirQueSize
+* Outbound Post = queueBaseAddr + cirQueSize
+*
+* OUTPUT: N/A.
+* RETURNS: true.
+*
+* The Circular Queue Starting Addresses as written in the spec:
+* ----------------------------------------
+* | Queue | Starting Address |
+* |----------------|---------------------|
+* | Inbound Free | QBAR |
+* | Inbound Post | QBAR + Queue Size |
+* | Outbound Post | QBAR + 2*Queue Size |
+* | Outbound Free | QBAR + 3*Queue Size |
+* ----------------------------------------
+*********************************************************************/
+bool circularQueueEnable(CIRCULAR_QUEUE_SIZE cirQueSize,
+ unsigned int queueBaseAddr)
+{
+ unsigned int regData;
+
+ regData = BIT0 | (cirQueSize << 1);
+ /* Enable Queue Operation */
+ GT_REG_WRITE(QUEUE_CONTROL_REGISTER_CPU_SIDE, regData);
+ /* Writing The base Address for the 4 Queues */
+ GT_REG_WRITE(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, queueBaseAddr);
+ /* Update The Inbound Free Queue Base Address, offset=0 */
+ GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, 0);
+ GT_REG_WRITE(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, 0);
+ /* Update The Inbound Post Queue Base Address, offset=_16K*cirQueSize */
+ GT_REG_WRITE(INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
+ _16K * cirQueSize);
+ GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
+ _16K * cirQueSize);
+ /* Update The Outbound Post Queue Base Address, offset=2*_16K*cirQueSize */
+ GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
+ 2 * _16K * cirQueSize);
+ GT_REG_WRITE(OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
+ 2 * _16K * cirQueSize);
+ /* Update The Outbound Free Queue Base Address, offset=3*_16K*cirQueSize */
+ GT_REG_WRITE(OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
+ 3 * _16K * cirQueSize);
+ GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
+ 3 * _16K * cirQueSize);
+ return true;
+}
+
+/********************************************************************
+* inBoundPostQueuePop - Two actions are being taken upon pop:
+* 1) Getting out the data from the Queue`s head.
+* 2) Increment the tail pointer in a cyclic way (The HEAD is
+* incremented automaticaly by the GT)
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: Data pointed by tail.
+*********************************************************************/
+unsigned int inBoundPostQueuePop()
+{
+ unsigned int tailAddrPointer;
+ unsigned int data;
+ unsigned int cirQueSize;
+ unsigned int qBar;
+ unsigned int inBoundPostQbase;
+
+ /* Gets the Inbound Post TAIL pointer */
+ GT_REG_READ(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
+ &tailAddrPointer);
+ /* Gets the Data From the pointer Address */
+ READ_WORD(tailAddrPointer, &data);
+ /* incrementing head process: */
+ /* Gets the fifo's base Address */
+ GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
+ qBar = qBar & 0xfff00000;
+ /* Gets the fifo's size */
+ GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
+ cirQueSize = 0x1f && (cirQueSize >> 1);
+ /* calculating The Inbound Post Queue Base Address */
+ inBoundPostQbase = qBar + 1 * cirQueSize * _16K;
+ /* incrementing Inbound Post queue TAIL in a cyclic loop */
+ tailAddrPointer = inBoundPostQbase + ((tailAddrPointer + 4) %
+ (_16K * cirQueSize));
+ /* updating the pointer back to INBOUND_POST_TAIL_POINTER_REGISTER */
+ GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
+ tailAddrPointer);
+ return data;
+}
+
+/********************************************************************
+* isInBoundPostQueueInterruptSet - Check if in bound interrupt is set.
+* can be used for polling mode.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true if the corresponding bit in the cause register is set otherwise
+* false.
+*********************************************************************/
+bool isInBoundPostQueueInterruptSet()
+{
+ unsigned int regData;
+
+ GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data);
+ return (regData & BIT4); /* if set return '1' (true), else '0' (false) */
+}
+
+/********************************************************************
+* clearInBoundPostQueueInterrupt - Clears the Post queue interrupt.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool clearInBoundPostQueueInterrupt()
+{
+ GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, BIT4);
+ return true;
+}
+
+/********************************************************************
+* maskInBoundPostQueueInterrupt - Mask the inbound interrupt, when masking
+* the interrupt you can work in polling mode.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS:
+*********************************************************************/
+void maskInBoundPostQueueInterrupt()
+{
+ unsigned int regData;
+
+ GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data);
+ GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ regData | BIT4);
+
+}
+
+/********************************************************************
+* enableInBoundPostQueueInterrupt - Enable interrupt when ever there is a new
+* message from the PCI agent.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS:
+*********************************************************************/
+void enableInBoundPostQueueInterrupt()
+{
+ unsigned int regData;
+
+ GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data);
+ GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
+ regData & 0xfffffffb);
+}
+
+/********************************************************************
+* inBoundFreeQueuePush - Two actions are being taken upon push:
+* 1) Place the user`s data on the Queue`s head.
+* 2) Increment the haed pointer in a cyclic way (The tail is
+* decremented automaticaly by the GT)
+*
+* INPUTS: unsigned int data - Data to be placed in the queue.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool inBoundFreeQueuePush(unsigned int data)
+{
+ unsigned int headPointer;
+ unsigned int cirQueSize;
+ unsigned int qBar;
+ unsigned int inBoundFreeQbase;
+
+ GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
+ &headPointer);
+ /* placing the data in the queue */
+ WRITE_WORD(headPointer, data);
+ /* incrementing head process: */
+ /* Gets the fifo's base Address */
+ GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
+ qBar = qBar & 0xfff00000;
+ /* Gets the fifo's size */
+ GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
+ cirQueSize = 0x1f && (cirQueSize >> 1);
+ /* calculating The Inbound Free Queue Base Address */
+ inBoundFreeQbase = qBar;
+ /* incrementing Inbound Free queue HEAD in a cyclic loop */
+ headPointer =
+ inBoundFreeQbase + ((headPointer + 4) % (_16K * cirQueSize));
+ /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */
+ GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
+ headPointer);
+ return true;
+}
+
+/********************************************************************
+* isInBoundFreeQueueEmpty - Check if Inbound Free Queue Empty.
+* Can be used for acknowledging the messages
+* being sent by us to the PCI agent.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true if the queue is empty , otherwise false.
+*********************************************************************/
+bool isInBoundFreeQueueEmpty()
+{
+ unsigned int inBoundFreeQueHead;
+ unsigned int inBoundFreeQueTail;
+
+ GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
+ &inBoundFreeQueHead);
+ GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
+ &inBoundFreeQueTail);
+ if (inBoundFreeQueHead == inBoundFreeQueTail) {
+ return true;
+ } else
+ return false;
+}
+
+/********************************************************************
+* outBoundPostQueuePush - Two actions are being taken upon push:
+* 1) Place the user`s data on the Queue`s head.
+* 2) Increment the haed pointer in a cyclic way (The tail is
+* decremented automaticaly by the GT when the Agent on the
+* PCI have read data from the Outbound Port).
+*
+* INPUTS: unsigned int data - Data to be placed in the queue`s head.
+* OUTPUT: N/A.
+* RETURNS: true.
+*********************************************************************/
+bool outBoundPostQueuePush(unsigned int data)
+{
+ unsigned int headPointer;
+ unsigned int cirQueSize;
+ unsigned int qBar;
+ unsigned int outBoundPostQbase;
+
+ GT_REG_READ(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
+ &headPointer);
+ /* placing the data in the queue (where the head point to..) */
+ WRITE_WORD(headPointer, data);
+ /* incrementing head process: */
+ /* Gets the fifo's base Address */
+ GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
+ qBar = qBar & 0xfff00000;
+ /* Gets the fifo's size */
+ GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
+ cirQueSize = 0x1f && (cirQueSize >> 1);
+ /* calculating The Outbound Post Queue Base Address */
+ outBoundPostQbase = qBar + 2 * cirQueSize * _16K;
+ /* incrementing Outbound Post queue in a cyclic loop */
+ headPointer =
+ outBoundPostQbase + ((headPointer + 4) % (_16K * cirQueSize));
+ /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */
+ GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
+ headPointer);
+ return true;
+}
+
+/********************************************************************
+* isOutBoundPostQueueEmpty - Check if Outbound Post Queue Empty.
+* Can be used for acknowledging the messages
+* being sent by us to the PCI agent.
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: true if the queue is empty , otherwise false.
+*********************************************************************/
+bool isOutBoundPostQueueEmpty()
+{
+ unsigned int outBoundPostQueHead;
+ unsigned int outBoundPostQueTail;
+
+ GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
+ &outBoundPostQueHead);
+ GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
+ &outBoundPostQueTail);
+ if (outBoundPostQueHead == outBoundPostQueTail) {
+ return true;
+ } else
+ return false;
+}
+
+/********************************************************************
+* outBoundFreeQueuePop - Two actions are being taken upon pop:
+* 1) Getting out the data from the Queue`s head.
+* 2) Increment the tail pointer in a cyclic way (The HEAD is
+* incremented automaticaly by the GT)
+*
+* INPUTS: N/A.
+* OUTPUT: N/A.
+* RETURNS: Data pointed by tail.
+*********************************************************************/
+unsigned int outBoundFreeQueuePop()
+{
+ unsigned int tailAddrPointer;
+ unsigned int data;
+ unsigned int cirQueSize;
+ unsigned int qBar;
+ unsigned int outBoundFreeQbase;
+
+ /* Gets the Inbound Post TAIL pointer */
+ GT_REG_READ(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
+ &tailAddrPointer);
+ /* Gets the Data From the pointer Address */
+ READ_WORD(tailAddrPointer, &data);
+ /* incrementing head process: */
+ /* Gets the fifo's base Address */
+ GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
+ qBar = qBar & 0xfff00000;
+ /* Gets the fifo's size */
+ GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
+ cirQueSize = 0x1f && (cirQueSize >> 1);
+ /* calculating The Inbound Post Queue Base Address */
+ outBoundFreeQbase = qBar + 3 * cirQueSize * _16K;
+ /* incrementing Outbound Free queue TAlL in a cyclic loop */
+ tailAddrPointer = outBoundFreeQbase + ((tailAddrPointer + 4) %
+ (_16K * cirQueSize));
+ /* updating the pointer back to OUTBOUND_FREE_TAIL_POINTER_REGISTER */
+ GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
+ tailAddrPointer);
+ return data;
+}
+
+
+EXPORT_SYMBOL(isInBoundDoorBellInterruptSet);
+EXPORT_SYMBOL(initiateOutBoundDoorBellInt);
+EXPORT_SYMBOL(clearInBoundDoorBellInt);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)