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 40OSDefineMetaClassAndStructors(IOMemoryCursor, OSObject) 41 42IOMemoryCursor * 43IOMemoryCursor::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 64bool 65IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc, 66 IOPhysicalLength inMaxSegmentSize, 67 IOPhysicalLength inMaxTransferSize, 68 IOPhysicalLength inAlignment) 69{ 70// @@@ gvdl: Remove me 71#if 1 72static UInt sMaxDBDMASegment; 73if (!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 79if (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 102UInt32 103IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor, 104 IOPhysicalLength 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, &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 195OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor) 196 197void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment, 198 void * outSegments, 199 UInt32 outSegmentIndex) 200{ 201 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment; 202} 203 204IONaturalMemoryCursor * 205IONaturalMemoryCursor::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 222bool 223IONaturalMemoryCursor::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 237OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor) 238 239void 240IOBigMemoryCursor::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 251IOBigMemoryCursor * 252IOBigMemoryCursor::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 269bool 270IOBigMemoryCursor::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 284OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor) 285 286void 287IOLittleMemoryCursor::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 298IOLittleMemoryCursor * 299IOLittleMemoryCursor::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 318bool 319IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, 320 IOPhysicalLength inMaxTransferSize, 321 IOPhysicalLength inAlignment) 322{ 323 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment, 324 inMaxSegmentSize, 325 inMaxTransferSize, 326 inAlignment); 327} 328 329/************************* class IODBDMAMemoryCursor *************************/ 330 331#if defined(__ppc__) 332 333#include <IOKit/ppc/IODBDMA.h> 334 335#undef super 336#define super IOMemoryCursor 337OSDefineMetaClassAndStructors(IODBDMAMemoryCursor, IOMemoryCursor) 338 339void 340IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment, 341 void * inSegments, 342 UInt32 inSegmentIndex) 343{ 344 IODBDMADescriptor *segment; 345 346 segment = &((IODBDMADescriptor *) inSegments)[inSegmentIndex]; 347 348 // Write location into address field 349 OSWriteSwapInt32((UInt32 *) segment, 4, inSegment.location); 350 351 // Write count into 1st two bytes of operation field. 352 // DO NOT touch rest of operation field as it should contain a STOP command. 353 OSWriteSwapInt16((UInt16 *) segment, 0, inSegment.length); 354} 355 356/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 357 358IODBDMAMemoryCursor * 359IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, 360 IOPhysicalLength inMaxTransferSize, 361 IOPhysicalLength inAlignment) 362{ 363 IODBDMAMemoryCursor *me = new IODBDMAMemoryCursor; 364 365 if (me && !me->initWithSpecification(inMaxSegmentSize, 366 inMaxTransferSize, 367 inAlignment)) 368 { 369 me->release(); 370 return 0; 371 } 372 373 return me; 374} 375 376/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 377 378bool 379IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, 380 IOPhysicalLength inMaxTransferSize, 381 IOPhysicalLength inAlignment) 382{ 383 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment, 384 inMaxSegmentSize, 385 inMaxTransferSize, 386 inAlignment); 387} 388 389#endif /* defined(__ppc__) */ 390 391