NOTE: this page is for archival only, see the note at the end of the page.

Go back –> Atheros Linux wireless drivers


ath the shared module between Atheros wireless drivers. It contains any shared common code. It currently only contains the common shared regulatory code but can be extended to contain anything seen shared between both drivers.


Here is the TODO list for the common shared code for Atheros modules.

  • When the regpair is detected check first the currently set alpha2 and if the regpair matches a group that has that alpha2 use that alpha2 instead for the regulatory_hint().
  • Test firmware upload on ar9271 and if it works as-is then share firmware upload code between ar9170 and ar9271 as currently the code is identical. There is one exception, the final command but we can probably just ignore the error code on that on ar9271 as well.


Atheros devices share the same regulatory implementation. All devices have a regulatory domain code programmed into their EEPROM. The programmed regulatory domain code can be of three kinds:

Historically the Atheros regulatory domains have been mapped to groups as many regulatory domains share common definitions. Atheros regulatory domains used to be all embedded in the driver source code so space efficiency was important. To save space and to allow more diversity regulatory domains were allowed to be mapped to a 5 GHz group and a 2 GHz group. When a band was not supported a NULL group for the band was used. Each band group had a arbitrary group name, such as FCC3 or MKKA.

To better understand the nomenclatures used it helps to understand the conventions followed by the old Atheros regulatory group naming convention. Tendencies to follow "US" similar regulatory domains were given "FCC" prepend labels after the FCC, European regulatory domains used the "ETSI" prepend name after the ETSI, Asian countries tended to fit under "MKK" under the Japanese regulatory agency (I forget what this stands for), "APL" which I believe stands for "Asia, Pacific and Latin America". Numbers were appended at the end of each group label for 5 GHz groups, and letters for 2 GHz band group names.

Examples of 5 GHz regulatory band group names:

  • MKK1
  • APL4
  • ETSI1
  • FCC3
  • WOR0 (World regulatory band definition 0)
  • WOR4 (World regulatory band definition 4)

Examples of 2 GHz regulatory band group names:

  • MKKA
  • MKKA1
  • MKKA2
  • FCCA
  • WORLD (there's only one 5 GHz group world regulatory domain)

Each band also had a set of world regulatory definitions.

Each regulatory band group had an attached set of frequency ranges along with regulatory flags for the channels. Band groups could be put together to form a regulatory domain, containing one 5 GHz regulatory domain group, and a 2 GHz regulatory domain group.

Examples of regulatory domain groups:

  • MKK9_MKKA1

Programmed EEPROM regulatory domains codes would map to regulatory domain groups along with flags specific to that regulatory domain.

Each regulatory domain group would also have an equivalent Conformance Test Limit (CTL) group. There are 3 CTL groups:

  • CTL_FCC = 0x10
  • CTL_MKK = 0x40
  • CTL_ETSI = 0x30

The CTL group is used internally by the driver to use the appropriate CTL index in the EEPROM to figure out the max regulatory EIRP. The CTL indexes always have a defined regulatory max EIRP and are programmed into the EEPROM. The CTL index maps frequency ranges to a specific max EIRP. This CTL index max EIRP is also used to ensure the device will not use an EIRP higher than should be used without damaging the card.

EEPROM world regulatory domain

Atheros EEPROM can use 12 custom world regulatory domains:

  • WOR0_WORLD = 0x60
  • WOR1_WORLD = 0x61
  • WOR2_WORLD = 0x62
  • WOR3_WORLD = 0x63
  • WOR4_WORLD = 0x64
  • WOR5_ETSIC = 0x65
  • WOR01_WORLD = 0x66
  • WOR02_WORLD = 0x67
  • EU1_WORLD = 0x68
  • WOR9_WORLD = 0x69
  • WORA_WORLD = 0x6A
  • WORB_WORLD = 0x6B

EEPROM ISO-3166-1-numeric code

The Atheros EEPROM regulatory domain can contain an ISO-3166-1-numeric country code. This may or not match the exact ISO3166-1-numeric country code, but usually does. Because it may not always match for the new regulatory infrastructure used in Linux we map the country to the ISO-3166-alpha2 country code.

Examples of possible country code numbers a card EEPROM can be programmed with:

  • CTRY_IRAN = 364
  • CTRY_IRAQ = 368
  • CTRY_IRELAND = 372
  • CTRY_ISRAEL = 376
  • CTRY_ITALY = 380
  • CTRY_JAMAICA = 388

When a country regulatory domain is used in the EEPROM the card will also have the COUNTRY_ERD_FLAG (0x8000) set to indicate the EEPROM has a country code. Without this the assumption is a regulatory pair group has been programmed in the EEPROM.

EEPROM regulatory pairs

The Atheros EEPROM can use a regulatory pair group. Examples of regulatory pair groups:

  • MKK1_MKKA = 0x40
  • ETSI1_WORLD = 0x37
  • FCC1_FCCA = 0x10
  • WOR02_WORLD = 0x67

The old way

The old way was to define all band groups (5 GHz and 2 GHz) in the driver code. Each band group would have a set of defined frequency ranges. ((this documentation section could be extended further))

The new way

We have extracted the regulatory domain definitions per ISO3166-alpha2 and converted them to human legible ASCII text file, used by the new Linux regulatory infrastructure. Each country therefore has a db.txt entry such as:

country EC:
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 20), (6, 17)
        (5250 - 5330 @ 20), (6, 23), DFS
        (5735 - 5835 @ 20), (6, 30)

The custom regulatory domains are kept statically as part of the driver. The custom regulatory domains are the 12 custom world regulatory domains.

Regulatory pair regulatory domains are mapped to the first ISO-3166-alpha2 country.

Driver initialization

The device programmed EEPROM is read. We then determine if the regulatory domain code is a country regulatory domain COUNTRY_ERD_FLAG (0x8000) or a regulatory pair. Based on that, we determine whether we use an ISO3166-alpha2 country code for a regulatory_hint() or we use a static world regulatory domain.

This is a static dump of the old wiki, taken after locking it in January 2015. The new wiki is at
versions of this page: last, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1