FIFO operation in the PCI-DP | Cypress Semiconductor
Support & Community
FIFO operation in the PCI-DP
- How does the internal FIFO work?
- How do I read/write to the internal FIFO?
- What is I20?
The FIFOs are designed to support the Message Transport protocol of the I2O (Intelligent I/O) Shell Interface Specification. The shell specification is chapter 4 of the I2O Architecture Specification, version 2.0, March 1999. The applicable portion to the PCI-DP is section 4.2.1, Register-level Interface. The FIFO may be used as general purpose FIFO, but should not be assumed to operate as one may typically expect for a common FIFO. I2O formally identifies ports 0x0030, 0x0034, 0x0040, and 0x0044. The PCI-DP includes ports 0x0038, 0x003C, 0x0048, and 0x004C as a means to access all FIFO from both PCI and Local interfaces; these are not to be used for I2O specified operations.
* All FIFO and FIFO status registers are accessible from both interfaces, PCI and Local.
* PCI access to FIFO resources is an offset from the Base Address Register 0, BAR0, of the PCI-DP PCI configuration space.
* Local access to FIFO resources is an offset of 0x0000 from the local bus address, ADR[14:0].
* Inbound Free FIFO, read at 0x0040, write at 0x0048.
* Inbound Post FIFO, read at 0x0048, write at 0x0040.
* Outbound Free FIFO, read at 0x004C, write at 0x0044.
* Outbound Post FIFO, read at 0x0044, write at 0x004C.
* Each of the four FIFO are 32 locations deep by 32-bits.
* When read, an empty FIFO always returns 0xFFFFFFFF.
* When a write access to a full FIFO is executed, the new data is not written to the FIFO. The state of the FIFO contents will not be changed. An overflow condition will be reported due to the write access.
* Port naming combines the names of the two FIFO since a single port accesses two different FIFO. The names are:
IBFPFIFO at 0x0040
OBPFFIFO at 0x0044
IBPFFIFO at 0x0048
OBFPFIFO at 0x004C
Names syntax is:
port name ::=
queue ::= IB | OB (for Inbound or Outbound queue, resp)
read context ::=
write context ::=
context ::= F | P (for Free or Post list FIFO, resp)
Summary of FIFO Conditions Supported
* Not-empty status is available for the Outbound Post FIFO and the Inbound Post FIFO. This status may be routed to interrupts or polled or both.
* The Outbound Free FIFO and the Inbound Free FIFO do not have not-empty status bits. An interrupt condition cannot be generated from their state of fullness. Since a read of an empty FIFO returns 0xFFFFFFFF, this is a way to detect an empty FIFO. Since that particular data pattern is intended to indicate an empty FIFO and if that pattern was stored as data into the FIFO, then when read it would be a false indication that the FIFO is empty.
* Overflow conditions are detected for all four FIFO.
* Overflow of either the Inbound Post FIFO or Outbound Free FIFO are reported as a single event. That is, the condition is OR'ed within the PCI-DP.
* Overflow of either the Inbound Free FIFO or Outbound Post FIFO are reported as a single event. That is, the condition is OR'ed within the PCI-DP.
I2O Interrupt and Status Registers
* Host Interrupt Status Register, I2OHISR, 0x0030, reflects status of the Outbound Post FIFO; I2OHISR is a not-empty flag. If it is not empty, then it is set to '1'; if it is empty it is set to '0'. All other bits of the 32-bit register are '0'. Writes to this register are ignored.
* Host Interrupt Mask Register, I2OHIMR, 0x0034, is used to disable or enable interrupt generation on the PCI-DP INTA# output as a function of the Outbound Post FIFO status. I2OHIMR is a mask bit. If it is set to '1', then an interrupt will not be generated using this interrupt mechanism. If it is set to '0' and I2OHISR is set to '1', then an interrupt will be generated. INTA# will continue to be asserted as long as the condition is true. I2OHIMR may be updated. All other I2OHIMR bits will read as '1' and writes to those bits are ignored.
* Local Interrupt Status Register, I2OLISR, 0x0038, reflects status of the Inbound Post FIFO; I2OLISR is a not-empty flag. If it is not empty, then it is set to '1'; if it is empty it is set to '0'. All other bits of the 32-bit register are '0'. Writes to this register are ignored.
* Local Interrupt Mask Register, I2OLIMR, 0x003C, is used to disable or enable interrupt generation on the PCI-DP IRQ_OUT# output as a function of the Inbound Post FIFO status. I2OLIMR is a mask bit. If it is set to '1', then an interrupt will not be generated using this interrupt mechanism; if it is set to '0' and I2OLISR is set to '1', then an interrupt will be generated. IRQ_OUT# will continue to be asserted as long as the condition is true. I2OLIMR may be updated. All other I2OLIMR bits will read as '1' and writes to those bits are ignored.
* Interrupt generation based upon applicable settings in the above registers are not conditioned by any other PCI-DP Operations Registers. However, the status bits, I2OHISR and I2OLISR are mirrored in both of the PCI-DP Interrupt Status registers, HINT and LINT. If the I2O method of interrupt generation is not desired, the HINT and LINT may be used to provide an alternate, (and more flexible), means of interrupt generation.
FIFO Status in the Host and Local Interrupt Status Registers
* The Host Interrupt Control and Status Register, HINT, 0x04E4, reflects a copy of the I2OHISR and I2OLISR at HINT and HINT, respectively. These bits cannot be cleared with a write-one-to-clear like the other Interrupt Event Status bits of the HINT. These bits follow the state of the I2O Status Register bits.
* The Local Interrupt Control and Status Register, LINT, 0x04F4, reflects a copy of the I2OHISR and I2OLISR at LINT and LINT, respectively. These bits cannot be cleared with a write-one-to-clear like the other Interrupt Event Status bits of the LINT. These bits follow the state of the I2O Status Register bits.
* An overflow condition on either the Inbound Post FIFO or Outbound Free FIFO will set a '1' to HINT and LINT. This is referred to as a PCI FIFO overflow since these two FIFO are written via the PCI interface when used as I2O FIFO. The bits are set whenever a write access is executed to a full FIFO. These bits are cleared with a write-one-to-clear protocol. HINT and LINT are not mirror copies of each other, therefore to clear both, each must be cleared.
* An overflow condition on either the Inbound Free FIFO or Outbound Post FIFO will set a '1' to HINT and LINT. This is referred to as a Local FIFO overflow since these two FIFO are written via the Local interface when used as I2O FIFO. The bits are set whenever a write access is executed to a full FIFO. These bits are cleared with a write-one-to-clear protocol. HINT and LINT are not mirror copies of each other, therefore to clear both, each must be cleared.
Byte, Word, and Special Addressing to the FIFO
Each FIFO entry is 32 bits is size. Each FIFO is located at a 32-bit port into the PCI-DP's memory space. There are four 32-bit ports which are used to access the FIFO: 0x0040, 0x0044, 0x0048, and 004C. However, there is a mechanism to support 8-bit and 16-bit local bus utilization of the FIFO. Addresses other than the 32-bit boundaries to which each FIFO port is based are supported. The FIFO consist of two elements: the memory that holds the data; and the FIFO pointers. The pointers point to where the next 32-bit FIFO entry will be written (the head pointer) and to where the next 32-bit FIFO entry will be read (the tail pointer). The memory locations themselves are always read or written when accessed. However, the FIFO pointers are only updated if the access was complete. In this way, a bus less than 32-bits wide may access a single 32-bit FIFO entry until the access is complete. The definition of a complete access is as follows:
From the PCI bus,
Write access is complete if all four byte enables are active;
Read access is always considered complete.
From the Local bus,
Read access is complete if the PCI-DP's internal byte enable 3 is active;
Write access is complete if the PCI-DP's internal byte enable 3 is active.
The byte enable 3 used above is the PCI-DP's internally generated byte enable 3. This is the sole criteria for determining if the FIFO access is complete. For instance, if during a local bus write access only byte 3 is updated, then the other bytes of the 32-bit FIFO entry will not be given the chance to update. This is because the FIFO access will be determined complete and the FIFO pointers will advance to the next 32-bit FIFO location. For basic linear addressing this is typically not an issue since the internally generated byte 3 enable is generated last so all other bytes in the 32-bit FIFO have been accessed, (updated for a write or read out for a read). Mapping for the internal byte enables is shown in the Interface Definitions section of the PCI-DP data sheet.
For a local bus configuration that uses the external BE3# as a byte lane enable, then the relation is one to one. That is, the internal byte enable 3 is connected to the PCI-DP BE3# input pin. An active low BE3# results in an active internal byte enable 3. This is typical for many 32-bit wide buses. In this case, when BE3# is active, the FIFO access is considered complete.
But, the PCI-DP's support for many different local bus protocols necessitates the need for internally generated byte enable signals that are not simply copies of the external BE# input pins. The PCI-DP supports 8-bit and 16-bit local bus interfaces that most likely do not use the BE# inputs directly as byte lane enables. For instance, for a typical 8-bit bus, BE3# and BE2# are connected to the least significant address lines of the bus, A1 and A0, respectively. A 2 to 4 decode of these lines produces the internal byte enables used to access PCI-DP resources. So, in this case, when A[1:0]='11', the FIFO access is considered complete and the FIFO pointers advance. Basic 16-bit interfaces are much the same way except that a single address bit determines which two, upper pair or lower pair, of internal byte enables are active. Even though address lines are decoded, basic linear addressing fits well with the 32-bit FIFO entry since the internal byte enable 3 is the last byte enable to be generated for any give 32-bit FIFO entry.
There is another kind of byte decode; herein, termed special byte decoding. This is used to support 16-bit and 32-bit local bus interfaces that use operand size and offset protocols to determine data alignment. The BE# inputs are not used as byte lane enables nor are the least significant address bits used solely for byte decoding. For 16-bit buses, the special byte decoding is invoked when BEMODE='1'. For 32-bit buses, either a BEMODE='1' setting, or a BW='11' setting, or both will invoke the special byte decode logic.
The mapping for special byte decoding logic is show in the PCI-DP data sheet in the 16-Bit Interface and 32-Bit Interface sections of the Interface Definitions section. The mapping shows how the external BE# lines are wired and how they map to the internal byte enables. For example, a 16-bit bus interface (BW='01') with BEMODE='1' will generate an internal byte 3 enable when A[1:0]='00'. This can be seen in the table for BEMODE='1' in the 16-Bit Interface section.
Care needs to be exercised when accessing the 32-bit FIFO with 8-bit or 16-bit buses and any 16-bit or 32-bit bus that uses special byte decoding. The reason is that in some processor domains, byte 3 may be accessed before the other bytes of the same 32-bit location. Particular attention needs to be focused on the special decoding case. For instance, in the example immediately above, for a 16-bit bus, a linear address sequencing from address A[2:0]='000' to address A[2:0]='010' would probably cause undesired results. This is because both addresses point to the same 32-bit location, but the FIFO pointers are advanced on the first access, not the last. Due to special byte encoding, the internal byte 3 is asserted on the first address access thereby completing the FIFO access and advancing the pointer to the next FIFO entry. This problem can be avoided by accessing in the other order, A[2:0]='010' and then A[2:0]='000'. So, if the Inbound Free FIFO is to be written with a 16-bit special byte decode bus, then a write to address 0x004A should occur first and then a write to 0x0048.