The PCMCIA core serves as a controller core just like the PCI core.
Contents
card information
The card information is built up as follows. The CIS always contains blocks of type/length/value tuples where type and length are bytes, and the length is the length of the payload of the tuple. There are functions for parsing this available in Linux.
The MAC address can be found in the CISTPL_FUNCE_LAN_NODE_ID of the FUNCE item.
Other parameters are found within the vendor defined element (0x80) which Broadcom builds up like the FUNCE element, meaning that the first byte of the element is again a subelement type. The subelement types can be found in this table:
subelement type |
meaning |
0x01 |
PCI vendor, device ID (possibly chip revision as well if 6 bytes are present instead of 4?) |
0x02 |
Board revision |
0x03 |
PA parameters (8 bytes) |
0x04 |
OEM name (8 byte NUL-padded string, empty on my card) |
0x05 |
default country code (1 byte) |
0x06 |
antennas available (bitfield, 1 byte) |
0x07 |
antenna gain |
0x08 |
board flags (low 16 bits) |
0x09 |
LED information (4 bytes) |
The PA parameters are built up as follows:
byte |
contents |
0 |
lower byte of pa0b0 |
1 |
upper byte of pa0b0 |
2 |
lower byte of pa0b1 |
3 |
upper byte of pa0b1 |
4 |
lower byte of pa0b2 |
5 |
upper byte of pa0b2 |
6 |
Idle TSSI Target (cf. SPROM) |
7 |
PA Max Power (cf. SPROM) |
mapping
The PCMCIA core provides a 0x800 byte long mapping of the core registers. In Linux you can apparently only create a mapping of size 0x1000, but only 0x800 bytes of that are usable. Now, since each core register space is always 0x1000 bytes long this means that you can directly only access the first half of the register space. To access the second part, the memory segment register is used (see below). I set the window's AccessSpeed to 250, but am not sure what the correct value would be, it seemed to work fine.
registers
The PCMCIA core provides the following registers in the CIS, as everything in CIS they are each one byte long
Offset |
Function |
0x00 |
core control |
0x80 |
alternative core control |
0x2e |
address 0 |
0x30 |
address 1 |
0x32 |
address 2 |
0x34 |
memory segment |
0x36 |
SROM control |
0x38 |
SROM data low |
0x3a |
SROM data high |
0x3c |
SROM address low |
0x3e |
SROM address low |
Example code to write the memory segment register:
req.Offset = 0x34; req.Action = CS_WRITE; req.Value = 1; pcmcia_access_configuration_register(pcmcia_device, &req);
address registers
The address registers are used to select the currently mapped core. To map a different core, write the core offset (the usual 0x18000000 + 0x1000*coreidx) to these registers as follows:
register |
part of offset |
address 0 |
(offset & 0x0000F000) >> 12 |
address 1 |
(offset & 0x00FF0000) >> 16 |
address 2 |
(offset & 0xFF000000) >> 24 |
memory segment register
This register just contains 0 or 1, 0 to access the lower half of the core register space and 1 to access the upper half.
SROM access
As described above, the configuration is actually stored in CIS so there's usually no need to access the SROM unless writing it. The SROM appears to contain 3 currently unknown words of data followed by the CIS information, the last byte is a CRC as in the regular SROM, but here the CRC covers the full 256 words.
SROM control register values:
Value |
Meaning |
0 |
idle |
1 |
write |
2 |
read |
4 |
enable write |
7 |
disable write |
8 |
done |
To execute an SROM command, write it to the SROM command register and wait until the done bit becomes set (up to 1000 tries).
In order to write the SROM, first enable writing by executing the enable write command.
Then, after waiting 500 milliseconds, write each word of the new contents to the SROM by setting the address low, address high, data low and data high registers and executing the write command. Delay 20 milliseconds after each write.
Finally disable writing again by executing the disable write command, delay 500 milliseconds afterwards.
You can read the SROM similarly, but of course no write enable/disable is necessary.
core control
This register (or the alternative one) is used to initialize the core. The alternative core control register must be used on any chip that is not a 4306 (can be determined the regular way, i.e. ChipCommon registers).
mask |
meaning |
0x80 |
core reset |
0x04 |
core irq enable |
0x01 |
core function enable |
Instead of enabling interrupts through the PCI core, they have to be enabled through the PCMCIA core. To do this, or the core control (or the alternative core control) register with core irq enable and core function enable. More setup is not required for PCMCIA.