1devmap(9E) Driver Entry Points devmap(9E)
2
3
4
6 devmap - validate and translate virtual mapping for memory mapped
7 device
8
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
20 Solaris DDI specific (Solaris DDI).
21
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
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
128 0 Successful completion.
129
130
131 Non-zero An error occurred.
132
133
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
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)