1 | /* |
2 | * Copyright (c) 1998-2019 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | #ifndef _IOMEMORYCURSOR_H |
29 | #define _IOMEMORYCURSOR_H |
30 | |
31 | #include <libkern/c++/OSObject.h> |
32 | #include <libkern/c++/OSPtr.h> |
33 | #include <IOKit/IOTypes.h> |
34 | |
35 | class IOMemoryDescriptor; |
36 | |
37 | /**************************** class IOMemoryCursor ***************************/ |
38 | |
39 | /*! |
40 | * @class IOMemoryCursor |
41 | * @abstract A mechanism to convert memory references to physical addresses. |
42 | * @discussion The IOMemoryCursor declares the super class that all |
43 | * specific memory cursors must inherit from, but a memory cursor can be created without a specific format subclass by just providing a segment function to the initializers. This class does the difficult stuff of dividing a memory descriptor into a physical scatter/gather list appropriate for the target hardware. |
44 | * <br><br> |
45 | * A driver is expected to create a memory cursor and configure it to the limitations of its DMA hardware; for instance the memory cursor used by the FireWire SBP-2 protocol has a maximum physical segment size of 2^16 - 1 but the actual transfer size is unlimited. Thus it would create a cursor with a maxSegmentSize of 65535 and a maxTransfer size of UINT_MAX. It would also provide a SegmentFunction that can output a pagelist entry. |
46 | * <br><br> |
47 | * Below is the simplest example of a SegmentFunction:<br> |
48 | * void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,<br> |
49 | * void * outSegments,<br> |
50 | * UInt32 outSegmentIndex)<br> |
51 | * {<br> |
52 | * ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;<br> |
53 | * } |
54 | * |
55 | */ |
56 | class IOMemoryCursor : public OSObject |
57 | { |
58 | OSDeclareDefaultStructors(IOMemoryCursor); |
59 | |
60 | public: |
61 | /*! |
62 | * @typedef PhysicalSegment |
63 | * @discussion A physical address/length pair. |
64 | */ |
65 | struct PhysicalSegment { |
66 | IOPhysicalAddress location; |
67 | IOPhysicalLength length; |
68 | }; |
69 | |
70 | /*! @defined IOPhysicalSegment |
71 | * @discussion Backward compatibility define for the old non-class scoped type definition. See IOMemoryCursor::PhysicalSegment |
72 | */ |
73 | #define IOPhysicalSegment IOMemoryCursor::PhysicalSegment |
74 | |
75 | /*! |
76 | * @typedef SegmentFunction |
77 | * @discussion Pointer to a C function that outputs a single physical segment to an element in the array as defined by the segments and segmentIndex parameters. |
78 | * @param segment The physical address and length that is next to be output. |
79 | * @param segments Base of the output vector of DMA address length pairs. |
80 | * @param segmentIndex Index to output 'segment' in the 'segments' array. |
81 | */ |
82 | typedef void (*SegmentFunction)(PhysicalSegment segment, |
83 | void * segments, |
84 | UInt32 segmentIndex); |
85 | |
86 | /*! @defined OutputSegmentFunc |
87 | * @discussion Backward compatibility define for the old non-class scoped type definition. See IOMemoryCursor::SegmentFunction */ |
88 | #define OutputSegmentFunc IOMemoryCursor::SegmentFunction |
89 | |
90 | protected: |
91 | /*! @var outSeg The action method called when an event has been delivered */ |
92 | SegmentFunction outSeg; |
93 | |
94 | /*! @var maxSegmentSize Maximum size of one segment in a scatter/gather list */ |
95 | IOPhysicalLength maxSegmentSize; |
96 | |
97 | /*! @var maxTransferSize |
98 | * Maximum size of a transfer that this memory cursor is allowed to generate */ |
99 | IOPhysicalLength maxTransferSize; |
100 | |
101 | /*! @var alignMask |
102 | * Currently unused. Reserved for automated aligment restriction code. */ |
103 | IOPhysicalLength alignMask; |
104 | |
105 | public: |
106 | /*! @function withSpecification |
107 | * @abstract Creates and initializes an IOMemoryCursor in one operation. |
108 | * @discussion Factory function to create and initialize an IOMemoryCursor in one operation. For more information, see IOMemoryCursor::initWithSpecification. |
109 | * @param outSegFunc SegmentFunction to call to output one physical segment. |
110 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
111 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
112 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
113 | * @result Returns a new memory cursor if successfully created and initialized, 0 otherwise. |
114 | */ |
115 | static OSPtr<IOMemoryCursor> |
116 | withSpecification(SegmentFunction outSegFunc, |
117 | IOPhysicalLength maxSegmentSize = 0, |
118 | IOPhysicalLength maxTransferSize = 0, |
119 | IOPhysicalLength alignment = 1); |
120 | |
121 | /*! @function initWithSpecification |
122 | * @abstract Primary initializer for the IOMemoryCursor class. |
123 | * @param outSegFunc SegmentFunction to call to output one physical segment. |
124 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
125 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
126 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
127 | * @result Returns true if the inherited classes and this instance initialize |
128 | * successfully. |
129 | */ |
130 | virtual bool initWithSpecification(SegmentFunction outSegFunc, |
131 | IOPhysicalLength maxSegmentSize = 0, |
132 | IOPhysicalLength maxTransferSize = 0, |
133 | IOPhysicalLength alignment = 1); |
134 | |
135 | /*! @function genPhysicalSegments |
136 | * @abstract Generates a physical scatter/gather list given a memory descriptor. |
137 | * @discussion Generates a list of physical segments from the given memory descriptor, relative to the current position of the descriptor. |
138 | * @param descriptor IOMemoryDescriptor that describes the data associated with an I/O request. |
139 | * @param fromPosition Starting location of the I/O within a memory descriptor. |
140 | * @param segments Void pointer to base of output physical scatter/gather list. Always passed directly onto the SegmentFunction without interpretation by the cursor. |
141 | * @param maxSegments Maximum number of segments that can be written to segments array. |
142 | * @param maxTransferSize Maximum transfer size is limited to that many bytes, otherwise it defaults to the maximum transfer size specified when the memory cursor was initialized. |
143 | * @param transferSize Pointer to an IOByteCount variable that can contain the total size of the transfer being described. Defaults to 0 indicating that no transfer size need be returned. |
144 | * @result If the descriptor is exhausted of memory, a zero is returned, otherwise the number of segments that were filled in is returned. |
145 | */ |
146 | virtual UInt32 genPhysicalSegments( |
147 | IOMemoryDescriptor *descriptor, |
148 | IOByteCount fromPosition, |
149 | void * segments, |
150 | UInt32 maxSegments, |
151 | UInt32 maxTransferSize = 0, |
152 | IOByteCount *transferSize = NULL); |
153 | }; |
154 | |
155 | /************************ class IONaturalMemoryCursor ************************/ |
156 | |
157 | |
158 | /*! |
159 | * @class IONaturalMemoryCursor |
160 | * @abstract An IOMemoryCursor subclass that outputs a vector of PhysicalSegments in the natural byte orientation for the CPU. |
161 | * @discussion The IONaturalMemoryCursor would be used when it is too difficult to safely describe a SegmentFunction that is more appropriate for your hardware. This cursor just outputs an array of PhysicalSegments. |
162 | */ |
163 | class IONaturalMemoryCursor : public IOMemoryCursor |
164 | { |
165 | OSDeclareDefaultStructors(IONaturalMemoryCursor); |
166 | |
167 | public: |
168 | /*! @function outputSegment |
169 | * @abstract Outputs the given segment into the output segments array in natural byte order. |
170 | * @param segment The physical address and length that is next to be output. |
171 | * @param segments Base of the output vector of DMA address length pairs. |
172 | * @param segmentIndex Index to output 'segment' in the 'segments' array. |
173 | */ |
174 | static void outputSegment(PhysicalSegment segment, |
175 | void * segments, |
176 | UInt32 segmentIndex); |
177 | |
178 | /*! @defined naturalOutputSegment |
179 | * @discussion Backward compatibility define for the old global function definition. See IONaturalMemoryCursor::outputSegment. |
180 | */ |
181 | #define naturalOutputSegment IONaturalMemoryCursor::outputSegment |
182 | |
183 | /*! @function withSpecification |
184 | * @abstract Creates and initializes an IONaturalMemoryCursor in one operation. |
185 | * @discussion Factory function to create and initialize an IONaturalMemoryCursor in one operation. For more information, see IONaturalMemoryCursor::initWithSpecification. |
186 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
187 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
188 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
189 | * @result Returns a new memory cursor if successfully created and initialized, 0 otherwise. |
190 | */ |
191 | static OSPtr<IONaturalMemoryCursor> |
192 | withSpecification(IOPhysicalLength maxSegmentSize, |
193 | IOPhysicalLength maxTransferSize, |
194 | IOPhysicalLength alignment = 1); |
195 | |
196 | /*! @function initWithSpecification |
197 | * @abstract Primary initializer for the IONaturalMemoryCursor class. |
198 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
199 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
200 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
201 | * @result Returns true if the inherited classes and this instance initialize successfully. |
202 | */ |
203 | virtual bool initWithSpecification(IOPhysicalLength maxSegmentSize, |
204 | IOPhysicalLength maxTransferSize, |
205 | IOPhysicalLength alignment = 1); |
206 | |
207 | |
208 | /*! @function getPhysicalSegments |
209 | * @abstract Generates a CPU natural physical scatter/gather list given a memory descriptor. |
210 | * @discussion Generates a list of physical segments from the given memory descriptor, relative to the current position of the descriptor. Wraps IOMemoryCursor::genPhysicalSegments. |
211 | * @param descriptor IOMemoryDescriptor that describes the data associated with an I/O request. |
212 | * @param fromPosition Starting location of the I/O within a memory descriptor. |
213 | * @param segments Pointer to an array of IOMemoryCursor::PhysicalSegments for the output physical scatter/gather list. |
214 | * @param maxSegments Maximum number of segments that can be written to segments array. |
215 | * @param inMaxTransferSize Maximum transfer size is limited to that many bytes, otherwise it defaults to the maximum transfer size specified when the memory cursor was initialized. |
216 | * @param transferSize Pointer to an IOByteCount variable that can contain the total size of the transfer being described. Defaults to 0 indicating that no transfer size need be returned. |
217 | * @result If the descriptor is exhausted of memory, a zero is returned, otherwise the number of segments that were filled in is returned. |
218 | */ |
219 | virtual UInt32 |
220 | getPhysicalSegments(IOMemoryDescriptor *descriptor, |
221 | IOByteCount fromPosition, |
222 | PhysicalSegment *segments, |
223 | UInt32 maxSegments, |
224 | UInt32 inMaxTransferSize = 0, |
225 | IOByteCount *transferSize = NULL) |
226 | { |
227 | return genPhysicalSegments(descriptor, fromPosition, segments, |
228 | maxSegments, maxTransferSize: inMaxTransferSize, transferSize); |
229 | } |
230 | }; |
231 | |
232 | /************************** class IOBigMemoryCursor **************************/ |
233 | |
234 | /*! |
235 | * @class IOBigMemoryCursor |
236 | * @abstract An IOMemoryCursor subclass that outputs a vector of PhysicalSegments in the big endian byte order. |
237 | * @discussion The IOBigMemoryCursor would be used when the DMA hardware requires a big endian address and length pair. This cursor outputs an array of PhysicalSegments that are encoded in big-endian format. |
238 | */ |
239 | class IOBigMemoryCursor : public IOMemoryCursor |
240 | { |
241 | OSDeclareDefaultStructors(IOBigMemoryCursor); |
242 | |
243 | public: |
244 | /*! @function outputSegment |
245 | * @abstract Outputs the given segment into the output segments array in big endian byte order. |
246 | * @param segment The physical address and length that is next to be output. |
247 | * @param segments Base of the output vector of DMA address length pairs. |
248 | * @param segmentIndex Index to output 'segment' in the 'segments' array. |
249 | */ |
250 | static void outputSegment(PhysicalSegment segment, |
251 | void * segments, |
252 | UInt32 segmentIndex); |
253 | |
254 | /*! @defined bigOutputSegment |
255 | * @discussion Backward compatibility define for the old global function definition. See IOBigMemoryCursor::outputSegment |
256 | */ |
257 | #define bigOutputSegment IOBigMemoryCursor::outputSegment |
258 | |
259 | /*! @function withSpecification |
260 | * @abstract Creates and initializes an IOBigMemoryCursor in one operation. |
261 | * @discussion Factory function to create and initialize an IOBigMemoryCursor in one operation. See also IOBigMemoryCursor::initWithSpecification. |
262 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
263 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
264 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
265 | * @result Returns a new memory cursor if successfully created and initialized, 0 otherwise. |
266 | */ |
267 | static OSPtr<IOBigMemoryCursor> |
268 | withSpecification(IOPhysicalLength maxSegmentSize, |
269 | IOPhysicalLength maxTransferSize, |
270 | IOPhysicalLength alignment = 1); |
271 | |
272 | /*! @function initWithSpecification |
273 | * @abstract Primary initializer for the IOBigMemoryCursor class. |
274 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
275 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
276 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
277 | * @result Returns true if the inherited classes and this instance initialize |
278 | * successfully. |
279 | */ |
280 | virtual bool initWithSpecification(IOPhysicalLength maxSegmentSize, |
281 | IOPhysicalLength maxTransferSize, |
282 | IOPhysicalLength alignment = 1); |
283 | |
284 | |
285 | /*! @function getPhysicalSegments |
286 | * @abstract Generates a big endian physical scatter/gather list given a memory descriptor. |
287 | * @discussion Generates a list of physical segments from the given memory descriptor, relative to the current position of the descriptor. Wraps IOMemoryCursor::genPhysicalSegments. |
288 | * @param descriptor IOMemoryDescriptor that describes the data associated with an I/O request. |
289 | * @param fromPosition Starting location of the I/O within a memory descriptor. |
290 | * @param segments Pointer to an array of IOMemoryCursor::PhysicalSegments for the output physical scatter/gather list. |
291 | * @param maxSegments Maximum number of segments that can be written to segments array. |
292 | * @param inMaxTransferSize Maximum transfer size is limited to that many bytes, otherwise it defaults to the maximum transfer size specified when the memory cursor was initialized. |
293 | * @param transferSize Pointer to an IOByteCount variable that can contain the total size of the transfer being described. Defaults to 0 indicating that no transfer size need be returned. |
294 | * @result If the descriptor is exhausted of memory, a zero is returned, otherwise the number of segments that were filled in is returned. |
295 | */ |
296 | virtual UInt32 |
297 | getPhysicalSegments(IOMemoryDescriptor * descriptor, |
298 | IOByteCount fromPosition, |
299 | PhysicalSegment * segments, |
300 | UInt32 maxSegments, |
301 | UInt32 inMaxTransferSize = 0, |
302 | IOByteCount * transferSize = NULL) |
303 | { |
304 | return genPhysicalSegments(descriptor, fromPosition, segments, |
305 | maxSegments, maxTransferSize: inMaxTransferSize, transferSize); |
306 | } |
307 | }; |
308 | |
309 | /************************* class IOLittleMemoryCursor ************************/ |
310 | |
311 | /*! |
312 | * @class IOLittleMemoryCursor |
313 | * @abstract An IOMemoryCursor subclass that outputs a vector of PhysicalSegments in the little endian byte order. |
314 | * @discussion The IOLittleMemoryCursor would be used when the DMA hardware requires a little endian address and length pair. This cursor outputs an array of PhysicalSegments that are encoded in little endian format. |
315 | */ |
316 | class IOLittleMemoryCursor : public IOMemoryCursor |
317 | { |
318 | OSDeclareDefaultStructors(IOLittleMemoryCursor); |
319 | |
320 | public: |
321 | /*! @function outputSegment |
322 | * @abstract Outputs the given segment into the output segments array in little endian byte order. |
323 | * @param segment The physical address and length that is next to be output. |
324 | * @param segments Base of the output vector of DMA address length pairs. |
325 | * @param segmentIndex Index to output 'segment' in the 'segments' array. |
326 | */ |
327 | static void outputSegment(PhysicalSegment segment, |
328 | void * segments, |
329 | UInt32 segmentIndex); |
330 | |
331 | /*! @defined littleOutputSegment |
332 | * @discussion Backward compatibility define for the old global function definition. See also IOLittleMemoryCursor::outputSegment. */ |
333 | #define littleOutputSegment IOLittleMemoryCursor::outputSegment |
334 | |
335 | /*! @function withSpecification |
336 | * @abstract Creates and initializes an IOLittleMemoryCursor in one operation. |
337 | * @discussion Factory function to create and initialize an IOLittleMemoryCursor in one operation. See also IOLittleMemoryCursor::initWithSpecification. |
338 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
339 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
340 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
341 | * @result Returns a new memory cursor if successfully created and initialized, 0 otherwise. |
342 | */ |
343 | static OSPtr<IOLittleMemoryCursor> |
344 | withSpecification(IOPhysicalLength maxSegmentSize, |
345 | IOPhysicalLength maxTransferSize, |
346 | IOPhysicalLength alignment = 1); |
347 | |
348 | /*! @function initWithSpecification |
349 | * @abstract Primary initializer for the IOLittleMemoryCursor class. |
350 | * @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0. |
351 | * @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. |
352 | * @param alignment Alignment restrictions on output physical addresses. Not currently implemented. Defaults to single byte alignment. |
353 | * @result Returns true if the inherited classes and this instance initialize successfully. |
354 | */ |
355 | virtual bool initWithSpecification(IOPhysicalLength maxSegmentSize, |
356 | IOPhysicalLength maxTransferSize, |
357 | IOPhysicalLength alignment = 1); |
358 | |
359 | |
360 | /*! @function getPhysicalSegments |
361 | * @abstract Generates a little endian physical scatter/gather list given a memory descriptor. |
362 | * @discussion Generates a list of physical segments from the given memory descriptor, relative to the current position of the descriptor. Wraps IOMemoryCursor::genPhysicalSegments. |
363 | * @param descriptor IOMemoryDescriptor that describes the data associated with an I/O request. |
364 | * @param fromPosition Starting location of the I/O within a memory descriptor. |
365 | * @param segments Pointer to an array of IOMemoryCursor::PhysicalSegments for the output physical scatter/gather list. |
366 | * @param maxSegments Maximum number of segments that can be written to segments array. |
367 | * @param inMaxTransferSize Maximum transfer size is limited to that many bytes, otherwise it defaults to the maximum transfer size specified when the memory cursor was initialized. |
368 | * @param transferSize Pointer to an IOByteCount variable that can contain the total size of the transfer being described. Defaults to 0 indicating that no transfer size need be returned. |
369 | * @result If the descriptor is exhausted of memory, a zero is returned, otherwise the number of segments that were filled in is returned. |
370 | */ |
371 | virtual UInt32 |
372 | getPhysicalSegments(IOMemoryDescriptor * descriptor, |
373 | IOByteCount fromPosition, |
374 | PhysicalSegment * segments, |
375 | UInt32 maxSegments, |
376 | UInt32 inMaxTransferSize = 0, |
377 | IOByteCount * transferSize = NULL) |
378 | { |
379 | return genPhysicalSegments(descriptor, fromPosition, segments, |
380 | maxSegments, maxTransferSize: inMaxTransferSize, transferSize); |
381 | } |
382 | }; |
383 | |
384 | #endif /* !_IOMEMORYCURSOR_H */ |
385 | |