1 /* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 #include <IOKit/assert.h> 23 #include <IOKit/system.h> 24 25 #include <IOKit/IOLib.h> 26 #include <IOKit/IOBufferMemoryDescriptor.h> 27 28 #include "IOKitKernelInternal.h" 29 30 __BEGIN_DECLS 31 void ipc_port_release_send(ipc_port_t port); 32 #include <vm/pmap.h> 33 34 vm_map_t IOPageableMapForAddress( vm_address_t address ); 35 __END_DECLS 36 37 #define super IOGeneralMemoryDescriptor 38 OSDefineMetaClassAndStructors(IOBufferMemoryDescriptor, 39 IOGeneralMemoryDescriptor); 40 41 bool IOBufferMemoryDescriptor::initWithAddress( 42 void * /* address */ , 43 IOByteCount /* withLength */ , 44 IODirection /* withDirection */ ) 45 { 46 return false; 47 } 48 49 bool IOBufferMemoryDescriptor::initWithAddress( 50 vm_address_t /* address */ , 51 IOByteCount /* withLength */ , 52 IODirection /* withDirection */ , 53 task_t /* withTask */ ) 54 { 55 return false; 56 } 57 58 bool IOBufferMemoryDescriptor::initWithPhysicalAddress( 59 IOPhysicalAddress /* address */ , 60 IOByteCount /* withLength */ , 61 IODirection /* withDirection */ ) 62 { 63 return false; 64 } 65 66 bool IOBufferMemoryDescriptor::initWithPhysicalRanges( 67 IOPhysicalRange * /* ranges */ , 68 UInt32 /* withCount */ , 69 IODirection /* withDirection */ , 70 bool /* asReference */ ) 71 { 72 return false; 73 } 74 75 bool IOBufferMemoryDescriptor::initWithRanges( 76 IOVirtualRange * /* ranges */ , 77 UInt32 /* withCount */ , 78 IODirection /* withDirection */ , 79 task_t /* withTask */ , 80 bool /* asReference */ ) 81 { 82 return false; 83 } 84 85 bool IOBufferMemoryDescriptor::initWithOptions( 86 IOOptionBits options, 87 vm_size_t capacity, 88 vm_offset_t alignment, 89 task_t inTask) 90 { 91 kern_return_t kr; 92 vm_map_t vmmap = 0; 93 IOOptionBits iomdOptions = kIOMemoryAsReference | kIOMemoryTypeVirtual; 94 95 if (!capacity) 96 return false; 97 98 _options = options; 99 _capacity = capacity; 100 _physAddrs = 0; 101 _physSegCount = 0; 102 _buffer = 0; 103 104 // Grab the direction and the Auto Prepare bits from the Buffer MD options 105 iomdOptions |= options & (kIOMemoryDirectionMask | kIOMemoryAutoPrepare); 106 107 if ((options & kIOMemorySharingTypeMask) && (alignment < page_size)) 108 alignment = page_size; 109 110 if ((inTask != kernel_task) && !(options & kIOMemoryPageable)) 111 return false; 112 113 _alignment = alignment; 114 if (options & kIOMemoryPageable) 115 { 116 iomdOptions |= kIOMemoryBufferPageable; 117 118 ipc_port_t sharedMem; 119 vm_size_t size = round_page_32(capacity); 120 121 // must create the entry before any pages are allocated 122 123 // set flags for entry + object create 124 vm_prot_t memEntryCacheMode = VM_PROT_READ | VM_PROT_WRITE 125 | MAP_MEM_NAMED_CREATE; 126 127 if (options & kIOMemoryPurgeable) 128 memEntryCacheMode |= MAP_MEM_PURGABLE; 129 130 // set memory entry cache mode 131 switch (options & kIOMapCacheMask) 132 { 133 case kIOMapInhibitCache: 134 SET_MAP_MEM(MAP_MEM_IO, memEntryCacheMode); 135 break; 136 137 case kIOMapWriteThruCache: 138 SET_MAP_MEM(MAP_MEM_WTHRU, memEntryCacheMode); 139 break; 140 141 case kIOMapWriteCombineCache: 142 SET_MAP_MEM(MAP_MEM_WCOMB, memEntryCacheMode); 143 break; 144 145 case kIOMapCopybackCache: 146 SET_MAP_MEM(MAP_MEM_COPYBACK, memEntryCacheMode); 147 break; 148 149 case kIOMapDefaultCache: 150 default: 151 SET_MAP_MEM(MAP_MEM_NOOP, memEntryCacheMode); 152 break; 153 } 154 155 kr = mach_make_memory_entry( vmmap, 156 &size, 0, 157 memEntryCacheMode, &sharedMem, 158 NULL ); 159 160 if( (KERN_SUCCESS == kr) && (size != round_page_32(capacity))) { 161 ipc_port_release_send( sharedMem ); 162 kr = kIOReturnVMError; 163 } 164 if( KERN_SUCCESS != kr) 165 return( false ); 166 167 _memEntry = (void *) sharedMem; 168 #if IOALLOCDEBUG 169 debug_iomallocpageable_size += size; 170 #endif 171 if ((NULL == inTask) && (options & kIOMemoryPageable)) 172 inTask = kernel_task; 173 else if (inTask == kernel_task) 174 { 175 vmmap = kernel_map; 176 } 177 else 178 { 179 180 if( !reserved) { 181 reserved = IONew( ExpansionData, 1 ); 182 if( !reserved) 183 return( false ); 184 } 185 vmmap = get_task_map(inTask); 186 vm_map_reference(vmmap); 187 reserved->map = vmmap; 188 } 189 } 190 else 191 { 192 // @@@ gvdl: Need to remove this 193 // Buffer should never auto prepare they should be prepared explicitly 194 // But it never was enforced so what are you going to do? 195 iomdOptions |= kIOMemoryAutoPrepare; 196 197 /* Allocate a wired-down buffer inside kernel space. */ 198 if (options & kIOMemoryPhysicallyContiguous) 199 _buffer = IOMallocContiguous(capacity, alignment, 0); 200 else if (alignment > 1) 201 _buffer = IOMallocAligned(capacity, alignment); 202 else 203 _buffer = IOMalloc(capacity); 204 205 if (!_buffer) 206 return false; 207 } 208 209 _singleRange.v.address = (vm_address_t) _buffer; 210 _singleRange.v.length = capacity; 211 212 if (!super::initWithOptions(&_singleRange.v, 1, 0, 213 inTask, iomdOptions, /* System mapper */ 0)) 214 return false; 215 216 if (options & kIOMemoryPageable) 217 { 218 kern_return_t kr; 219 220 if (vmmap) 221 { 222 kr = doMap(vmmap, (IOVirtualAddress *) &_buffer, kIOMapAnywhere, 0, round_page_32(capacity)); 223 if (KERN_SUCCESS != kr) 224 { 225 _buffer = 0; 226 return( false ); 227 } 228 _singleRange.v.address = (vm_address_t) _buffer; 229 } 230 } 231 232 setLength(capacity); 233 234 return true; 235 } 236 237 IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::inTaskWithOptions( 238 task_t inTask, 239 IOOptionBits options, 240 vm_size_t capacity, 241 vm_offset_t alignment) 242 { 243 IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; 244 245 if (me && !me->initWithOptions(options, capacity, alignment, inTask)) { 246 me->release(); 247 me = 0; 248 } 249 return me; 250 } 251 252 bool IOBufferMemoryDescriptor::initWithOptions( 253 IOOptionBits options, 254 vm_size_t capacity, 255 vm_offset_t alignment) 256 { 257 return( initWithOptions(options, capacity, alignment, kernel_task) ); 258 } 259 260 IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::withOptions( 261 IOOptionBits options, 262 vm_size_t capacity, 263 vm_offset_t alignment) 264 { 265 IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; 266 267 if (me && !me->initWithOptions(options, capacity, alignment, kernel_task)) { 268 me->release(); 269 me = 0; 270 } 271 return me; 272 } 273 274 275 /* 276 * withCapacity: 277 * 278 * Returns a new IOBufferMemoryDescriptor with a buffer large enough to 279 * hold capacity bytes. The descriptor's length is initially set to the capacity. 280 */ 281 IOBufferMemoryDescriptor * 282 IOBufferMemoryDescriptor::withCapacity(vm_size_t inCapacity, 283 IODirection inDirection, 284 bool inContiguous) 285 { 286 return( IOBufferMemoryDescriptor::withOptions( 287 inDirection | kIOMemoryUnshared 288 | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), 289 inCapacity, inContiguous ? inCapacity : 1 )); 290 } 291 292 /* 293 * initWithBytes: 294 * 295 * Initialize a new IOBufferMemoryDescriptor preloaded with bytes (copied). 296 * The descriptor's length and capacity are set to the input buffer's size. 297 */ 298 bool IOBufferMemoryDescriptor::initWithBytes(const void * inBytes, 299 vm_size_t inLength, 300 IODirection inDirection, 301 bool inContiguous) 302 { 303 if (!initWithOptions( 304 inDirection | kIOMemoryUnshared 305 | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), 306 inLength, inLength )) 307 return false; 308 309 // start out with no data 310 setLength(0); 311 312 if (!appendBytes(inBytes, inLength)) 313 return false; 314 315 return true; 316 } 317 318 /* 319 * withBytes: 320 * 321 * Returns a new IOBufferMemoryDescriptor preloaded with bytes (copied). 322 * The descriptor's length and capacity are set to the input buffer's size. 323 */ 324 IOBufferMemoryDescriptor * 325 IOBufferMemoryDescriptor::withBytes(const void * inBytes, 326 vm_size_t inLength, 327 IODirection inDirection, 328 bool inContiguous) 329 { 330 IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; 331 332 if (me && !me->initWithBytes(inBytes, inLength, inDirection, inContiguous)){ 333 me->release(); 334 me = 0; 335 } 336 return me; 337 } 338 339 /* 340 * free: 341 * 342 * Free resources 343 */ 344 void IOBufferMemoryDescriptor::free() 345 { 346 // Cache all of the relevant information on the stack for use 347 // after we call super::free()! 348 IOOptionBits options = _options; 349 vm_size_t size = _capacity; 350 void * buffer = _buffer; 351 vm_map_t vmmap = 0; 352 vm_offset_t alignment = _alignment; 353 354 if (reserved) 355 { 356 vmmap = reserved->map; 357 IODelete( reserved, ExpansionData, 1 ); 358 } 359 360 /* super::free may unwire - deallocate buffer afterwards */ 361 super::free(); 362 363 if (options & kIOMemoryPageable) 364 { 365 #if IOALLOCDEBUG 366 if (!buffer || vmmap) 367 debug_iomallocpageable_size -= round_page_32(size); 368 #endif 369 if (buffer) 370 { 371 if (vmmap) 372 vm_deallocate(vmmap, (vm_address_t) buffer, round_page_32(size)); 373 else 374 IOFreePageable(buffer, size); 375 } 376 } 377 else if (buffer) 378 { 379 if (options & kIOMemoryPhysicallyContiguous) 380 IOFreeContiguous(buffer, size); 381 else if (alignment > 1) 382 IOFreeAligned(buffer, size); 383 else 384 IOFree(buffer, size); 385 } 386 if (vmmap) 387 vm_map_deallocate(vmmap); 388 } 389 390 /* 391 * getCapacity: 392 * 393 * Get the buffer capacity 394 */ 395 vm_size_t IOBufferMemoryDescriptor::getCapacity() const 396 { 397 return _capacity; 398 } 399 400 /* 401 * setLength: 402 * 403 * Change the buffer length of the memory descriptor. When a new buffer 404 * is created, the initial length of the buffer is set to be the same as 405 * the capacity. The length can be adjusted via setLength for a shorter 406 * transfer (there is no need to create more buffer descriptors when you 407 * can reuse an existing one, even for different transfer sizes). Note 408 * that the specified length must not exceed the capacity of the buffer. 409 */ 410 void IOBufferMemoryDescriptor::setLength(vm_size_t length) 411 { 412 assert(length <= _capacity); 413 414 _length = length; 415 _singleRange.v.length = length; 416 } 417 418 /* 419 * setDirection: 420 * 421 * Change the direction of the transfer. This method allows one to redirect 422 * the descriptor's transfer direction. This eliminates the need to destroy 423 * and create new buffers when different transfer directions are needed. 424 */ 425 void IOBufferMemoryDescriptor::setDirection(IODirection direction) 426 { 427 _direction = direction; 428 } 429 430 /* 431 * appendBytes: 432 * 433 * Add some data to the end of the buffer. This method automatically 434 * maintains the memory descriptor buffer length. Note that appendBytes 435 * will not copy past the end of the memory descriptor's current capacity. 436 */ 437 bool 438 IOBufferMemoryDescriptor::appendBytes(const void * bytes, vm_size_t withLength) 439 { 440 vm_size_t actualBytesToCopy = min(withLength, _capacity - _length); 441 442 assert(_length <= _capacity); 443 bcopy(/* from */ bytes, (void *)(_singleRange.v.address + _length), 444 actualBytesToCopy); 445 _length += actualBytesToCopy; 446 _singleRange.v.length += actualBytesToCopy; 447 448 return true; 449 } 450 451 /* 452 * getBytesNoCopy: 453 * 454 * Return the virtual address of the beginning of the buffer 455 */ 456 void * IOBufferMemoryDescriptor::getBytesNoCopy() 457 { 458 return (void *)_singleRange.v.address; 459 } 460 461 /* 462 * getBytesNoCopy: 463 * 464 * Return the virtual address of an offset from the beginning of the buffer 465 */ 466 void * 467 IOBufferMemoryDescriptor::getBytesNoCopy(vm_size_t start, vm_size_t withLength) 468 { 469 if (start < _length && (start + withLength) <= _length) 470 return (void *)(_singleRange.v.address + start); 471 return 0; 472 } 473 474 OSMetaClassDefineReservedUsed(IOBufferMemoryDescriptor, 0); 475 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 1); 476 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 2); 477 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 3); 478 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 4); 479 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 5); 480 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 6); 481 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 7); 482 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 8); 483 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 9); 484 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 10); 485 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 11); 486 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 12); 487 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 13); 488 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 14); 489 OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 15); 490