1devmap(9E)                    Driver Entry Points                   devmap(9E)
2
3
4

NAME

6       devmap  -  validate  and  translate  virtual  mapping for memory mapped
7       device
8

SYNOPSIS

10       #include <sys/ddi.h>
11       #include <sys/sunddi.h>
12
13
14
15       int prefixdevmap(dev_t dev, devmap_cookie_t dhp, offset_t off,
16            size_t len, size_t *maplen, uint_t model);
17
18

INTERFACE LEVEL

20       Solaris DDI specific (Solaris DDI).
21

PARAMETERS

23       dev        Device whose memory is to be mapped.
24
25
26       dhp        An opaque mapping handle that the system  uses  to  describe
27                  the mapping.
28
29
30       off        User  offset  within  the logical device memory at which the
31                  mapping begins.
32
33
34       len        Length (in bytes) of the mapping to be mapped.
35
36
37       maplen     Pointer to length (in bytes) of mapping that has been  vali‐
38                  dated. maplen is less than or equal to  len.
39
40
41       model      The data model type of the current thread.
42
43

DESCRIPTION

45       devmap()  is  a  required  entry point for character drivers supporting
46       memory-mapped devices if the drivers use the devmap framework to set up
47       the mapping. A memory mapped device has memory  that can be mapped into
48       a process's address space. The mmap(2) system call, when applied  to  a
49       character  special  file,  allows  this device memory to be mapped into
50       user space for direct access by the user applications.
51
52
53       As a result of a mmap(2) system call, the  system  calls  the  devmap()
54       entry  point  during  the  mapping  setup  when  D_DEVMAP is set in the
55       cb_flag field of the cb_ops(9S) structure, and  any  of  the  following
56       conditions apply:
57
58           o      ddi_devmap_segmap(9F) is used as the segmap(9E) entry point.
59
60           o      segmap(9E) entry point is set to NULL.
61
62           o      mmap(9E) entry point is set to NULL.
63
64
65       Otherwise EINVAL will be returned to mmap(2).
66
67
68       Device drivers should use devmap() to validate the user mappings to the
69       device, to translate the logical offset,   off,  to  the  corresponding
70       physical  offset  within the device address space, and to pass the map‐
71       ping information to the system for setting up the mapping.
72
73
74       dhp is a device mapping handle that the system uses to describe a  map‐
75       ping to a memory that is either contiguous in physical address space or
76       in kernel virtual address space. The system may create multiple mapping
77       handles  in  one  mmap(2) system call (for example, if the mapping con‐
78       tains multiple physically discontiguous memory regions).
79
80
81       model returns the C  Language  Type  Model  which  the  current  thread
82       expects.   It  is  set to DDI_MODEL_ILP32 if the current thread expects
83       32-bit ( ILP32) semantics, or  DDI_MODEL_LP64  if  the  current  thread
84       expects  64-bit  (  LP64)  semantics. model is used in combination with
85       ddi_model_convert_from(9F) to determine whether there is a  data  model
86       mismatch  between  the current thread and the device driver. The device
87       driver might have to adjust the shape of data structures before export‐
88       ing them to a user thread which supports a different data model.
89
90
91       devmap() should return EINVAL if the logical offset, off, is out of the
92       range of memory exported by the device to user  space.  If  off  +  len
93       exceeds  the range of the contiguous memory, devmap() should return the
94       length from  off to the end of the contiguous memory region. The system
95       will repeatedly call devmap() until the original mapping length is sat‐
96       isfied. The driver sets *maplen to the validated length which  must  be
97       either less than or equal to len.
98
99
100       The  devmap() entry point must initialize the mapping parameters before
101       passing them to the system through either  devmap_devmem_setup(9F)  (if
102       the  memory being mapped is device memory) or devmap_umem_setup(9F) (if
103       the memory being mapped is kernel memory).  The  devmap()  entry  point
104       initializes  the  mapping  parameters  by  mapping the control callback
105       structure (see devmap_callback_ctl(9S)), the device access  attributes,
106       mapping  length,  maximum  protection  possible  for  the  mapping, and
107       optional    mapping    flags.    See    devmap_devmem_setup(9F)     and
108       devmap_umem_setup(9F)  for further information on initializing the map‐
109       ping parameters.
110
111
112       The system will copy the driver's devmap_callback_ctl(9S) data into its
113       private  memory  so  the drivers do not need to keep the data structure
114       after   the   return    from    either    devmap_devmem_setup(9F)    or
115       devmap_umem_setup(9F).
116
117
118       For device mappings, the system establishes the mapping to the physical
119       address that corresponds to off by passing the register number and  the
120       offset within the register address space to  devmap_devmem_setup(9F).
121
122
123       For  kernel  memory  mapping, the system selects a user virtual address
124       that is aligned with the kernel address being mapped for  cache  coher‐
125       ence.
126

