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 29 #include <IOKit/IOLib.h> 30 #include <IOKit/IOInterleavedMemoryDescriptor.h> 31 32 #define super IOMemoryDescriptor 33 OSDefineMetaClassAndStructors(IOInterleavedMemoryDescriptor, IOMemoryDescriptor) 34 35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 36 37 bool IOInterleavedMemoryDescriptor::initWithAddress( 38 void * /* address */ , 39 IOByteCount /* withLength */ , 40 IODirection /* withDirection */ ) 41 { 42 return false; 43 } 44 45 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 46 47 bool IOInterleavedMemoryDescriptor::initWithAddress( 48 vm_address_t /* address */ , 49 IOByteCount /* withLength */ , 50 IODirection /* withDirection */ , 51 task_t /* withTask */ ) 52 { 53 return false; 54 } 55 56 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 57 58 bool IOInterleavedMemoryDescriptor::initWithPhysicalAddress( 59 IOPhysicalAddress /* address */ , 60 IOByteCount /* withLength */ , 61 IODirection /* withDirection */ ) 62 { 63 return false; 64 } 65 66 67 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 68 69 bool IOInterleavedMemoryDescriptor::initWithPhysicalRanges( 70 IOPhysicalRange * /* ranges */ , 71 UInt32 /* withCount */ , 72 IODirection /* withDirection */ , 73 bool /* asReference */ ) 74 { 75 return false; 76 } 77 78 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 79 80 bool IOInterleavedMemoryDescriptor::initWithRanges( 81 IOVirtualRange * /* ranges */ , 82 UInt32 /* withCount */ , 83 IODirection /* withDirection */ , 84 task_t /* withTask */ , 85 bool /* asReference */ ) 86 { 87 return false; 88 } 89 90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 91 92 IOInterleavedMemoryDescriptor * IOInterleavedMemoryDescriptor::withCapacity( 93 UInt32 capacity, 94 IODirection direction ) 95 { 96 // 97 // Create a new IOInterleavedMemoryDescriptor. The "buffer" will be made up 98 // of several memory descriptors, that are to be chained end-to-end to make up 99 // a single memory descriptor. 100 // 101 102 IOInterleavedMemoryDescriptor * me = new IOInterleavedMemoryDescriptor; 103 104 if ( me && !me->initWithCapacity( 105 /* capacity */ capacity, 106 /* direction */ direction )) 107 { 108 me->release(); 109 me = 0; 110 } 111 112 return me; 113 } 114 115 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 116 117 bool IOInterleavedMemoryDescriptor::initWithCapacity( 118 UInt32 capacity, 119 IODirection direction ) 120 { 121 // 122 // Initialize an IOInterleavedMemoryDescriptor. The "buffer" will be made up 123 // of several memory descriptors, that are to be chained end-to-end to make up 124 // a single memory descriptor. 125 // 126 127 assert(capacity); 128 129 // Ask our superclass' opinion. 130 if ( super::init() == false ) return false; 131 132 // Initialize our minimal state. 133 134 _direction = direction; 135 _length = 0; 136 _mappings = 0; 137 _tag = 0; 138 _descriptorCount = 0; 139 _descriptors = IONew(IOMemoryDescriptor *, capacity); 140 _descriptorOffsets = IONew(IOByteCount, capacity); 141 _descriptorLengths = IONew(IOByteCount, capacity); 142 143 if ( (_descriptors == 0) || (_descriptorOffsets == 0) || (_descriptorLengths == 0) ) 144 return false; 145 146 _descriptorCapacity = capacity; 147 148 return true; 149 } 150 151 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 152 153 void IOInterleavedMemoryDescriptor::clearMemoryDescriptors( IODirection direction ) 154 { 155 UInt32 index; 156 157 for ( index = 0; index < _descriptorCount; index++ ) 158 { 159 if ( _descriptorPrepared ) 160 _descriptors[index]->complete(_direction); 161 162 _descriptors[index]->release(); 163 _descriptors[index] = 0; 164 165 _descriptorOffsets[index] = 0; 166 _descriptorLengths[index] = 0; 167 } 168 169 if ( direction != kIODirectionNone ) 170 _direction = direction; 171 172 _descriptorCount = 0; 173 _length = 0; 174 _mappings = 0; 175 _tag = 0; 176 177 }; 178 179 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 180 181 bool IOInterleavedMemoryDescriptor::setMemoryDescriptor( 182 IOMemoryDescriptor * descriptor, 183 IOByteCount offset, 184 IOByteCount length ) 185 { 186 if ( _descriptorPrepared || (_descriptorCount == _descriptorCapacity) ) 187 return false; 188 189 if ( (offset + length) > descriptor->getLength() ) 190 return false; 191 192 // if ( descriptor->getDirection() != _direction ) 193 // return false; 194 195 descriptor->retain(); 196 _descriptors[_descriptorCount] = descriptor; 197 _descriptorOffsets[_descriptorCount] = offset; 198 _descriptorLengths[_descriptorCount] = length; 199 200 _descriptorCount++; 201 202 _length += length; 203 204 return true; 205 } 206 207 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 208 209 void IOInterleavedMemoryDescriptor::free() 210 { 211 // 212 // Free all of this object's outstanding resources. 213 // 214 215 if ( _descriptors ) 216 { 217 for ( unsigned index = 0; index < _descriptorCount; index++ ) 218 _descriptors[index]->release(); 219 220 if ( _descriptors != 0 ) 221 IODelete(_descriptors, IOMemoryDescriptor *, _descriptorCapacity); 222 223 if ( _descriptorOffsets != 0 ) 224 IODelete(_descriptorOffsets, IOMemoryDescriptor *, _descriptorCapacity); 225 226 if ( _descriptorLengths != 0 ) 227 IODelete(_descriptorLengths, IOMemoryDescriptor *, _descriptorCapacity); 228 } 229 230 super::free(); 231 } 232 233 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 234 235 IOReturn IOInterleavedMemoryDescriptor::prepare(IODirection forDirection) 236 { 237 // 238 // Prepare the memory for an I/O transfer. 239 // 240 // This involves paging in the memory and wiring it down for the duration 241 // of the transfer. The complete() method finishes the processing of the 242 // memory after the I/O transfer finishes. 243 // 244 245 unsigned index; 246 IOReturn status = kIOReturnSuccess; 247 IOReturn statusUndo; 248 249 if ( forDirection == kIODirectionNone ) 250 { 251 forDirection = _direction; 252 } 253 254 for ( index = 0; index < _descriptorCount; index++ ) 255 { 256 status = _descriptors[index]->prepare(forDirection); 257 if ( status != kIOReturnSuccess ) break; 258 } 259 260 if ( status != kIOReturnSuccess ) 261 { 262 for ( unsigned indexUndo = 0; indexUndo < index; indexUndo++ ) 263 { 264 statusUndo = _descriptors[index]->complete(forDirection); 265 assert(statusUndo == kIOReturnSuccess); 266 } 267 } 268 269 if ( status == kIOReturnSuccess ) _descriptorPrepared = true; 270 271 return status; 272 } 273 274 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 275 276 IOReturn IOInterleavedMemoryDescriptor::complete(IODirection forDirection) 277 { 278 // 279 // Complete processing of the memory after an I/O transfer finishes. 280 // 281 // This method shouldn't be called unless a prepare() was previously issued; 282 // the prepare() and complete() must occur in pairs, before and after an I/O 283 // transfer. 284 // 285 286 IOReturn status; 287 IOReturn statusFinal = kIOReturnSuccess; 288 289 if ( forDirection == kIODirectionNone ) 290 { 291 forDirection = _direction; 292 } 293 294 for ( unsigned index = 0; index < _descriptorCount; index++ ) 295 { 296 status = _descriptors[index]->complete(forDirection); 297 if ( status != kIOReturnSuccess ) statusFinal = status; 298 assert(status == kIOReturnSuccess); 299 } 300 301 _descriptorPrepared = false; 302 303 return statusFinal; 304 } 305 306 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 307 308 addr64_t IOInterleavedMemoryDescriptor::getPhysicalSegment64( 309 IOByteCount offset, IOByteCount * length ) 310 { 311 // 312 // This method returns the physical address of the byte at the given offset 313 // into the memory, and optionally the length of the physically contiguous 314 // segment from that offset. 315 // 316 317 addr64_t pa; 318 319 assert(offset <= _length); 320 321 for ( unsigned index = 0; index < _descriptorCount; index++ ) 322 { 323 if ( offset < _descriptorLengths[index] ) 324 { 325 pa = _descriptors[index]->getPhysicalSegment64(_descriptorOffsets[index] + offset, length); 326 if ((_descriptorLengths[index] - offset) < *length) *length = _descriptorLengths[index] - offset; 327 return pa; 328 } 329 offset -= _descriptorLengths[index]; 330 } 331 332 if ( length ) *length = 0; 333 334 return 0; 335 } 336 337 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 338 339 IOPhysicalAddress IOInterleavedMemoryDescriptor::getPhysicalSegment( 340 IOByteCount offset, IOByteCount * length ) 341 { 342 // 343 // This method returns the physical address of the byte at the given offset 344 // into the memory, and optionally the length of the physically contiguous 345 // segment from that offset. 346 // 347 348 IOPhysicalAddress pa; 349 350 assert(offset <= _length); 351 352 for ( unsigned index = 0; index < _descriptorCount; index++ ) 353 { 354 if ( offset < _descriptorLengths[index] ) 355 { 356 pa = _descriptors[index]->getPhysicalSegment(_descriptorOffsets[index] + offset, length); 357 if ((_descriptorLengths[index] - offset) < *length) *length = _descriptorLengths[index] - offset; 358 return pa; 359 } 360 offset -= _descriptorLengths[index]; 361 } 362 363 if ( length ) *length = 0; 364 365 return 0; 366 } 367 368 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 369 370 IOPhysicalAddress IOInterleavedMemoryDescriptor::getSourceSegment( 371 IOByteCount offset, 372 IOByteCount * length ) 373 { 374 // 375 // This method returns the physical address of the byte at the given offset 376 // into the memory, and optionally the length of the physically contiguous 377 // segment from that offset. 378 // 379 380 IOPhysicalAddress pa; 381 382 assert(offset <= _length); 383 384 for ( unsigned index = 0; index < _descriptorCount; index++ ) 385 { 386 if ( offset < _descriptorLengths[index] ) 387 { 388 pa = _descriptors[index]->getSourceSegment(_descriptorOffsets[index] + offset, length); 389 if ((_descriptorLengths[index] - offset) < *length) *length = _descriptorLengths[index] - offset; 390 return pa; 391 } 392 offset -= _descriptorLengths[index]; 393 } 394 395 if ( length ) *length = 0; 396 397 return 0; 398 } 399 400 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 401 402 void * IOInterleavedMemoryDescriptor::getVirtualSegment( IOByteCount /* offset */ , 403 IOByteCount * /* length */ ) 404 { 405 return 0; 406 } 407