''Part of the WritingPortableDrivers section''[[BR]] == Memory Issues == 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; } }}}