1709Swollman================================================
217210SpstGeneric bitfield packing and unpacking functions
3709Swollman================================================
437Srgrimes
537SrgrimesProblem statement
637Srgrimes-----------------
737Srgrimes
837SrgrimesWhen working with hardware, one has to choose between several approaches of
937Srgrimesinterfacing with it.
108460SjkhOne can memory-map a pointer to a carefully crafted struct over the hardware
118460Sjkhdevice's memory region, and access its fields as struct members (potentially
128460Sjkhdeclared as bitfields). But writing code this way would make it less portable,
138460Sjkhdue to potential endianness mismatches between the CPU and the hardware device.
1437SrgrimesAdditionally, one has to pay close attention when translating register
1537Srgrimesdefinitions from the hardware documentation into bit field indices for the
1637Srgrimesstructs. Also, some hardware (typically networking equipment) tends to group
1737Srgrimesits register fields in ways that violate any reasonable word boundaries
1837Srgrimes(sometimes even 64 bit ones). This creates the inconvenience of having to
1937Srgrimesdefine "high" and "low" portions of register fields within the struct.
2037SrgrimesA more robust alternative to struct field definitions would be to extract the
2137Srgrimesrequired fields by shifting the appropriate number of bits. But this would
2237Srgrimesstill not protect from endianness mismatches, except if all memory accesses
2337Srgrimeswere performed byte-by-byte. Also the code can easily get cluttered, and the
2437Srgrimeshigh-level idea might get lost among the many bit shifts required.
2515568SasamiMany drivers take the bit-shifting approach and then attempt to reduce the
2615568Sasamiclutter with tailored macros, but more often than not these macros take
2715568Sasamishortcuts that still prevent the code from being truly portable.
2815568Sasami
2915568SasamiThe solution
3015568Sasami------------
313843Sdg
323843SdgThis API deals with 2 basic operations:
332164Sdg
3437Srgrimes  - Packing a CPU-usable number into a memory buffer (with hardware
3537Srgrimes    constraints/quirks)
3637Srgrimes  - Unpacking a memory buffer (which has hardware constraints/quirks)
3737Srgrimes    into a CPU-usable number.
3837Srgrimes
3937SrgrimesThe API offers an abstraction over said hardware constraints and quirks,
4037Srgrimesover CPU endianness and therefore between possible mismatches between
4137Srgrimesthe two.
4237Srgrimes
4337SrgrimesThe basic unit of these API functions is the u64. From the CPU's
4437Srgrimesperspective, bit 63 always means bit offset 7 of byte 7, albeit only
4537Srgrimeslogically. The question is: where do we lay this bit out in memory?
4637Srgrimes
4737SrgrimesThe following examples cover the memory layout of a packed u64 field.
4837SrgrimesThe byte offsets in the packed buffer are always implicitly 0, 1, ... 7.
4937SrgrimesWhat the examples show is where the logical bytes and bits sit.
5037Srgrimes
5137Srgrimes1. Normally (no quirks), we would do it like this:
5237Srgrimes
5337Srgrimes::
5437Srgrimes
5537Srgrimes  63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
5637Srgrimes  7                       6                       5                        4
5737Srgrimes  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
5837Srgrimes  3                       2                       1                        0
5937Srgrimes
6037SrgrimesThat is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the
6137SrgrimesLSByte (0) of the u64 sits at memory offset 7.
6237SrgrimesThis corresponds to what most folks would regard to as "big endian", where
6337Srgrimesbit i corresponds to the number 2^i. This is also referred to in the code
6437Srgrimescomments as "logical" notation.
652164Sdg
662164Sdg
6737Srgrimes2. If QUIRK_MSB_ON_THE_RIGHT is set, we do it like this:
6837Srgrimes
6937Srgrimes::
7037Srgrimes
713036Sdg  56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39
723036Sdg  7                       6                        5                       4
733036Sdg  24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7
748530Sdg  3                       2                        1                       0
758530Sdg
768530SdgThat is, QUIRK_MSB_ON_THE_RIGHT does not affect byte positioning, but
778530Sdginverts bit offsets inside a byte.
781692Sphk
7937Srgrimes
808530Sdg3. If QUIRK_LITTLE_ENDIAN is set, we do it like this:
8137Srgrimes
828530Sdg::
838530Sdg
848530Sdg  39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56
858530Sdg  4                       5                       6                       7
8637Srgrimes  7  6  5  4  3  2  1  0  15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
874091Sache  0                       1                       2                       3
88872Sache
897219SjkhTherefore, QUIRK_LITTLE_ENDIAN means that inside the memory region, every
907219Sjkhbyte from each 4-byte word is placed at its mirrored position compared to
917219Sjkhthe boundary of that word.
927219Sjkh
937219Sjkh4. If QUIRK_MSB_ON_THE_RIGHT and QUIRK_LITTLE_ENDIAN are both set, we do it
941675Sache   like this:
957219Sjkh
967293Sjkh::
971675Sache
981675Sache  32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
9914596Snate  4                       5                       6                       7
10014624Snate  0  1  2  3  4  5  6  7  8   9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
10114624Snate  0                       1                       2                       3
10214596Snate
10314596Snate
1047487Srgrimes5. If just QUIRK_LSW32_IS_FIRST is set, we do it like this:
1057460Sjkh
1067750Srgrimes::
1077460Sjkh
1087460Sjkh  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
1098540Srgrimes  3                       2                       1                        0
1107487Srgrimes  63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
1117487Srgrimes  7                       6                       5                        4
1127487Srgrimes
1137487SrgrimesIn this case the 8 byte memory region is interpreted as follows: first
1147487Srgrimes4 bytes correspond to the least significant 4-byte word, next 4 bytes to
1157487Srgrimesthe more significant 4-byte word.
1167487Srgrimes
1177761Sache
1187487Srgrimes6. If QUIRK_LSW32_IS_FIRST and QUIRK_MSB_ON_THE_RIGHT are set, we do it like
11915684Sjkh   this:
1207487Srgrimes
12116588Sjoerg::
12216588Sjoerg
12316588Sjoerg  24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7
12416588Sjoerg  3                       2                        1                       0
12516588Sjoerg  56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39
12616588Sjoerg  7                       6                        5                       4
12716588Sjoerg
12816588Sjoerg
12916588Sjoerg7. If QUIRK_LSW32_IS_FIRST and QUIRK_LITTLE_ENDIAN are set, it looks like
1307487Srgrimes   this:
1317487Srgrimes
1327487Srgrimes::
1337487Srgrimes
1347487Srgrimes  7  6  5  4  3  2  1  0  15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
1357487Srgrimes  0                       1                       2                       3
1367487Srgrimes  39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56
13716588Sjoerg  4                       5                       6                       7
13816588Sjoerg
13916588Sjoerg
14016588Sjoerg8. If QUIRK_LSW32_IS_FIRST, QUIRK_LITTLE_ENDIAN and QUIRK_MSB_ON_THE_RIGHT
14116588Sjoerg   are set, it looks like this:
14216588Sjoerg
14316588Sjoerg::
14416588Sjoerg
1459305Sbde  0  1  2  3  4  5  6  7  8   9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
1469305Sbde  0                       1                       2                       3
1479305Sbde  32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
1489305Sbde  4                       5                       6                       7
1499305Sbde
1507487Srgrimes
1517487SrgrimesWe always think of our offsets as if there were no quirk, and we translate
1527487Srgrimesthem afterwards, before accessing the memory region.
1537487Srgrimes
1547487SrgrimesIntended use
1557487Srgrimes------------
1567487Srgrimes
1577487SrgrimesDrivers that opt to use this API first need to identify which of the above 3
1587487Srgrimesquirk combinations (for a total of 8) match what the hardware documentation
1597487Srgrimesdescribes. Then they should wrap the packing() function, creating a new
1607487Srgrimesxxx_packing() that calls it using the proper QUIRK_* one-hot bits set.
1617487Srgrimes
1627487SrgrimesThe packing() function returns an int-encoded error code, which protects the
1637487Srgrimesprogrammer against incorrect API use.  The errors are not expected to occur
1647487Srgrimesduring runtime, therefore it is reasonable for xxx_packing() to return void
1657487Srgrimesand simply swallow those errors. Optionally it can dump stack or print the
1667487Srgrimeserror description.
1677487Srgrimes