1/*
2 * Copyright (c) 1998-2000 Apple Computer, 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 <IOKit/IOTypes.h>
33
34class IOMemoryDescriptor;
35
36/**************************** class IOMemoryCursor ***************************/
37
38/*!
39    @class IOMemoryCursor
40    @abstract A mechanism to convert memory references to physical addresses.
41    @discussion The IOMemoryCursor declares the super class that all
42specific 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.
43<br><br>
44    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.
45<br><br>
46Below is the simplest example of a SegmentFunction:<br>
47void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,<br>
48					  void *	  outSegments,<br>
49					  UInt32	  outSegmentIndex)<br>
50{<br>
51    ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;<br>
52}
53
54*/
55class IOMemoryCursor : public OSObject
56{
57    OSDeclareDefaultStructors(IOMemoryCursor)
58
59public:
60/*!
61    @typedef PhysicalSegment
62    @discussion A physical address/length pair.
63*/
64    struct PhysicalSegment
65    {
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 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
128successfully.
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 = 0);
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 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 getPhysicalSegments(IOMemoryDescriptor *descriptor,
220				       IOByteCount	   fromPosition,
221				       PhysicalSegment	  *segments,
222				       UInt32		   maxSegments,
223				       UInt32		   inMaxTransferSize = 0,
224				       IOByteCount	  *transferSize = 0)
225    {
226	return genPhysicalSegments(descriptor, fromPosition, segments,
227				maxSegments, inMaxTransferSize, transferSize);
228    }
229};
230
231/************************** class IOBigMemoryCursor **************************/
232
233/*!
234    @class IOBigMemoryCursor
235    @abstract An IOMemoryCursor subclass that outputs a vector of PhysicalSegments in the big endian byte order.
236    @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.
237*/
238class IOBigMemoryCursor : public IOMemoryCursor
239{
240    OSDeclareDefaultStructors(IOBigMemoryCursor)
241
242public:
243/*! @function outputSegment
244    @abstract Outputs the given segment into the output segments array in big endian byte order.
245    @param segment The physical address and length that is next to be output.
246    @param segments Base of the output vector of DMA address length pairs.
247    @param segmentIndex Index to output 'segment' in the 'segments' array.
248*/
249    static void outputSegment(PhysicalSegment segment,
250			      void *	      segments,
251			      UInt32	      segmentIndex);
252
253/*! @defined bigOutputSegment
254    @discussion Backward compatibility define for the old global function definition.  See IOBigMemoryCursor::outputSegment
255*/
256#define bigOutputSegment IOBigMemoryCursor::outputSegment
257
258/*! @function withSpecification
259    @abstract Creates and initializes an IOBigMemoryCursor in one operation.
260    @discussion Factory function to create and initialize an IOBigMemoryCursor in one operation.  See also IOBigMemoryCursor::initWithSpecification.
261    @param maxSegmentSize Maximum allowable size for one segment.  Defaults to 0.
262    @param maxTransferSize Maximum size of an entire transfer.	Defaults to 0 indicating no maximum.
263    @param alignment Alignment restrictions on output physical addresses.  Not currently implemented.  Defaults to single byte alignment.
264    @result Returns a new memory cursor if successfully created and initialized, 0 otherwise.
265*/
266    static IOBigMemoryCursor *
267	withSpecification(IOPhysicalLength maxSegmentSize,
268			  IOPhysicalLength maxTransferSize,
269			  IOPhysicalLength alignment = 1);
270
271/*! @function initWithSpecification
272    @abstract Primary initializer for the IOBigMemoryCursor class.
273    @param maxSegmentSize Maximum allowable size for one segment.  Defaults to 0.
274    @param maxTransferSize Maximum size of an entire transfer.	Defaults to 0 indicating no maximum.
275    @param alignment Alignment restrictions on output physical addresses.  Not currently implemented.  Defaults to single byte alignment.
276    @result Returns true if the inherited classes and this instance initialize
277successfully.
278*/
279    virtual bool initWithSpecification(IOPhysicalLength	 maxSegmentSize,
280				       IOPhysicalLength	 maxTransferSize,
281				       IOPhysicalLength	 alignment = 1);
282
283
284/*! @function getPhysicalSegments
285    @abstract Generates a big endian physical scatter/gather list given a memory descriptor.
286    @discussion Generates a list of physical segments from the given memory descriptor, relative to the current position of the descriptor.  Wraps IOMemoryCursor::genPhysicalSegments.
287    @param descriptor IOMemoryDescriptor that describes the data associated with an I/O request.
288    @param fromPosition Starting location of the I/O within a memory descriptor.
289    @param segments Pointer to an array of IOMemoryCursor::PhysicalSegments for the output physical scatter/gather list.
290    @param maxSegments Maximum number of segments that can be written to segments array.
291    @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.
292    @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.
293    @result If the descriptor is exhausted of memory, a zero is returned, otherwise the number of segments that were filled in is returned.
294*/
295    virtual UInt32 getPhysicalSegments(IOMemoryDescriptor * descriptor,
296				       IOByteCount	    fromPosition,
297				       PhysicalSegment *    segments,
298				       UInt32		    maxSegments,
299				       UInt32		    inMaxTransferSize = 0,
300				       IOByteCount	 *  transferSize = 0)
301    {
302	return genPhysicalSegments(descriptor, fromPosition, segments,
303				maxSegments, inMaxTransferSize, transferSize);
304    }
305};
306
307/************************* class IOLittleMemoryCursor ************************/
308
309/*!
310    @class IOLittleMemoryCursor
311    @abstract An IOMemoryCursor subclass that outputs a vector of PhysicalSegments in the little endian byte order.
312    @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.
313*/
314class IOLittleMemoryCursor : public IOMemoryCursor
315{
316    OSDeclareDefaultStructors(IOLittleMemoryCursor)
317
318public:
319/*! @function outputSegment
320    @abstract Outputs the given segment into the output segments array in little endian byte order.
321    @param segment The physical address and length that is next to be output.
322    @param segments Base of the output vector of DMA address length pairs.
323    @param segmentIndex Index to output 'segment' in the 'segments' array.
324*/
325    static void outputSegment(PhysicalSegment segment,
326			      void *	      segments,
327			      UInt32	      segmentIndex);
328
329/*! @defined littleOutputSegment
330    @discussion Backward compatibility define for the old global function definition.  See also IOLittleMemoryCursor::outputSegment. */
331#define littleOutputSegment IOLittleMemoryCursor::outputSegment
332
333/*! @function withSpecification
334    @abstract Creates and initializes an IOLittleMemoryCursor in one operation.
335    @discussion Factory function to create and initialize an IOLittleMemoryCursor in one operation.  See also IOLittleMemoryCursor::initWithSpecification.
336    @param maxSegmentSize Maximum allowable size for one segment.  Defaults to 0.
337    @param maxTransferSize Maximum size of an entire transfer.	Defaults to 0 indicating no maximum.
338    @param alignment Alignment restrictions on output physical addresses.  Not currently implemented.  Defaults to single byte alignment.
339    @result Returns a new memory cursor if successfully created and initialized, 0 otherwise.
340*/
341    static IOLittleMemoryCursor *
342	withSpecification(IOPhysicalLength maxSegmentSize,
343			  IOPhysicalLength maxTransferSize,
344			  IOPhysicalLength alignment = 1);
345
346/*! @function initWithSpecification
347    @abstract Primary initializer for the IOLittleMemoryCursor class.
348    @param maxSegmentSize Maximum allowable size for one segment.  Defaults to 0.
349    @param maxTransferSize Maximum size of an entire transfer.	Defaults to 0 indicating no maximum.
350    @param alignment Alignment restrictions on output physical addresses.  Not currently implemented.  Defaults to single byte alignment.
351    @result Returns true if the inherited classes and this instance initialize successfully.
352*/
353    virtual bool initWithSpecification(IOPhysicalLength	 maxSegmentSize,
354				       IOPhysicalLength	 maxTransferSize,
355				       IOPhysicalLength	 alignment = 1);
356
357
358/*! @function getPhysicalSegments
359    @abstract Generates a little endian physical scatter/gather list given a memory descriptor.
360    @discussion Generates a list of physical segments from the given memory descriptor, relative to the current position of the descriptor.  Wraps IOMemoryCursor::genPhysicalSegments.
361    @param descriptor IOMemoryDescriptor that describes the data associated with an I/O request.
362    @param fromPosition Starting location of the I/O within a memory descriptor.
363    @param segments Pointer to an array of IOMemoryCursor::PhysicalSegments for the output physical scatter/gather list.
364    @param maxSegments Maximum number of segments that can be written to segments array.
365    @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.
366    @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.
367    @result If the descriptor is exhausted of memory, a zero is returned, otherwise the number of segments that were filled in is returned.
368*/
369    virtual UInt32 getPhysicalSegments(IOMemoryDescriptor * descriptor,
370				       IOByteCount	    fromPosition,
371				       PhysicalSegment *    segments,
372				       UInt32		    maxSegments,
373				       UInt32		    inMaxTransferSize = 0,
374				       IOByteCount	 *  transferSize = 0)
375    {
376	return genPhysicalSegments(descriptor, fromPosition, segments,
377				maxSegments, inMaxTransferSize, transferSize);
378    }
379};
380
381#endif /* !_IOMEMORYCURSOR_H */
382
383