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