svcadm(8)을 검색하려면 섹션에서 8 을 선택하고, 맨 페이지 이름에 svcadm을 입력하고 검색을 누른다.
devmap(9e)
devmap(9E) Driver Entry Points devmap(9E)
NAME
devmap - validate and translate virtual mapping for memory mapped
device
SYNOPSIS
#include <sys/ddi.h>
#include <sys/sunddi.h>
int prefixdevmap(dev_t dev, devmap_cookie_t dhp, offset_t off,
size_t len, size_t *maplen, uint_t model);
INTERFACE LEVEL
Solaris DDI specific (Solaris DDI).
PARAMETERS
dev Device whose memory is to be mapped.
dhp An opaque mapping handle that the system uses to describe the
mapping.
off User offset within the logical device memory at which the
mapping begins.
len Length (in bytes) of the mapping to be mapped.
maplen Pointer to length (in bytes) of mapping that has been vali‐
dated. maplen is less than or equal to len.
model The data model type of the current thread.
DESCRIPTION
devmap() is a required entry point for character drivers supporting
memory-mapped devices if the drivers use the devmap framework to set up
the mapping. A memory mapped device has memory that can be mapped into
a process's address space. The mmap(2) system call, when applied to a
character special file, allows this device memory to be mapped into
user space for direct access by the user applications.
As a result of a mmap(2) system call, the system calls the devmap()
entry point during the mapping setup when D_DEVMAP is set in the
cb_flag field of the cb_ops(9S) structure, and any of the following
conditions apply:
o ddi_devmap_segmap(9F) is used as the segmap(9E) entry point.
o segmap(9E) entry point is set to NULL.
o mmap(9E) entry point is set to NULL.
Otherwise EINVAL will be returned to mmap(2).
When the MAP_ALIGN flag is set, the system is informed that the align‐
ment of pa must be the same as addr. The alignment value in addr must
be 0 or some power of two multiple of page size as returned by
sysconf(3C). If addr is 0, the system will choose a suitable alignment.
Device drivers should use devmap() to validate the user mappings to the
device, to translate the logical offset, off, to the corresponding
physical offset within the device address space, and to pass the map‐
ping information to the system for setting up the mapping.
dhp is a device mapping handle that the system uses to describe a map‐
ping to a memory that is either contiguous in physical address space or
in kernel virtual address space. The system may create multiple mapping
handles in one mmap(2) system call (for example, if the mapping con‐
tains multiple physically discontiguous memory regions).
model returns the C Language Type Model which the current thread
expects. It is set to DDI_MODEL_ILP32 if the current thread expects
32-bit ( ILP32) semantics, or DDI_MODEL_LP64 if the current thread
expects 64-bit ( LP64) semantics. model is used in combination with
ddi_model_convert_from(9F) to determine whether there is a data model
mismatch between the current thread and the device driver. The device
driver might have to adjust the shape of data structures before export‐
ing them to a user thread which supports a different data model.
devmap() should return EINVAL if the logical offset, off, is out of the
range of memory exported by the device to user space. If off + len
exceeds the range of the contiguous memory, devmap() should return the
length from off to the end of the contiguous memory region. The system
will repeatedly call devmap() until the original mapping length is sat‐
isfied. The driver sets *maplen to the validated length which must be
either less than or equal to len.
The devmap() entry point must initialize the mapping parameters before
passing them to the system through either devmap_devmem_setup(9F) (if
the memory being mapped is device memory) or devmap_umem_setup(9F) (if
the memory being mapped is kernel memory). The devmap() entry point
initializes the mapping parameters by mapping the control callback
structure (see devmap_callback_ctl(9S)), the device access attributes,
mapping length, maximum protection possible for the mapping, and
optional mapping flags. See devmap_devmem_setup(9F) and
devmap_umem_setup(9F) for further information on initializing the map‐
ping parameters.
The system will copy the driver's devmap_callback_ctl(9S) data into its
private memory so the drivers do not need to keep the data structure
after the return from either devmap_devmem_setup(9F) or
devmap_umem_setup(9F).
For device mappings, the system establishes the mapping to the physical
address that corresponds to off by passing the register number and the
offset within the register address space to devmap_devmem_setup(9F).
For kernel memory mapping, the system selects a user virtual address
that is aligned with the kernel address being mapped for cache coher‐
ence.
RETURN VALUES
0 Successful completion.
Non-zero An error occurred.
EXAMPLES
Example 1 Implementing the devmap() Entry Point
The following is an example of the implementation for the devmap()
entry point. For mapping device memory, devmap() calls
devmap_devmem_setup(9F) with the register number, rnumber, and the off‐
set within the register, roff. For mapping kernel memory, the driver
must first allocate the kernel memory using ddi_umem_alloc(9F). For
example, ddi_umem_alloc(9F) can be called in the attach(9E) routine.
The resulting kernel memory cookie is stored in the driver soft state
structure, which is accessible from the devmap() entry point. See
ddi_soft_state(9F). devmap() passes the cookie obtained from
ddi_umem_alloc(9F) and the offset within the allocated kernel memory to
devmap_umem_setup(9F). The corresponding ddi_umem_free(9F) can be made
in the detach(9E) routine to free up the kernel memory.
...
#define MAPPING_SIZE 0x2000 /* size of the mapping */
#define MAPPING_START 0x70000000 /* logical offset at beginning
of the mapping */
static
struct devmap_callback_ctl xxmap_ops = {
DEVMAP_OPS_REV, /* devmap_ops version number */
xxmap_map, /* devmap_ops map routine */
xxmap_access, /* devmap_ops access routine */
xxmap_dup, /* devmap_ops dup routine */
xxmap_unmap, /* devmap_ops unmap routine */
};
static int
xxdevmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
size_t *maplen, uint_t model)
{
int instance;
struct xxstate *xsp;
struct ddi_device_acc_attr *endian_attr;
struct devmap_callback_ctl *callbackops = NULL;
ddi_umem_cookie_t cookie;
dev_info_t *dip;
offset_t roff;
offset_t koff;
uint_t rnumber;
uint_t maxprot;
uint_t flags = 0;
size_t length;
int err;
/* get device soft state */
instance = getminor(dev);
xsp = ddi_get_soft_state(statep, instance);
if (xsp == NULL)
return (-1);
dip = xsp->dip;
/* check for a valid offset */
if ( off is invalid )
return (-1);
/* check if len is within the range of contiguous memory */
if ( (off + len) is contiguous.)
length = len;
else
length = MAPPING_START + MAPPING_SIZE - off;
/* device access attributes */
endian_attr = xsp->endian_attr;
if ( off is referring to a device memory. ) {
/* assign register related parameters */
rnumber = XXX; /* index to register set at off */
roff = XXX; /* offset of rnumber at local bus */
callbackops = &xxmap_ops; /* do all callbacks for this mapping */
maxprot = PROT_ALL; /* allowing all access */
if ((err = devmap_devmem_setup(dhp, dip, callbackops, rnumber, roff,
length, maxprot, flags, endian_attr)) < 0)
return (err);
} else if ( off is referring to a kernel memory.) {
cookie = xsp->cookie; /* cookie is obtained from
ddi_umem_alloc(9F) */
koff = XXX; /* offset within the kernel memory. */
callbackops = NULL; /* don't do callback for this mapping */
maxprot = PROT_ALL; /* allowing all access */
if ((err = devmap_umem_setup(dhp, dip, callbackops, cookie, koff,
length, maxprot, flags, endian_attr)) < 0)
return (err);
}
*maplen = length;
return (0);
}
SEE ALSO
mmap(2), attach(9E), detach(9E), mmap(9E), segmap(9E),
ddi_devmap_segmap(9F), ddi_model_convert_from(9F), ddi_soft_state(9F),
ddi_umem_alloc(9F), ddi_umem_free(9F), devmap_devmem_setup(9F),
devmap_setup(9F), devmap_umem_setup(9F), cb_ops(9S), devmap_call‐
back_ctl(9S)
Writing Device Drivers in Oracle Solaris 11.4
Oracle Solaris 11.4 04 July 2017 devmap(9E)