''Part of the WritingPortableDrivers section''<<BR>>

As we saw in the example in InternalKernelDataTypes taken from {{{drivers/char/serial.c}}}, you can ask the kernel for a memory page. The size of a memory page is not always 4KB of data (as it is on i386). If you are going to be referencing memory pages, you need to use the {{{PAGE_SHIFT}}} and {{{PAGE_SIZE }}}defines.

{{{PAGE_SHIFT}}} is the number of bits to shift one bit left to get the {{{PAGE_SIZE}}} value. Different architectures define this to different values. The table below shows a short list of some architectures and the values of {{{PAGE_SHIFT}}} and the resulting value for {{{PAGE_SIZE}}}.

||Architecture||PAGE_SHIFT||PAGE_SIZE||
||i386||12||4K||
||MIPS||12||4K||
||Alpha||13||8K||
||m68k||12||4K||
||m68k||13||8K||
||ARM||12||4K||
||ARM||14||16K||
||ARM||15||32K||
||IA-64||12||4K||
||IA-64||13||8K||
||IA-64||14||16K||
||IA-64||16||64K||


Even on the same base architecture type, you can have different page sizes. This depends sometimes on a configuration option (like IA-64) or is due to different variants of the processor type (like on ARM).

The code snippet from {{{drivers/usb/class/audio.c}}} below shows how {{{PAGE_SHIFT}}} and {{{PAGE_SIZE}}} are used when accessing memory directly:
{{{
#!cplusplus
static int dmabuf_mmap(...)
{
        size >>= PAGE_SHIFT;
        for(nr = 0; nr < size; nr++)
                if (!db->sgbuf[nr])
                        return -EINVAL;
        db->mapped = 1;
        for (nr = 0; nr < size; nr++) {
                unsigned long pfn;

                pfn = virt_to_phys(db->sgbuf[nr]) >> PAGE_SHIFT;
                if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, prot))
                        return -EAGAIN;
                start += PAGE_SIZE;
        }
        return 0;
}
}}}