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 /* IOMemoryCursor.cpp created by wgulland on 1999-3-02 */ 29 30 #define IOKIT_ENABLE_SHARED_PTR 31 32 #include <IOKit/assert.h> 33 #include <IOKit/IOLib.h> 34 #include <IOKit/IOMemoryCursor.h> 35 #include <IOKit/IOMemoryDescriptor.h> 36 #include <libkern/OSByteOrder.h> 37 38 /**************************** class IOMemoryCursor ***************************/ 39 40 #undef super 41 #define super OSObject 42 OSDefineMetaClassAndStructors(IOMemoryCursor, OSObject) 43 44 OSSharedPtr<IOMemoryCursor> 45 IOMemoryCursor::withSpecification(SegmentFunction inSegFunc, 46 IOPhysicalLength inMaxSegmentSize, 47 IOPhysicalLength inMaxTransferSize, 48 IOPhysicalLength inAlignment) 49 { 50 OSSharedPtr<IOMemoryCursor> me = OSMakeShared<IOMemoryCursor>(); 51 52 if (me && !me->initWithSpecification(inSegFunc, 53 inMaxSegmentSize, 54 inMaxTransferSize, 55 inAlignment)) { 56 return nullptr; 57 } 58 59 return me; 60 } 61 62 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 63 64 bool 65 IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc, 66 IOPhysicalLength inMaxSegmentSize, 67 IOPhysicalLength inMaxTransferSize, 68 IOPhysicalLength inAlignment) 69 { 70 // @@@ gvdl: Remove me 71 #if 1 72 static UInt sMaxDBDMASegment; 73 if (!sMaxDBDMASegment) { 74 sMaxDBDMASegment = (UInt) - 1; 75 if (PE_parse_boot_argn("mseg", &sMaxDBDMASegment, sizeof(sMaxDBDMASegment))) { 76 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment); 77 } 78 } 79 80 if (inMaxSegmentSize > sMaxDBDMASegment) { 81 inMaxSegmentSize = sMaxDBDMASegment; 82 } 83 #endif 84 85 if (!super::init()) { 86 return false; 87 } 88 89 if (!inSegFunc) { 90 return false; 91 } 92 if (inMaxTransferSize > UINT_MAX) { 93 return false; 94 } 95 96 outSeg = inSegFunc; 97 maxSegmentSize = inMaxSegmentSize; 98 if (inMaxTransferSize) { 99 maxTransferSize = inMaxTransferSize; 100 } else { 101 maxTransferSize = (IOPhysicalLength) - 1; 102 } 103 alignMask = inAlignment - 1; 104 assert(alignMask == 0); // No alignment code yet! 105 106 return true; 107 } 108 109 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 110 111 UInt32 112 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor, 113 IOByteCount fromPosition, 114 void * inSegments, 115 UInt32 inMaxSegments, 116 UInt32 inMaxTransferSize, 117 IOByteCount *outTransferSize) 118 { 119 if (!inDescriptor) { 120 return 0; 121 } 122 123 if (!inMaxSegments) { 124 return 0; 125 } 126 127 if (!inMaxTransferSize) { 128 inMaxTransferSize = (typeof(inMaxTransferSize))maxTransferSize; 129 } 130 131 /* 132 * Iterate over the packet, translating segments where allowed 133 * 134 * If we finished cleanly return number of segments found 135 * and update the position in the descriptor. 136 */ 137 PhysicalSegment curSeg = { 0, 0 }; 138 UInt curSegIndex = 0; 139 UInt curTransferSize = 0; 140 IOByteCount inDescriptorLength = inDescriptor->getLength(); 141 PhysicalSegment seg = { 0, 0 }; 142 143 while ((seg.location) || (fromPosition < inDescriptorLength)) { 144 if (!seg.location) { 145 seg.location = inDescriptor->getPhysicalSegment( 146 fromPosition, (IOByteCount*)&seg.length); 147 assert(seg.location); 148 assert(seg.length); 149 fromPosition += seg.length; 150 } 151 152 if (!curSeg.location) { 153 curTransferSize += seg.length; 154 curSeg = seg; 155 seg.location = 0; 156 } else if ((curSeg.location + curSeg.length == seg.location)) { 157 curTransferSize += seg.length; 158 curSeg.length += seg.length; 159 seg.location = 0; 160 } 161 162 if (!seg.location) { 163 if ((curSeg.length > maxSegmentSize)) { 164 seg.location = curSeg.location + maxSegmentSize; 165 seg.length = curSeg.length - maxSegmentSize; 166 curTransferSize -= seg.length; 167 curSeg.length -= seg.length; 168 } 169 170 if ((curTransferSize >= inMaxTransferSize)) { 171 curSeg.length -= curTransferSize - inMaxTransferSize; 172 curTransferSize = inMaxTransferSize; 173 break; 174 } 175 } 176 177 if (seg.location) { 178 if ((curSegIndex + 1 == inMaxSegments)) { 179 break; 180 } 181 (*outSeg)(curSeg, inSegments, curSegIndex++); 182 curSeg.location = 0; 183 } 184 } 185 186 if (curSeg.location) { 187 (*outSeg)(curSeg, inSegments, curSegIndex++); 188 } 189 190 if (outTransferSize) { 191 *outTransferSize = curTransferSize; 192 } 193 194 return curSegIndex; 195 } 196 197 /************************ class IONaturalMemoryCursor ************************/ 198 199 #undef super 200 #define super IOMemoryCursor 201 OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor) 202 203 void 204 IONaturalMemoryCursor::outputSegment(PhysicalSegment segment, 205 void * outSegments, 206 UInt32 outSegmentIndex) 207 { 208 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment; 209 } 210 211 OSSharedPtr<IONaturalMemoryCursor> 212 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, 213 IOPhysicalLength inMaxTransferSize, 214 IOPhysicalLength inAlignment) 215 { 216 OSSharedPtr<IONaturalMemoryCursor> me = OSMakeShared<IONaturalMemoryCursor>(); 217 218 if (me && !me->initWithSpecification(inMaxSegmentSize, 219 inMaxTransferSize, 220 inAlignment)) { 221 return nullptr; 222 } 223 224 return me; 225 } 226 227 bool 228 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, 229 IOPhysicalLength inMaxTransferSize, 230 IOPhysicalLength inAlignment) 231 { 232 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment, 233 inMaxSegmentSize, 234 inMaxTransferSize, 235 inAlignment); 236 } 237 238 /************************** class IOBigMemoryCursor **************************/ 239 240 #undef super 241 #define super IOMemoryCursor 242 OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor) 243 244 void 245 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment, 246 void * inSegments, 247 UInt32 inSegmentIndex) 248 { 249 IOPhysicalAddress * segment; 250 251 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location; 252 #if IOPhysSize == 64 253 OSWriteBigInt64(segment, 0, inSegment.location); 254 OSWriteBigInt64(segment, sizeof(IOPhysicalAddress), inSegment.length); 255 #else 256 OSWriteBigInt(segment, 0, inSegment.location); 257 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length); 258 #endif 259 } 260 261 OSSharedPtr<IOBigMemoryCursor> 262 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, 263 IOPhysicalLength inMaxTransferSize, 264 IOPhysicalLength inAlignment) 265 { 266 OSSharedPtr<IOBigMemoryCursor> me = OSMakeShared<IOBigMemoryCursor>(); 267 268 if (me && !me->initWithSpecification(inMaxSegmentSize, 269 inMaxTransferSize, 270 inAlignment)) { 271 return nullptr; 272 } 273 274 return me; 275 } 276 277 bool 278 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, 279 IOPhysicalLength inMaxTransferSize, 280 IOPhysicalLength inAlignment) 281 { 282 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment, 283 inMaxSegmentSize, 284 inMaxTransferSize, 285 inAlignment); 286 } 287 288 /************************* class IOLittleMemoryCursor ************************/ 289 290 #undef super 291 #define super IOMemoryCursor 292 OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor) 293 294 void 295 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment, 296 void * inSegments, 297 UInt32 inSegmentIndex) 298 { 299 IOPhysicalAddress * segment; 300 301 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location; 302 #if IOPhysSize == 64 303 OSWriteLittleInt64(segment, 0, inSegment.location); 304 OSWriteLittleInt64(segment, sizeof(IOPhysicalAddress), inSegment.length); 305 #else 306 OSWriteLittleInt(segment, 0, inSegment.location); 307 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length); 308 #endif 309 } 310 311 OSSharedPtr<IOLittleMemoryCursor> 312 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, 313 IOPhysicalLength inMaxTransferSize, 314 IOPhysicalLength inAlignment) 315 { 316 OSSharedPtr<IOLittleMemoryCursor> me = OSMakeShared<IOLittleMemoryCursor>(); 317 318 if (me && !me->initWithSpecification(inMaxSegmentSize, 319 inMaxTransferSize, 320 inAlignment)) { 321 return nullptr; 322 } 323 324 return me; 325 } 326 327 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 328 329 bool 330 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, 331 IOPhysicalLength inMaxTransferSize, 332 IOPhysicalLength inAlignment) 333 { 334 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment, 335 inMaxSegmentSize, 336 inMaxTransferSize, 337 inAlignment); 338 } 339