Writing Device Drivers

Structure Padding

A device that has a 1-byte command and status register followed by a 4-byte data register might lead to the following structure layout:

	struct device_reg {
 		uint8_t			csr;
 		uint32	_t		data;
 	};

This structure is not correct, because the compiler places padding between the two fields. For example, the SPARC processor requires each type to be on its natural boundary, which is 1-byte alignment for the csr field, but 4-byte alignment for the data field. This results in three unused bytes between the two fields. When the driver accesses a data register, it will be three bytes off. Consequently, this layout should not be used.

Finding Padding

The ANSI C offsetof(3C) macro may be used in a test program to determine the offset of each element in the structure. Knowing the offset and the size of each element, the location and size of any padding can be determined.


Example 3-2 Structure Padding

#include <sys/types.h>
#include <stdio.h>
#include <stddef.h>

struct device_reg {
	uint8_t			csr;
	uint32_t			data;
};

int main(void)
{
	printf("The offset of csr is %d, its size is %d.\n",
			offsetof(struct device_reg, csr), sizeof (uint8_t));
	printf("The offset of data is %d, its size is %d.\n",
			offsetof(struct device_reg, data), sizeof (uint32_t));
	return (0);
}

Here is a sample compilation with Sun WorkShopTM Compiler C version 4.2 and a subsequent run of the program:

test% cc -Xa c.c

test% a.out

The offset of csr is 0, its size is 1.

The offset of data is 4, its size is 4.

Be aware that padding is dependent not only on the processor but also on the compiler.