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
35class 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 */
56class IOMemoryCursor : public OSObject
57{
58 OSDeclareDefaultStructors(IOMemoryCursor);
59
60public:
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
90protected:
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
105public:
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 */
163class IONaturalMemoryCursor : public IOMemoryCursor
164{
165 OSDeclareDefaultStructors(IONaturalMemoryCursor);
166
167public:
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 */
239class IOBigMemoryCursor : public IOMemoryCursor
240{
241 OSDeclareDefaultStructors(IOBigMemoryCursor);
242
243public:
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 */
316class IOLittleMemoryCursor : public IOMemoryCursor
317{
318 OSDeclareDefaultStructors(IOLittleMemoryCursor);
319
320public:
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