Driver Entry Points devmap(9E)
NAME
devmap - validate and translate virtual mapping for memory
mapped device
SYNOPSIS
#include
#include
int prefixdevmap(devt dev, devmapcookiet dhp, offsett off,
sizet len, sizet *maplen, uintt model);
INTERFACE LEVEL
Solaris DI specific (Solaris DI).
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 validated. 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 dev-
map 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 DEVMAP
SunOS 5.11 Last change: 15 Jan 1997 1
Driver Entry Points devmap(9E)
is set in the cbflag field of the cbops(9S) structure, and
any of the following conditions apply:
o ddidevmapsegmap(9F) is used as the segmap(9E)
entry point.
o segmap(9E) entry point is set to NUL.
o mmap(9E) entry point is set to NUL.
Otherwise EINVAL will be returned to mmap(2).
Device drivers should use devmap() to validate the user map-
pings to the device, to translate the logical offset, off,
to the corresponding physical offset within the device
address space, and to pass the mapping information to the
system for setting up the mapping.
dhp is a device mapping handle that the system uses to
describe a mapping 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 contains
multiple physically discontiguous memory regions).
model returns the C Language Type Model which the current
thread expects. It is set to DIMODELILP32 if the current
thread expects 32-bit ( ILP32) semantics, or DIMODELP64
if the current thread expects 64-bit ( LP64) semantics.
model is used in combination with ddimodelconvertfrom(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
exporting 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 repeat-
edly call devmap() until the original mapping length is
satisfied. The driver sets *maplen to the validated length
which must be either less than or equal to len.
SunOS 5.11 Last change: 15 Jan 1997 2
Driver Entry Points devmap(9E)
The devmap() entry point must initialize the mapping parame-
ters before passing them to the system through either
devmapdevmemsetup(9F) (if the memory being mapped is dev-
ice memory) or devmapumemsetup(9F) (if the memory being
mapped is kernel memory). The devmap() entry point initial-
izes the mapping parameters by mapping the control callback
structure (see devmapcallbackctl(9S)), the device access
attributes, mapping length, maximum protection possible for
the mapping, and optional mapping flags. See
devmapdevmemsetup(9F) and devmapumemsetup(9F) for
further information on initializing the mapping parameters.
The system will copy the driver's devmapcallbackctl(9S)
data into its private memory so the drivers do not need to
keep the data structure after the return from either
devmapdevmemsetup(9F) or devmapumemsetup(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 devmapdevmemsetup(9F).
For kernel memory mapping, the system selects a user virtual
address that is aligned with the kernel address being mapped
for cache coherence.
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 devmapdevmemsetup(9F) with the register number,
rnumber, and the offset within the register, roff. For map-
ping kernel memory, the driver must first allocate the ker-
nel memory using ddiumemalloc(9F). For example,
ddiumemalloc(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 ddisoftstate(9F). devmap() passes the
cookie obtained from ddiumemalloc(9F) and the offset
within the allocated kernel memory to devmapumemsetup(9F).
SunOS 5.11 Last change: 15 Jan 1997 3
Driver Entry Points devmap(9E)
The corresponding ddiumemfree(9F) can be made in the
detach(9E) routine to free up the kernel memory.
...
#define MAPINGSIZE 0x2000 /* size of the mapping */
#define MAPINGSTART 0x70000000 /* logical offset at beginning
of the mapping */
static
struct devmapcallbackctl xxmapops = {
DEVMAPOPSREV, /* devmapops version number */
xxmapmap, /* devmapops map routine */
xxmapaccess, /* devmapops access routine */
xxmapdup, /* devmapops dup routine */
xxmapunmap, /* devmapops unmap routine */
};
static int
xxdevmap(devt dev, devmapcookiet dhp, offsett off, sizet len,
sizet *maplen, uintt model)
{
int instance;
struct xxstate *xsp;
struct ddideviceaccattr *endianattr;
struct devmapcallbackctl *callbackops = NUL;
ddiumemcookiet cookie;
devinfot *dip;
offsett roff;
offsett koff;
uintt rnumber;
uintt maxprot;
uintt flags = 0;
sizet length;
int err;
/* get device soft state */
instance = getminor(dev);
xsp = ddigetsoftstate(statep, instance);
if (xsp == NUL)
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 = MAPINGSTART ] MAPINGSIZE - off;
SunOS 5.11 Last change: 15 Jan 1997 4
Driver Entry Points devmap(9E)
/* device access attributes */
endianattr = xsp->endianattr;
if ( off is referring to a device memory. ) {
/* assign register related parameters */
rnumber = X; /* index to register set at off */
roff = X; /* offset of rnumber at local bus */
callbackops = &xxmapops; /* do all callbacks for this mapping */
maxprot = PROTAL; /* allowing all access */
if ((err = devmapdevmemsetup(dhp, dip, callbackops, rnumber, roff,
length, maxprot, flags, endianattr)) < 0)
return (err);
} else if ( off is referring to a kernel memory.) {
cookie = xsp->cookie; /* cookie is obtained from
ddiumemalloc(9F) */
koff = X; /* offset within the kernel memory. */
callbackops = NUL; /* don't do callback for this mapping */
maxprot = PROTAL; /* allowing all access */
if ((err = devmapumemsetup(dhp, dip, callbackops, cookie, koff,
length, maxprot, flags, endianattr)) < 0)
return (err);
}
*maplen = length;
return (0);
}
SEE ALSO
mmap(2), attach(9E), detach(9E), mmap(9E), segmap(9E),
ddidevmapsegmap(9F), ddimodelconvertfrom(9F),
ddisoftstate(9F), ddiumemalloc(9F), ddiumemfree(9F),
devmapdevmemsetup(9F), devmapsetup(9F),
devmapumemsetup(9F), cbops(9S), devmapcallbackctl(9S)
Writing Device Drivers
SunOS 5.11 Last change: 15 Jan 1997 5
|