#include <sys/types.h> #include <sys/cred.h> #include <sys/mman.h> #include <sys/ddi.h> #include <sys/sunddi.h>
int prefixmmap(dev_t dev, off_t off, int prot);
Architecture independent level 1 (DDI/DKI).
The mmap(9E) entry point is called as a result of an mmap(2) system call, and also as a result of a page fault. mmap(9E) is called to translate the offset off in device memory to the corresponding physical page frame number.
The mmap(9E) entry point checks if the offset off is within the range of pages exported by the device. For example, a device that has 512 bytes of memory that can be mapped into user space should not support offsets greater than 512. If the offset does not exist, then -1 is returned. If the offset does exist, mmap(9E) returns the value returned by hat_getkpfnum(9F) for the physical page in device memory containing the offset off.
hat_getkpfnum(9F) accepts a kernel virtual address as an argument. A kernel virtual address can be obtained by calling ddi_map_regs(9F) in the driver’s attach(9E) routine. The corresponding ddi_unmap_regs(9F) call can be made in the driver’s detach(9E) routine. Refer to the EXAMPLES section below for more information.
mmap(9E) should only be supported for memory-mapped devices. See the segmap(9E) and ddi_mapdev(9F) reference pages for further information on memory-mapped device drivers.
struct reg { char csr; char data; }; struct xxstate { ... struct reg *regp ... }; struct xxstate *xsp; ... static int xxmmap(dev_t dev, off_t off, int prot) { int instance; struct xxstate *xsp; /* No write access */ if (prot & PROT_WRITE) return (-1); instance = getminor(dev); xsp = ddi_get_soft_state(statep, instance); if (xsp == NULL) return (-1); /* check for a valid offset */ if ( off is invalid ) return (-1); return (hat_getkpfnum (xsp->regp->csr + off)); }
One alternative is to create a mapping for only the first page of device memory in attach(9E) . If the device memory is contiguous, a kernel page frame number may be obtained by calling hat_getkpfnum(9F) with the kernel virtual address of the first page of device memory and adding the desired page offset to the result. The page offset may be obtained by converting the byte offset off to pages (see ddi_btop(9F) ).
Another alternative is to call ddi_map_regs(9F) and ddi_unmap_regs(9F) in mmap. These function calls would bracket the call to hat_getkpfnum(9F) .
However, note that the above alternatives may not work in all cases. The existence of intermediate nexus devices with memory management unit translation resources which are not locked down may cause unexpected and undefined behavior.