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