bcm-specs

[Specification

This page describes how to initiate DMA from and to the wireless core.

General

The chip has 6 DMA controllers, each of which has a transmit and a receive channel. Each DMA controller is controlled via its own set of registers, located in the MMIO. Depending on your board, there are two different DMA register layouts. If the 64 bit DMA flag is set in sbtmstatehigh, then use the 64 bit DMA layout, otherwise, use the 32 bit DMA layout.

32 Bit DMA

The 6 DMA controllers are addressed by accessing MMIO offsets 0x200, 0x220, 0x240, 0x260, 0x280 and 0x2A0 respectively.

Controller Registers

Each controller has the following registers, given as offsets of the MMIO addresses:

Offset

Description

Transmit Channel

0x00 (4 bytes)

Control word

0x04 (4 bytes)

Descriptor Ring Address

0x08 (4 bytes)

Descriptor Stop Index

0x0C (4 bytes)

Transmit Status Word

Receive Channel

0x10 (4 bytes)

Control word

0x14 (4 bytes)

Descriptor Ring Address

0x18 (4 bytes)

Descriptor Index

0x1C (4 bytes)

Receive Status Word

All descriptor rings must be 4K aligned and fit into a single 4K page.

Transmit Channel Control Word

The transmit channel control word consists of the following:

Mask

Function

0x00000001

Enable

0x00000002

Suspend Request

0x00000004

Loopback Enable

0x00000010

Flush Request

0x00030000

Address Extension

Transmit Channel Status Word

The transmit channel status word consists of the following:

Mask

Function

0x00000FFF

Current Descriptor Pointer

0x0000F000

Transmit State

0x000F0000

Transmit Errors

0xFFF00000

Active Descriptor

Transmit Errors

This field can take the following values:

Value

Meaning

0

No Error

1

Descriptor Protocol Error (Indicates the Descriptor Ring Address could not be accessed)

2

Data FIFO Underrun

3

Bus Error on Buffer Read

4

Bus Error on Descriptor Access

Transmit State

This field can take the following values:

Value

Meaning

0

Disabled

1

Active

2

Idle Wait

3

Stopped

4

Suspend Pending

Receive Channel Control Word

The receive channel control word consists of the following:

Mask

Function

0x00000001

Enable

0x000000FE

Frame Offset

0x00000100

Direct FIFO Receive Mode (PIO)

0x00030000

Address Extension Bits

Receive Channel Status Word

The receive channel status word consists of the following:

Mask

Function

0x00000FFF

Current Descriptor Pointer

0x0000F000

Receive State

0x000F0000

Receive Errors

0xFFF00000

Active Descriptor

Receive Errors

This field can take the following values:

Value

Meaning

0

No Error

1

Descriptor Protocol Error (Indicates the Descriptor Ring Address could not be accessed)

2

Data FIFO Overflow

3

Bus Error on Buffer Write

4

Bus Error on Descriptor Access

Receive State

This field can take the following values:

Value

Meaning

0

Disabled

1

Active

2

Idle Wait

3

Stopped

Descriptors

Each descriptor (that is stored into the descriptor ring and posted) contains of two 4 byte fields:

32 Bit DMA Descriptor

Control

Address

(in this order). The descriptor is never modified by the hardware, only read by it.

The control field breaks down as such

Mask

Function

0x00001FFF

Buffer Byte Count

0x00030000

Address Extension Bits

0x10000000

End of Descriptor Table

0x20000000

Interrupt on Completetion Requested

0x40000000

End of Frame

0x80000000

Start of Frame

The meaning of the flags at the high 4 bits of the control field is clear when you consider scatter-gather-I/O. Each transfer can be posted into or read from multiple buffers. The start of frame flag indicates that this transfer starts a new I/O packet, end of frame indicates that this is the last buffer for one packet.

The interrupt on completion flag signals (if turned on) that an interrupt is requested when this single transfer (not packet) is completed, end of descriptor table is used to signal to the chip that no valid descriptors follow in the memory after this one but that the controller should rather start reading at the beginning of the descriptor ring again.

The address field is as follows:

Mask

Function

0x3FFFFFFF

Address

0xC0000000

Routing

Known values for the routing value are as follows:

Value

Function

0

No translation

1

Client Mode Translation (1GB)

If you have enabled any routing bits, make sure to also set the address extension bits in the control field when setting the address. This allows use of the full 32 bits of address space.

64 Bit DMA

The 6 DMA controllers are addressed by accessing MMIO offsets 0x200, 0x240, 0x280, 0x2C0, 0x300 and 0x340 respectively.

Controller Registers

Each controller has the following registers, given as offsets of the MMIO addresses:

Offset

Description

Transmit Channel

0x00 (4 bytes)

Control Word

0x04 (4 bytes)

Descriptor Stop Index

0x08 (4 bytes)

Descriptor Ring Address (Low 32 Bits)

0x0C (4 bytes)

Descriptor Ring Address (High 32 Bits)

0x10 (4 bytes)

Status - State

0x14 (4 bytes)

Status - Error

Receive Channel

0x20 (4 bytes)

Control Word

0x24 (4 bytes)

Descriptor Stop Index

0x28 (4 bytes)

Descriptor Ring Address (Low 32 Bits)

0x2C (4 bytes)

Descriptor Ring Address (High 32 Bits)

0x30 (4 bytes)

Status - State

0x34 (4 bytes)

Status - Error

All descriptor rings must be 8K aligned and fit into a single 8K page.

Transmit Channel Control Word

The transmit channel control word consists of the following:

Mask

Function

0x00000001

Enable

0x00000002

Suspend Request

0x00000004

Loopback Enable

0x00000010

Flush Request

0x00030000

Address Extension

Transmit Channel Status - State

The transmit channel status state word consists of the following:

Mask

Function

0x00001FFF

Current Descriptor Pointer

0xF0000000

Transmit State

Transmit State

This field can take the following values:

Value

Meaning

0

Disabled

1

Active

2

Idle Wait

3

Stopped

4

Suspend Pending

Transmit Channel Status - Errors

The transmit channel status errors word consists of the following:

Mask

Function

0x0001FFFF

Active Descriptor Pointer

0xF0000000

Transmit Errors

Transmit Errors

This field can take the following values:

Value

Meaning

0

No Error

1

Descriptor Protocol Error (Indicates the Descriptor Ring Address could not be accessed)

2

Data FIFO Underrun

3

Data Transfer Error

4

Descriptor Read Error

5

Core Error

Receive Channel Control Word

The receive channel control word consists of the following:

Mask

Function

0x00000001

Enable

0x000000FE

Frame Offset

0x00000100

Direct FIFO Receive Mode (PIO)

0x00030000

Address Extension Bits

Receive Channel Status - State

The receive channel status state word consists of the following:

Mask

Function

0x00001FFF

Current Descriptor Pointer

0xF0000000

Receive State

Receive State

This field can take the following values:

Value

Meaning

0

Disabled

1

Active

2

Idle Wait

3

Stopped

4

Suspend Pending

Receive Channel Status - Errors

The receive channel status word consists of the following:

Mask

Function

0x0001FFFF

Active Descriptor Pointer

0xF0000000

Receive Errors

Receive Errors

This field can take the following values:

Value

Meaning

0

No Error

1

Descriptor Protocol Error (Indicates the Descriptor Ring Address could not be accessed)

2

Data FIFO Overflow

3

Data Transfer Error

4

Descriptor Read Error

5

Core Error

Descriptors

Each descriptor (that is stored into the descriptor ring and posted) contains of four 4 byte fields:

64 Bit DMA Descriptor

Control 1 - Control and Buffer Count

Control 2 - Buffer Count and Address Extension

Address 1 - Low bits of memory address of data buffer

Address 2 - High bits of memory address of data buffer

(in this order). The descriptor is never modified by the hardware, only read by it.

Control 1

Control field 1 breaks down as such:

0x10000000

End of Descriptor Table

0x20000000

Interrupt on Completetion Requested

0x40000000

End of Frame

0x80000000

Start of Frame

Control 2

Control field 2 breaks down as such:

Mask

Function

0x00001FFF

Buffer Byte Count

0x00030000

Address Extension Bits

The meaning of the flags at the high 4 bits of the control 1 field is clear when you consider scatter-gather-I/O. Each transfer can be posted into or read from multiple buffers. The start of frame flag indicates that this transfer starts a new I/O packet, end of frame indicates that this is the last buffer for one packet.

The interrupt on completion flag signals (if turned on) that an interrupt is requested when this single transfer (not packet) is completed, end of descriptor table is used to signal to the chip that no valid descriptors follow in the memory after this one but that the controller should rather start reading at the beginning of the descriptor ring again.

The address 2 field is as follows (address 1 contains all address bits):

Mask

Function

0x3FFFFFFF

Address

0xC0000000

Routing

Known values for the routing value are as follows:

Value

Function

0

No translation

2

Client Mode Translation (2 Zettabytes)

If you have enabled any routing bits, make sure to also set the address extension bits in the control field when setting the address. This allows use of the full 64 bits of address space.

Working with the DMA Engine

DMA Engine Initialization

  1. Allocate enough DMA-able memory for the transmit and receiving descriptor rings and however many descriptors you want to fit into them. Make sure they are 4/8K-page-aligned and not larger than 4/8K.
  2. Zero out the descriptor rings
  3. (If applicable) set the transmit control register to have only transmit enable set, set the transmit descriptor ring address.

  4. (If applicable) set the receive descriptor ring address (since no receive buffers have been posted yet, you cannot change the control register).

Transfer DMA Initialization

  1. Clear the Transmit Descriptor Ring
  2. Set the transfer enable bit in the Transmit Control Register
  3. Write the bus address of the transfer descriptor ring to the Transmit Address Register

Receive DMA Initialization

  1. Clear the Receive Descriptor Ring
  2. Set the receive enable bit in the Receive Control Register
  3. Write the bus address of the receive descriptor ring to the Receive Address Register

Suspend the Transfer DMA

  1. Set the PowerSavingControlBits bit 26 and calculate bit 25

  2. Set the Suspend Request register in the Transmit Control Register

Resume the Transfer DMA

  1. Unset the Suspend Request register in the Transmit Control Register
  2. Calculate both of the PowerSavingControlBits

Reset Transfer DMA

  1. Spinwait for up to 10 mSec, or until the DMA transmit status register is set to disabled, idle or stopped
  2. Write 0 to the Transmit DMA control register
  3. Spinwait for up to 10 mSec or until the DMA transmit status register is set to disabled
  4. If the status is still not disabled, an error has occured
  5. Delay for 300 uSec to ensure that the reset was completed

Reset Receiving DMA

  1. Write 0 to the Receive DMA control register
  2. Spinwait for up to 10 mSec or until the DMA receive status register is set to disabled
  3. If the status is still not disabled, an error has occured

Disabling the DMA Engine

  1. Disabling is as simple as freeing the DMA descriptor rings

Transmitting (To the Wireless Core)

Now you already know almost everything you need to transfer stuff.

  1. For each piece of the packet to be transferred, get a descriptor and set its properties to the correct values. If you need, ask for interrupts but you probably should only do that on the last descriptor of one packet.
  2. Write the first descriptor offset the engine should not process (for the 10th descriptor this is 80) to the descriptor stop index register of the transmit channel (that is, the last used offset+1 handling wrap-around).

Receiving (From the Wireless Core)

When some data is received, the 802.11 core gives this data to the DMA engine. Additionally, a receive header (see FrameInformation) is given to the DMA engine as well. The receive header is put into the space before the frame offset (which is why the frame offset should be 30), and the actual data is put after that. I don't know what happens if the frame offset is chosen too small, maybe then the data overwrites the header. Additionally, the DMA engine prepends the length of the payload (frame offset + data length). If one descriptor is too small, the data is split over multiple rx descriptors, ignoring the frame offset in the next descriptors (I think). The original driver ignores packets that don't fit into one descriptor, skipping them and the extra descriptors that belong to it. Every packet gets its own descriptor(s).

DMA Interrupts

Each DMA controller is linked to the interrupt reason registers in the MMIO area 0x20 - 0x38. They contain the following flags (incomplete):

bits

31

..

17

16

15

..

10

9

...

0

unknown

DMA receive done

chiperrors

unknown

Chip Errors

The chiperrors field is a bunch of flags:

bits

5

4

3

2

1

0

unknown,fatal

unknown,fatal

unknown, not fatal

unknown,fatal

unknown,fatal

unknown,fatal

If a fatal error occurs, you need to reset the chip (80211CoreReset followed by 80211Init). In some cases it might suffice to reset the DMA queues for example, but we don't know that.

DMA Parameters for the Wireless Core

On the wireless core, out of the 6 DMA engines only the first is used for receiving data, and only the first 5 are even attached. On cores with revision < 5, the fourth DMA engine is also used, but it's only used for receiving control packets. If the 4th DMA engine is used, its parameters are described below. All others can under certain circumstances be used for sending, but only in access point mode. In station mode, always use the second DMA engine for sending packets.

The first receive part should have a frame offset of 30 bytes, the last doesn't use a frame offset. You should always keep about 16 receive descriptors posted to the chip, on the first engine their buffer sizes should not be below 1792 bytes, on the last one 16 bytes suffice.

As a rule of thumb, reserve about 256 transmit descriptors. But it doesn't really matter, the page alignment requirements makes you reserve more memory anyway unless you want to re-use the rest of that page for receive buffers.


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