Contents
General
There are 4 PIO queues. The PIO queues each have a set of registers located at MMIO offsets 0x300, 0x310, 0x320 and 0x330 respectively.
PIO Queue Registers
Offset |
Size |
Description |
0x00 |
2 Bytes |
TX Control |
0x02 |
2 Bytes |
TX Data (Endianness is affected by SBF_REGISTER_BYTESWAP) |
0x04 |
2 Bytes |
Internal PIO TX queue buffer size |
0x06 |
2 Bytes |
Unused |
0x08 |
2 Bytes |
RX Control |
0x0A |
2 Bytes |
RX Data (Endianness is affected by SBF_REGISTER_BYTESWAP) |
0x0C |
2 Bytes |
Unused, maybe RX queue buffer size? (For symmetry with TX) |
0x0E |
2 Bytes |
Unused |
TX Control Register
Bits |
|||||||
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Suspend Queue |
|
|
|
Initiate Transfer |
Transfer Complete |
Write upper 8 bits |
Write lower 8 bits |
RX Control Register
Bits |
|||||||
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
|
|
Data Ready |
Initiate Receiving |
Working With PIO Queues
PIO Queue Usage
PIO Queue usage is exactly as DMA usage, all queues for sending, queue 1 for receiving and queue 4 for receiving transmit status notifications on cores with revision < 3.
Initialization
- Setup the Packet Queues (Software linked lists really)
- If the Core Revision is less than 3, bitwise OR 0x100 to the Chip Interrupt Mask
Resume the Transfer PIO Queue
- Clear bit 0x80 of the Transfer Control Register of the desired queue
Calculate the PowerSavingControlBits
Suspend the Transfer PIO Queue
Set the PowerSavingControlBits bit 26 and calculate bit 25
- Mask the Transfer Control Register of the desired queue with 0x80
Transmitting (To the Wireless Core)
Buffering information
Since the PIO queues need to buffer the data that is to be transmitted on the chip, you need to make sure to not ever have more bytes outstanding than the internal buffer size (PIO TX Register 0x04) - 80 (no idea why -80, but it is like that, maybe some chip-internal accounting overhead and the register actually notes the complete memory that's available?). Additionally, you can only have at most 31 (32?) packets in the chip-internal buffer of a queue at a time. This means you need to account for the packets and bytes that are currently in the chip-internal PIO queues and need to assume they are in the queue until you get a TransmitStatus notification. Note that if the PIO TX Queue Control register has the Suspend Queue bit set, you should also not buffer any more data for transmission.
Start the Transfer
- Write 0x08 to the PIO TX Control Register
- If the 802.11 Core Revision is less than 3, save the last byte of the packet data and do not transfer it with the other bytes.
Writing a Single Byte
- If the 802.11 Core Revision is less than 3
- Write the 8 bit data as a 16 bit value to the PIO TX Data Register
- Write 0x01 to the PIO TX Control Register
- Otherwise
- Write 0x01 to the PIO TX Control Register
- Write the 8 bit data as a 16 bit value to the PIO TX Data Register
Writing 16 Bits
- If the 802.11 Core Revision is less than 3
- Write the first 16 bits of the data as a short to the PIO TX Data Register
- Write 3 to the PIO TX Control Register
- Write the remaining 16 bit data to the PIO TX Data Register until we've emptied the queue. If we have a byte left over afterwards, write it using the Writing a Single Byte method above.
Complete the Transfer
- If the 802.11 Core Revision is less than 3
- Write the saved last byte of the packet to the PIO TX Data Register
- Write 5 to the PIO TX Control Register
- Otherwise
- Write 4 to the PIO TX Control Register
Receiving (From the Wireless Core)
Start Receiving
- If bit 0 of the RX Control Register is not set, then we can't receive data right now and we return
- Write 1 to the RX Control Register (Ack the RX data bit?)
- Spinwait until there is data to receive (bit 1 of the RX Control Register is set) and if there is no data to receive after 100 uSec, return (check every 10 uSec for 100 uSec)
- Read the length of the data packet from the RX Data Register (first two bytes of the RX header)
- If the packet is more than 0x700 bytes, it's an error
- If the packet's length is 0 and we're not on PIO Queue 4, it's an error
- Obtain the rest of the RX Header (0xE bytes on PIO Queue 4, 0x12 on all others) by reading 16 bit pieces from the RX Data Register and padding it to 30 bytes with zeroes
It is an error condition if the "Invalid Frame" bit in the flags2 field of the RX Header (see FrameInformation) is set, but if it is on PIO Queue 1, read the RX Data Register 15 times before returning (this probably somehow empties buffers)
- If this is PIO Queue 4, return since there's no more data to retrieve
- Read the rest of the data (packet length) in 16 bit pieces from the RX Data Register (except the last byte if there are an odd number of bytes)
If the number of bytes being read is odd, the last byte read is actually the first data byte (overwrite the first byte of the PLCP header, offset 0x20 if the "Type 2 Frame" is set in the RX Header (see FrameInformation), offset 0x1E otherwise)
Errors
- Record the error
- Write 2 to the PIO RX Control Register
- Abort