xref: /xnu-10002.81.5/iokit/IOKit/IOMemoryCursor.h (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
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, 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, 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, inMaxTransferSize, transferSize);
381 	}
382 };
383 
384 #endif /* !_IOMEMORYCURSOR_H */
385