1mmap(9E) Driver Entry Points mmap(9E)
2
3
4
6 mmap - check virtual mapping for memory mapped device
7
9 #include <sys/types.h>
10 #include <sys/cred.h>
11 #include <sys/mman.h>
12 #include <sys/ddi.h>
13
14
15
16 int prefixmmap(dev_t dev, off_t off, int prot);
17
18
20 This interface is obsolete. devmap(9E) should be used instead.
21
23 dev Device whose memory is to be mapped.
24
25
26 off Offset within device memory at which mapping begins.
27
28
29 prot A bit field that specifies the protections this page of memory
30 will receive. Possible settings are:
31
32 PROT_READ Read access will be granted.
33
34
35 PROT_WRITE Write access will be granted.
36
37
38 PROT_EXEC Execute access will be granted.
39
40
41 PROT_USER User-level access will be granted.
42
43
44 PROT_ALL All access will be granted.
45
46
47
49 Future releases of Solaris will provide this function for binary and
50 source compatibility. However, for increased functionality, use
51 devmap(9E) instead. See devmap(9E) for details.
52
53
54 The mmap() entry point is a required entry point for character drivers
55 supporting memory-mapped devices. A memory mapped device has memory
56 that can be mapped into a process's address space. The mmap(2) system
57 call, when applied to a character special file, allows this device mem‐
58 ory to be mapped into user space for direct access by the user applica‐
59 tion.
60
61
62 The mmap() entry point is called as a result of an mmap(2) system call,
63 and also as a result of a page fault. mmap() is called to translate the
64 offset off in device memory to the corresponding physical page frame
65 number.
66
67
68 The mmap() entry point checks if the offset off is within the range of
69 pages exported by the device. For example, a device that has 512 bytes
70 of memory that can be mapped into user space should not support offsets
71 greater than 512. If the offset does not exist, then -1 is returned. If
72 the offset does exist, mmap() returns the value returned by
73 hat_getkpfnum(9F) for the physical page in device memory containing the
74 offset off.
75
76
77 hat_getkpfnum(9F) accepts a kernel virtual address as an argument. A
78 kernel virtual address can be obtained by calling ddi_regs_map_set‐
79 up(9F) in the driver's attach(9E) routine. The corresponding
80 ddi_regs_map_free(9F) call can be made in the driver's detach(9E) rou‐
81 tine. Refer to the example below mmap Entry Point for more information.
82
83
84 mmap() should only be supported for memory-mapped devices. See
85 segmap(9E) for further information on memory-mapped device drivers.
86
87
88 If a device driver shares data structures with the application, for
89 example through exported kernel memory, and the driver gets recompiled
90 for a 64-bit kernel but the application remains 32-bit, the binary lay‐
91 out of any data structures will be incompatible if they contain longs
92 or pointers. The driver needs to know whether there is a model mismatch
93 between the current thread and the kernel and take necessary action.
94 ddi_mmap_get_model(9F) can be use to get the C Language Type Model
95 which the current thread expects. In combination with ddi_model_con‐
96 vert_from(9F) the driver can determine whether there is a data model
97 mismatch between the current thread and the device driver. The device
98 driver might have to adjust the shape of data structures before export‐
99 ing them to a user thread which supports a different data model. See
100 ddi_mmap_get_model(9F) for an example.
101
103 If the protection and offset are valid for the device, the driver
104 should return the value returned by hat_getkpfnum(9F), for the page at
105 offset off in the device's memory. If not, -1 should be returned.
106
108 Example 1 mmap() Entry Point
109
110
111 The following is an example of the mmap() entry point. If offset off is
112 valid, hat_getkpfnum(9F) is called to obtain the page frame number cor‐
113 responding to this offset in the device's memory. In this example,
114 xsp→regp→csr is a kernel virtual address which maps to device memory.
115 ddi_regs_map_setup(9F) can be used to obtain this address. For example,
116 ddi_regs_map_setup(9F) can be called in the driver's attach(9E) rou‐
117 tine. The resulting kernel virtual address is stored in the xxstate
118 structure, which is accessible from the driver's mmap() entry point.
119 See ddi_soft_state(9F). The corresponding ddi_regs_map_free(9F) call
120 can be made in the driver's detach(9E) routine.
121
122
123 struct reg {
124 uint8_t csr;
125 uint8_t data;
126 };
127 struct xxstate {
128 ...
129 struct reg *regp
130 ...
131 };
132
133 struct xxstate *xsp;
134 ...
135
136 static int
137 xxmmap(dev_t dev, off_t off, int prot)
138 {
139 int instance;
140 struct xxstate *xsp;
141
142 /* No write access */
143 if (prot & PROT_WRITE)
144 return (-1);
145
146 instance = getminor(dev);
147 xsp = ddi_get_soft_state(statep, instance);
148 if (xsp == NULL)
149 return (-1);
150
151 /* check for a valid offset */
152 if ( off is invalid )
153 return (-1);
154 return (hat_getkpfnum (xsp->regp->csr + off));
155 }
156
157
159 See attributes(5) for a description of the following attributes:
160
161
162
163
164 ┌─────────────────────────────┬─────────────────────────────┐
165 │ ATTRIBUTE TYPE │ ATTRIBUTE VALUE │
166 ├─────────────────────────────┼─────────────────────────────┤
167 │Stability Level │Obsolete │
168 └─────────────────────────────┴─────────────────────────────┘
169
171 mmap(2), attributes(5), attach(9E), detach(9E), devmap(9E), segmap(9E),
172 ddi_btop(9F), ddi_get_soft_state(9F), ddi_mmap_get_model(9F),
173 ddi_model_convert_from(9F), ddi_regs_map_free(9F), ddi_regs_map_set‐
174 up(9F), ddi_soft_state(9F), devmap_setup(9F), getminor(9F),
175 hat_getkpfnum(9F)
176
177
178 Writing Device Drivers
179
181 For some devices, mapping device memory in the driver's attach(9E) rou‐
182 tine and unmapping device memory in the driver's detach(9E) routine is
183 a sizeable drain on system resources. This is especially true for
184 devices with a large amount of physical address space.
185
186
187 One alternative is to create a mapping for only the first page of
188 device memory in attach(9E). If the device memory is contiguous, a ker‐
189 nel page frame number may be obtained by calling hat_getkpfnum(9F) with
190 the kernel virtual address of the first page of device memory and
191 adding the desired page offset to the result. The page offset may be
192 obtained by converting the byte offset off to pages. See ddi_btop(9F).
193
194
195 Another alternative is to call ddi_regs_map_setup(9F) and
196 ddi_regs_map_free(9F) in mmap(). These function calls would bracket the
197 call to hat_getkpfnum(9F).
198
199
200 However, note that the above alternatives may not work in all cases.
201 The existence of intermediate nexus devices with memory management unit
202 translation resources that are not locked down may cause unexpected and
203 undefined behavior.
204
205
206
207SunOS 5.11 27 Sep 2002 mmap(9E)