bcm-specs

[Specification

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

  1. Setup the Packet Queues (Software linked lists really)
  2. If the Core Revision is less than 3, bitwise OR 0x100 to the Chip Interrupt Mask

Resume the Transfer PIO Queue

  1. Clear bit 0x80 of the Transfer Control Register of the desired queue
  2. Calculate the PowerSavingControlBits

Suspend the Transfer PIO Queue

  1. Set the PowerSavingControlBits bit 26 and calculate bit 25

  2. 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

  1. Write 0x08 to the PIO TX Control Register
  2. 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

  1. If the 802.11 Core Revision is less than 3
    1. Write the 8 bit data as a 16 bit value to the PIO TX Data Register
    2. Write 0x01 to the PIO TX Control Register
  2. Otherwise
    1. Write 0x01 to the PIO TX Control Register
    2. Write the 8 bit data as a 16 bit value to the PIO TX Data Register

Writing 16 Bits

  1. If the 802.11 Core Revision is less than 3
    1. Write the first 16 bits of the data as a short to the PIO TX Data Register
  2. Write 3 to the PIO TX Control Register
  3. 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

  1. If the 802.11 Core Revision is less than 3
    1. Write the saved last byte of the packet to the PIO TX Data Register
    2. Write 5 to the PIO TX Control Register
  2. Otherwise
    1. Write 4 to the PIO TX Control Register

Receiving (From the Wireless Core)

Start Receiving

  1. If bit 0 of the RX Control Register is not set, then we can't receive data right now and we return
  2. Write 1 to the RX Control Register (Ack the RX data bit?)
  3. 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)
  4. Read the length of the data packet from the RX Data Register (first two bytes of the RX header)
  5. If the packet is more than 0x700 bytes, it's an error
  6. If the packet's length is 0 and we're not on PIO Queue 4, it's an error
  7. 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
  8. 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)

  9. If this is PIO Queue 4, return since there's no more data to retrieve
  10. 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)
  11. 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

  1. Record the error
  2. Write 2 to the PIO RX Control Register
  3. Abort

Exported/Archived from the wiki to HTML on 2016-10-27