RETURN VALUES

128       0           Successful completion.
129
130
131       Non-zero    An error occurred.
132
133

EXAMPLES

135       Example 1 Implementing the devmap() Entry Point
136
137
138       The  following  is  an  example  of the implementation for the devmap()
139       entry   point.   For   mapping   device    memory,    devmap()    calls
140       devmap_devmem_setup(9F) with the register number, rnumber, and the off‐
141       set within the register, roff. For mapping kernel  memory,  the  driver
142       must  first  allocate  the  kernel memory using ddi_umem_alloc(9F). For
143       example, ddi_umem_alloc(9F) can be called in  the  attach(9E)  routine.
144       The  resulting  kernel memory cookie is stored in the driver soft state
145       structure, which is accessible  from  the  devmap()  entry  point.  See
146       ddi_soft_state(9F).   devmap()   passes   the   cookie   obtained  from
147       ddi_umem_alloc(9F) and the offset within the allocated kernel memory to
148       devmap_umem_setup(9F).  The corresponding ddi_umem_free(9F) can be made
149       in the detach(9E) routine to free up the kernel memory.
150
151
152         ...
153         #define MAPPING_SIZE 0x2000        /* size of the mapping */
154         #define MAPPING_START 0x70000000   /* logical offset at beginning
155                                               of the mapping */
156         static
157         struct devmap_callback_ctl xxmap_ops = {
158                 DEVMAP_OPS_REV,                /* devmap_ops version number */
159                 xxmap_map,                     /* devmap_ops map routine */
160                 xxmap_access,                  /* devmap_ops access routine */
161                 xxmap_dup,                     /* devmap_ops dup routine */
162                 xxmap_unmap,                   /* devmap_ops unmap routine  */
163         };
164
165
166         static int
167         xxdevmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
168            size_t *maplen, uint_t model)
169         {
170            int    instance;
171            struct xxstate *xsp;
172            struct ddi_device_acc_attr *endian_attr;
173            struct devmap_callback_ctl *callbackops = NULL;
174            ddi_umem_cookie_t cookie;
175            dev_info_t *dip;
176            offset_t   roff;
177            offset_t   koff;
178            uint_t rnumber;
179            uint_t maxprot;
180            uint_t flags = 0;
181            size_t length;
182            int    err;
183
184            /* get device soft state */
185            instance = getminor(dev);
186            xsp = ddi_get_soft_state(statep, instance);
187            if (xsp == NULL)
188               return (-1);
189
190            dip = xsp->dip;
191            /* check for a valid offset */
192            if ( off is invalid )
193               return (-1);
194            /* check if len is within the range of contiguous memory */
195            if ( (off + len) is contiguous.)
196                length = len;
197            else
198                length = MAPPING_START + MAPPING_SIZE - off;
199
200            /* device access attributes */
201            endian_attr = xsp->endian_attr;
202
203            if (  off is referring to a device memory.  ) {
204                                          /* assign register related parameters */
205               rnumber = XXX;             /* index to register set at off */
206               roff = XXX;                /* offset of rnumber at local bus */
207               callbackops = &xxmap_ops;  /* do all callbacks for this mapping */
208               maxprot = PROT_ALL;        /* allowing all access */
209               if ((err = devmap_devmem_setup(dhp, dip, callbackops, rnumber, roff,
210                        length, maxprot, flags, endian_attr)) < 0)
211
212
213                   return (err);
214
215            } else if ( off is referring to a kernel memory.) {
216               cookie = xsp->cookie;      /* cookie is obtained from
217                                             ddi_umem_alloc(9F) */
218               koff = XXX;                /* offset within the kernel memory. */
219               callbackops = NULL;        /* don't do callback for this mapping */
220               maxprot = PROT_ALL;        /* allowing all access */
221               if ((err = devmap_umem_setup(dhp, dip, callbackops, cookie, koff,
222                        length, maxprot, flags, endian_attr)) < 0)
223                  return (err);
224           }
225
226                  *maplen = length;
227             return (0);
228         }
229
230

SEE ALSO

232       mmap(2),     attach(9E),     detach(9E),     mmap(9E),      segmap(9E),
233       ddi_devmap_segmap(9F),  ddi_model_convert_from(9F), ddi_soft_state(9F),
234       ddi_umem_alloc(9F),     ddi_umem_free(9F),     devmap_devmem_setup(9F),
235       devmap_setup(9F),   devmap_umem_setup(9F),   cb_ops(9S),   devmap_call‐
236       back_ctl(9S)
237
238
239       Writing Device Drivers
240
241
242
243SunOS 5.11                        15 Jan 1997                       devmap(9E)
Impressum