1c1dac77fSApple OSS Distributions /* 2c1dac77fSApple OSS Distributions * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3c1dac77fSApple OSS Distributions * 4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5c1dac77fSApple OSS Distributions * 6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement. 14c1dac77fSApple OSS Distributions * 15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at 16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17e13b1fa5SApple OSS Distributions * 18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are 19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and 24e13b1fa5SApple OSS Distributions * limitations under the License. 25c1dac77fSApple OSS Distributions * 26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27c1dac77fSApple OSS Distributions */ 28*bb611c8fSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR 293ca3bd55SApple OSS Distributions 303ca3bd55SApple OSS Distributions #define _IOMEMORYDESCRIPTOR_INTERNAL_ 313ca3bd55SApple OSS Distributions 32c1dac77fSApple OSS Distributions #include <IOKit/assert.h> 33c1dac77fSApple OSS Distributions #include <IOKit/system.h> 34c1dac77fSApple OSS Distributions 35c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h> 36e13b1fa5SApple OSS Distributions #include <IOKit/IOMapper.h> 37c1dac77fSApple OSS Distributions #include <IOKit/IOBufferMemoryDescriptor.h> 383ca3bd55SApple OSS Distributions #include <libkern/OSDebug.h> 39186b8fceSApple OSS Distributions #include <mach/mach_vm.h> 40c1dac77fSApple OSS Distributions 4114e3d835SApple OSS Distributions #include "IOKitKernelInternal.h" 4214e3d835SApple OSS Distributions 43186b8fceSApple OSS Distributions #ifdef IOALLOCDEBUG 44186b8fceSApple OSS Distributions #include <libkern/c++/OSCPPDebug.h> 45186b8fceSApple OSS Distributions #endif 46186b8fceSApple OSS Distributions #include <IOKit/IOStatisticsPrivate.h> 47186b8fceSApple OSS Distributions 48186b8fceSApple OSS Distributions #if IOKITSTATS 49186b8fceSApple OSS Distributions #define IOStatisticsAlloc(type, size) \ 50186b8fceSApple OSS Distributions do { \ 51186b8fceSApple OSS Distributions IOStatistics::countAlloc(type, size); \ 52186b8fceSApple OSS Distributions } while (0) 53186b8fceSApple OSS Distributions #else 54186b8fceSApple OSS Distributions #define IOStatisticsAlloc(type, size) 55186b8fceSApple OSS Distributions #endif /* IOKITSTATS */ 56186b8fceSApple OSS Distributions 57186b8fceSApple OSS Distributions 58c1dac77fSApple OSS Distributions __BEGIN_DECLS 59c1dac77fSApple OSS Distributions void ipc_port_release_send(ipc_port_t port); 60fad439e7SApple OSS Distributions #include <vm/pmap.h> 61c1dac77fSApple OSS Distributions 62368ad365SApple OSS Distributions __END_DECLS 63c1dac77fSApple OSS Distributions 64e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 65e13b1fa5SApple OSS Distributions 66a5e72196SApple OSS Distributions enum{ 67855239e5SApple OSS Distributions kInternalFlagPhysical = 0x00000001, 68186b8fceSApple OSS Distributions kInternalFlagPageSized = 0x00000002, 6976e12aa3SApple OSS Distributions kInternalFlagPageAllocated = 0x00000004, 7076e12aa3SApple OSS Distributions kInternalFlagInit = 0x00000008 713ca3bd55SApple OSS Distributions }; 723ca3bd55SApple OSS Distributions 73e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 74e13b1fa5SApple OSS Distributions 75c1dac77fSApple OSS Distributions #define super IOGeneralMemoryDescriptor 76*bb611c8fSApple OSS Distributions OSDefineMetaClassAndStructorsWithZone(IOBufferMemoryDescriptor, 77*bb611c8fSApple OSS Distributions IOGeneralMemoryDescriptor, ZC_ZFREE_CLEARMEM); 78c1dac77fSApple OSS Distributions 793ca3bd55SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 80c1dac77fSApple OSS Distributions 81a5e72196SApple OSS Distributions static uintptr_t 82a5e72196SApple OSS Distributions IOBMDPageProc(iopa_t * a) 83186b8fceSApple OSS Distributions { 84186b8fceSApple OSS Distributions kern_return_t kr; 85186b8fceSApple OSS Distributions vm_address_t vmaddr = 0; 86186b8fceSApple OSS Distributions int options = 0;// KMA_LOMEM; 87186b8fceSApple OSS Distributions 88186b8fceSApple OSS Distributions kr = kernel_memory_allocate(kernel_map, &vmaddr, 890f3703acSApple OSS Distributions page_size, 0, options, VM_KERN_MEMORY_IOKIT); 90186b8fceSApple OSS Distributions 91a5e72196SApple OSS Distributions if (KERN_SUCCESS != kr) { 92a5e72196SApple OSS Distributions vmaddr = 0; 93a5e72196SApple OSS Distributions } else { 94a5e72196SApple OSS Distributions bzero((void *) vmaddr, page_size); 95a5e72196SApple OSS Distributions } 96186b8fceSApple OSS Distributions 97a5e72196SApple OSS Distributions return (uintptr_t) vmaddr; 98186b8fceSApple OSS Distributions } 99186b8fceSApple OSS Distributions 100186b8fceSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 101186b8fceSApple OSS Distributions 1023ca3bd55SApple OSS Distributions #ifndef __LP64__ 103a5e72196SApple OSS Distributions bool 104a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::initWithOptions( 105c1dac77fSApple OSS Distributions IOOptionBits options, 106c1dac77fSApple OSS Distributions vm_size_t capacity, 107fad439e7SApple OSS Distributions vm_offset_t alignment, 108fad439e7SApple OSS Distributions task_t inTask) 109c1dac77fSApple OSS Distributions { 110e13b1fa5SApple OSS Distributions mach_vm_address_t physicalMask = 0; 111a5e72196SApple OSS Distributions return initWithPhysicalMask(inTask, options, capacity, alignment, physicalMask); 112e13b1fa5SApple OSS Distributions } 1133ca3bd55SApple OSS Distributions #endif /* !__LP64__ */ 114e13b1fa5SApple OSS Distributions 115*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 116a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::withCopy( 117a5e72196SApple OSS Distributions task_t inTask, 118a5e72196SApple OSS Distributions IOOptionBits options, 119a5e72196SApple OSS Distributions vm_map_t sourceMap, 120a5e72196SApple OSS Distributions mach_vm_address_t source, 121a5e72196SApple OSS Distributions mach_vm_size_t size) 122a5e72196SApple OSS Distributions { 123*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> inst; 124a5e72196SApple OSS Distributions kern_return_t err; 125a5e72196SApple OSS Distributions vm_map_copy_t copy; 126a5e72196SApple OSS Distributions vm_map_address_t address; 127a5e72196SApple OSS Distributions 128a5e72196SApple OSS Distributions copy = NULL; 129a5e72196SApple OSS Distributions do { 130a5e72196SApple OSS Distributions err = kIOReturnNoMemory; 131*bb611c8fSApple OSS Distributions inst = OSMakeShared<IOBufferMemoryDescriptor>(); 132a5e72196SApple OSS Distributions if (!inst) { 133a5e72196SApple OSS Distributions break; 134a5e72196SApple OSS Distributions } 135a5e72196SApple OSS Distributions inst->_ranges.v64 = IONew(IOAddressRange, 1); 136a5e72196SApple OSS Distributions if (!inst->_ranges.v64) { 137a5e72196SApple OSS Distributions break; 138a5e72196SApple OSS Distributions } 139a5e72196SApple OSS Distributions 140a5e72196SApple OSS Distributions err = vm_map_copyin(sourceMap, source, size, 141a5e72196SApple OSS Distributions false /* src_destroy */, ©); 142a5e72196SApple OSS Distributions if (KERN_SUCCESS != err) { 143a5e72196SApple OSS Distributions break; 144a5e72196SApple OSS Distributions } 145a5e72196SApple OSS Distributions 146a5e72196SApple OSS Distributions err = vm_map_copyout(get_task_map(inTask), &address, copy); 147a5e72196SApple OSS Distributions if (KERN_SUCCESS != err) { 148a5e72196SApple OSS Distributions break; 149a5e72196SApple OSS Distributions } 150a5e72196SApple OSS Distributions copy = NULL; 151a5e72196SApple OSS Distributions 152a5e72196SApple OSS Distributions inst->_ranges.v64->address = address; 153a5e72196SApple OSS Distributions inst->_ranges.v64->length = size; 154a5e72196SApple OSS Distributions 155a5e72196SApple OSS Distributions if (!inst->initWithPhysicalMask(inTask, options, size, page_size, 0)) { 156a5e72196SApple OSS Distributions err = kIOReturnError; 157a5e72196SApple OSS Distributions } 158a5e72196SApple OSS Distributions } while (false); 159a5e72196SApple OSS Distributions 160a5e72196SApple OSS Distributions if (KERN_SUCCESS == err) { 161a5e72196SApple OSS Distributions return inst; 162a5e72196SApple OSS Distributions } 163a5e72196SApple OSS Distributions 164a5e72196SApple OSS Distributions if (copy) { 165a5e72196SApple OSS Distributions vm_map_copy_discard(copy); 166a5e72196SApple OSS Distributions } 167*bb611c8fSApple OSS Distributions 168*bb611c8fSApple OSS Distributions return nullptr; 169a5e72196SApple OSS Distributions } 170a5e72196SApple OSS Distributions 171a5e72196SApple OSS Distributions 172a5e72196SApple OSS Distributions bool 173a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::initWithPhysicalMask( 174e13b1fa5SApple OSS Distributions task_t inTask, 175e13b1fa5SApple OSS Distributions IOOptionBits options, 176e13b1fa5SApple OSS Distributions mach_vm_size_t capacity, 177e13b1fa5SApple OSS Distributions mach_vm_address_t alignment, 178e13b1fa5SApple OSS Distributions mach_vm_address_t physicalMask) 179e13b1fa5SApple OSS Distributions { 180e13b1fa5SApple OSS Distributions task_t mapTask = NULL; 181e13b1fa5SApple OSS Distributions vm_map_t vmmap = NULL; 1823ca3bd55SApple OSS Distributions mach_vm_address_t highestMask = 0; 1833ca3bd55SApple OSS Distributions IOOptionBits iomdOptions = kIOMemoryTypeVirtual64 | kIOMemoryAsReference; 184186b8fceSApple OSS Distributions IODMAMapSpecification mapSpec; 185186b8fceSApple OSS Distributions bool mapped = false; 186a5e72196SApple OSS Distributions bool withCopy = false; 187*bb611c8fSApple OSS Distributions bool mappedOrShared = false; 188fad439e7SApple OSS Distributions 189a5e72196SApple OSS Distributions if (!capacity) { 190a5e72196SApple OSS Distributions return false; 191a5e72196SApple OSS Distributions } 192c1dac77fSApple OSS Distributions 193c1dac77fSApple OSS Distributions _options = options; 194c1dac77fSApple OSS Distributions _capacity = capacity; 1953ca3bd55SApple OSS Distributions _internalFlags = 0; 1963ca3bd55SApple OSS Distributions _internalReserved = 0; 197a5e72196SApple OSS Distributions _buffer = NULL; 198c1dac77fSApple OSS Distributions 199a5e72196SApple OSS Distributions if (!_ranges.v64) { 2003ca3bd55SApple OSS Distributions _ranges.v64 = IONew(IOAddressRange, 1); 201a5e72196SApple OSS Distributions if (!_ranges.v64) { 202a5e72196SApple OSS Distributions return false; 203a5e72196SApple OSS Distributions } 2043ca3bd55SApple OSS Distributions _ranges.v64->address = 0; 2053ca3bd55SApple OSS Distributions _ranges.v64->length = 0; 206a5e72196SApple OSS Distributions } else { 207a5e72196SApple OSS Distributions if (!_ranges.v64->address) { 208a5e72196SApple OSS Distributions return false; 209a5e72196SApple OSS Distributions } 210a5e72196SApple OSS Distributions if (!(kIOMemoryPageable & options)) { 211a5e72196SApple OSS Distributions return false; 212a5e72196SApple OSS Distributions } 213a5e72196SApple OSS Distributions if (!inTask) { 214a5e72196SApple OSS Distributions return false; 215a5e72196SApple OSS Distributions } 216a5e72196SApple OSS Distributions _buffer = (void *) _ranges.v64->address; 217a5e72196SApple OSS Distributions withCopy = true; 218a5e72196SApple OSS Distributions } 219d0c1fef6SApple OSS Distributions // make sure super::free doesn't dealloc _ranges before super::init 220d0c1fef6SApple OSS Distributions _flags = kIOMemoryAsReference; 2213ca3bd55SApple OSS Distributions 2223ca3bd55SApple OSS Distributions // Grab IOMD bits from the Buffer MD options 2233ca3bd55SApple OSS Distributions iomdOptions |= (options & kIOBufferDescriptorMemoryFlags); 2243ca3bd55SApple OSS Distributions 225a5e72196SApple OSS Distributions if (!(kIOMemoryMapperNone & options)) { 226186b8fceSApple OSS Distributions IOMapper::checkForSystemMapper(); 227a5e72196SApple OSS Distributions mapped = (NULL != IOMapper::gSystem); 228186b8fceSApple OSS Distributions } 229186b8fceSApple OSS Distributions 230a5e72196SApple OSS Distributions if (physicalMask && (alignment <= 1)) { 2313ca3bd55SApple OSS Distributions alignment = ((physicalMask ^ (-1ULL)) & (physicalMask - 1)); 2323ca3bd55SApple OSS Distributions highestMask = (physicalMask | alignment); 2333ca3bd55SApple OSS Distributions alignment++; 234a5e72196SApple OSS Distributions if (alignment < page_size) { 235a5e72196SApple OSS Distributions alignment = page_size; 236a5e72196SApple OSS Distributions } 237a5e72196SApple OSS Distributions } 238a5e72196SApple OSS Distributions 239a5e72196SApple OSS Distributions if ((options & (kIOMemorySharingTypeMask | kIOMapCacheMask | kIOMemoryClearEncrypt)) && (alignment < page_size)) { 240855239e5SApple OSS Distributions alignment = page_size; 2413ca3bd55SApple OSS Distributions } 242368ad365SApple OSS Distributions 243a5e72196SApple OSS Distributions if (alignment >= page_size) { 244*bb611c8fSApple OSS Distributions if (round_page_overflow(capacity, &capacity)) { 245*bb611c8fSApple OSS Distributions return false; 246*bb611c8fSApple OSS Distributions } 247a5e72196SApple OSS Distributions } 2483ca3bd55SApple OSS Distributions 249a5e72196SApple OSS Distributions if (alignment > page_size) { 2503ca3bd55SApple OSS Distributions options |= kIOMemoryPhysicallyContiguous; 251a5e72196SApple OSS Distributions } 252fad439e7SApple OSS Distributions 253c1dac77fSApple OSS Distributions _alignment = alignment; 254fad439e7SApple OSS Distributions 255a5e72196SApple OSS Distributions if ((capacity + alignment) < _capacity) { 256e13b1fa5SApple OSS Distributions return false; 257a5e72196SApple OSS Distributions } 258a5e72196SApple OSS Distributions 259a5e72196SApple OSS Distributions if ((inTask != kernel_task) && !(options & kIOMemoryPageable)) { 260a5e72196SApple OSS Distributions return false; 261a5e72196SApple OSS Distributions } 262c1dac77fSApple OSS Distributions 263186b8fceSApple OSS Distributions bzero(&mapSpec, sizeof(mapSpec)); 264186b8fceSApple OSS Distributions mapSpec.alignment = _alignment; 265186b8fceSApple OSS Distributions mapSpec.numAddressBits = 64; 266a5e72196SApple OSS Distributions if (highestMask && mapped) { 267a5e72196SApple OSS Distributions if (highestMask <= 0xFFFFFFFF) { 268*bb611c8fSApple OSS Distributions mapSpec.numAddressBits = (uint8_t)(32 - __builtin_clz((unsigned int) highestMask)); 269a5e72196SApple OSS Distributions } else { 270*bb611c8fSApple OSS Distributions mapSpec.numAddressBits = (uint8_t)(64 - __builtin_clz((unsigned int) (highestMask >> 32))); 271a5e72196SApple OSS Distributions } 272186b8fceSApple OSS Distributions highestMask = 0; 273186b8fceSApple OSS Distributions } 274186b8fceSApple OSS Distributions 275a3bb9fccSApple OSS Distributions // set memory entry cache mode, pageable, purgeable 276a3bb9fccSApple OSS Distributions iomdOptions |= ((options & kIOMapCacheMask) >> kIOMapCacheShift) << kIOMemoryBufferCacheShift; 277a5e72196SApple OSS Distributions if (options & kIOMemoryPageable) { 278e13b1fa5SApple OSS Distributions iomdOptions |= kIOMemoryBufferPageable; 279a5e72196SApple OSS Distributions if (options & kIOMemoryPurgeable) { 280a5e72196SApple OSS Distributions iomdOptions |= kIOMemoryBufferPurgeable; 281e13b1fa5SApple OSS Distributions } 282a5e72196SApple OSS Distributions } else { 283e13b1fa5SApple OSS Distributions vmmap = kernel_map; 284e13b1fa5SApple OSS Distributions 285e13b1fa5SApple OSS Distributions // Buffer shouldn't auto prepare they should be prepared explicitly 286e13b1fa5SApple OSS Distributions // But it never was enforced so what are you going to do? 287e13b1fa5SApple OSS Distributions iomdOptions |= kIOMemoryAutoPrepare; 288e13b1fa5SApple OSS Distributions 289e13b1fa5SApple OSS Distributions /* Allocate a wired-down buffer inside kernel space. */ 290855239e5SApple OSS Distributions 291186b8fceSApple OSS Distributions bool contig = (0 != (options & kIOMemoryHostPhysicallyContiguous)); 292186b8fceSApple OSS Distributions 293a5e72196SApple OSS Distributions if (!contig && (0 != (options & kIOMemoryPhysicallyContiguous))) { 294186b8fceSApple OSS Distributions contig |= (!mapped); 295186b8fceSApple OSS Distributions contig |= (0 != (kIOMemoryMapperNone & options)); 296186b8fceSApple OSS Distributions #if 0 297186b8fceSApple OSS Distributions // treat kIOMemoryPhysicallyContiguous as kIOMemoryHostPhysicallyContiguous for now 298186b8fceSApple OSS Distributions contig |= true; 299186b8fceSApple OSS Distributions #endif 300186b8fceSApple OSS Distributions } 301186b8fceSApple OSS Distributions 302*bb611c8fSApple OSS Distributions mappedOrShared = (mapped || (0 != (kIOMemorySharingTypeMask & options))); 303a5e72196SApple OSS Distributions if (contig || highestMask || (alignment > page_size)) { 304855239e5SApple OSS Distributions _internalFlags |= kInternalFlagPhysical; 305a5e72196SApple OSS Distributions if (highestMask) { 306855239e5SApple OSS Distributions _internalFlags |= kInternalFlagPageSized; 307*bb611c8fSApple OSS Distributions if (round_page_overflow(capacity, &capacity)) { 308*bb611c8fSApple OSS Distributions return false; 309*bb611c8fSApple OSS Distributions } 310855239e5SApple OSS Distributions } 311186b8fceSApple OSS Distributions _buffer = (void *) IOKernelAllocateWithPhysicalRestrict( 312186b8fceSApple OSS Distributions capacity, highestMask, alignment, contig); 313*bb611c8fSApple OSS Distributions } else if (mappedOrShared 314*bb611c8fSApple OSS Distributions && (capacity + alignment) <= (page_size - gIOPageAllocChunkBytes)) { 315186b8fceSApple OSS Distributions _internalFlags |= kInternalFlagPageAllocated; 316186b8fceSApple OSS Distributions _buffer = (void *) iopa_alloc(&gIOBMDPageAllocator, &IOBMDPageProc, capacity, alignment); 317a5e72196SApple OSS Distributions if (_buffer) { 318186b8fceSApple OSS Distributions IOStatisticsAlloc(kIOStatisticsMallocAligned, capacity); 319186b8fceSApple OSS Distributions #if IOALLOCDEBUG 320*bb611c8fSApple OSS Distributions OSAddAtomicLong(capacity, &debug_iomalloc_size); 321186b8fceSApple OSS Distributions #endif 322186b8fceSApple OSS Distributions } 323a5e72196SApple OSS Distributions } else if (alignment > 1) { 324e13b1fa5SApple OSS Distributions _buffer = IOMallocAligned(capacity, alignment); 325a5e72196SApple OSS Distributions } else { 326e13b1fa5SApple OSS Distributions _buffer = IOMalloc(capacity); 3273ca3bd55SApple OSS Distributions } 328a5e72196SApple OSS Distributions if (!_buffer) { 329e13b1fa5SApple OSS Distributions return false; 330e13b1fa5SApple OSS Distributions } 331a5e72196SApple OSS Distributions bzero(_buffer, capacity); 332a5e72196SApple OSS Distributions } 333e13b1fa5SApple OSS Distributions 334855239e5SApple OSS Distributions if ((options & (kIOMemoryPageable | kIOMapCacheMask))) { 3353ca3bd55SApple OSS Distributions vm_size_t size = round_page(capacity); 336e13b1fa5SApple OSS Distributions 337a3bb9fccSApple OSS Distributions // initWithOptions will create memory entry 338a5e72196SApple OSS Distributions if (!withCopy) { 339a3bb9fccSApple OSS Distributions iomdOptions |= kIOMemoryPersistent; 340a5e72196SApple OSS Distributions } 341e13b1fa5SApple OSS Distributions 342e13b1fa5SApple OSS Distributions if (options & kIOMemoryPageable) { 34314e3d835SApple OSS Distributions #if IOALLOCDEBUG 3440f3703acSApple OSS Distributions OSAddAtomicLong(size, &debug_iomallocpageable_size); 34514e3d835SApple OSS Distributions #endif 346a5e72196SApple OSS Distributions if (!withCopy) { 347e13b1fa5SApple OSS Distributions mapTask = inTask; 348a5e72196SApple OSS Distributions } 349a5e72196SApple OSS Distributions if (NULL == inTask) { 35014e3d835SApple OSS Distributions inTask = kernel_task; 351e13b1fa5SApple OSS Distributions } 352a5e72196SApple OSS Distributions } else if (options & kIOMapCacheMask) { 353e13b1fa5SApple OSS Distributions // Prefetch each page to put entries into the pmap 354e13b1fa5SApple OSS Distributions volatile UInt8 * startAddr = (UInt8 *)_buffer; 355e13b1fa5SApple OSS Distributions volatile UInt8 * endAddr = (UInt8 *)_buffer + capacity; 356e13b1fa5SApple OSS Distributions 357a5e72196SApple OSS Distributions while (startAddr < endAddr) { 358186b8fceSApple OSS Distributions UInt8 dummyVar = *startAddr; 359186b8fceSApple OSS Distributions (void) dummyVar; 360e13b1fa5SApple OSS Distributions startAddr += page_size; 361e13b1fa5SApple OSS Distributions } 362e13b1fa5SApple OSS Distributions } 363e13b1fa5SApple OSS Distributions } 364e13b1fa5SApple OSS Distributions 365a5e72196SApple OSS Distributions _ranges.v64->address = (mach_vm_address_t) _buffer; 3663ca3bd55SApple OSS Distributions _ranges.v64->length = _capacity; 367e13b1fa5SApple OSS Distributions 3683ca3bd55SApple OSS Distributions if (!super::initWithOptions(_ranges.v64, 1, 0, 369a5e72196SApple OSS Distributions inTask, iomdOptions, /* System mapper */ NULL)) { 370e13b1fa5SApple OSS Distributions return false; 371a5e72196SApple OSS Distributions } 372e13b1fa5SApple OSS Distributions 37376e12aa3SApple OSS Distributions _internalFlags |= kInternalFlagInit; 37476e12aa3SApple OSS Distributions #if IOTRACKING 375a5e72196SApple OSS Distributions if (!(options & kIOMemoryPageable)) { 376a5e72196SApple OSS Distributions trackingAccumSize(capacity); 377a5e72196SApple OSS Distributions } 37876e12aa3SApple OSS Distributions #endif /* IOTRACKING */ 37976e12aa3SApple OSS Distributions 380186b8fceSApple OSS Distributions // give any system mapper the allocation params 381186b8fceSApple OSS Distributions if (kIOReturnSuccess != dmaCommandOperation(kIOMDAddDMAMapSpec, 382a5e72196SApple OSS Distributions &mapSpec, sizeof(mapSpec))) { 383186b8fceSApple OSS Distributions return false; 384a5e72196SApple OSS Distributions } 385186b8fceSApple OSS Distributions 386a5e72196SApple OSS Distributions if (mapTask) { 38714e3d835SApple OSS Distributions if (!reserved) { 38814e3d835SApple OSS Distributions reserved = IONew( ExpansionData, 1 ); 389a5e72196SApple OSS Distributions if (!reserved) { 390a5e72196SApple OSS Distributions return false; 391a5e72196SApple OSS Distributions } 39214e3d835SApple OSS Distributions } 3933ca3bd55SApple OSS Distributions reserved->map = createMappingInTask(mapTask, 0, 394*bb611c8fSApple OSS Distributions kIOMapAnywhere | (options & kIOMapPrefault) | (options & kIOMapCacheMask), 0, 0).detach(); 395a5e72196SApple OSS Distributions if (!reserved->map) { 396a5e72196SApple OSS Distributions _buffer = NULL; 397a5e72196SApple OSS Distributions return false; 39814e3d835SApple OSS Distributions } 399e13b1fa5SApple OSS Distributions release(); // map took a retain on this 4003ca3bd55SApple OSS Distributions reserved->map->retain(); 4013ca3bd55SApple OSS Distributions removeMapping(reserved->map); 402e13b1fa5SApple OSS Distributions mach_vm_address_t buffer = reserved->map->getAddress(); 403e13b1fa5SApple OSS Distributions _buffer = (void *) buffer; 404a5e72196SApple OSS Distributions if (kIOMemoryTypeVirtual64 == (kIOMemoryTypeMask & iomdOptions)) { 405e13b1fa5SApple OSS Distributions _ranges.v64->address = buffer; 406fad439e7SApple OSS Distributions } 407a5e72196SApple OSS Distributions } 408c1dac77fSApple OSS Distributions 4093ca3bd55SApple OSS Distributions setLength(_capacity); 410c1dac77fSApple OSS Distributions 411c1dac77fSApple OSS Distributions return true; 412c1dac77fSApple OSS Distributions } 413c1dac77fSApple OSS Distributions 414*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 415a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::inTaskWithOptions( 416fad439e7SApple OSS Distributions task_t inTask, 417fad439e7SApple OSS Distributions IOOptionBits options, 418fad439e7SApple OSS Distributions vm_size_t capacity, 419368ad365SApple OSS Distributions vm_offset_t alignment) 420fad439e7SApple OSS Distributions { 421*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> me = OSMakeShared<IOBufferMemoryDescriptor>(); 422fad439e7SApple OSS Distributions 4233ca3bd55SApple OSS Distributions if (me && !me->initWithPhysicalMask(inTask, options, capacity, alignment, 0)) { 424*bb611c8fSApple OSS Distributions me.reset(); 425e13b1fa5SApple OSS Distributions } 426e13b1fa5SApple OSS Distributions return me; 427e13b1fa5SApple OSS Distributions } 428e13b1fa5SApple OSS Distributions 429*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 430*bb611c8fSApple OSS Distributions IOBufferMemoryDescriptor::inTaskWithOptions( 431*bb611c8fSApple OSS Distributions task_t inTask, 432*bb611c8fSApple OSS Distributions IOOptionBits options, 433*bb611c8fSApple OSS Distributions vm_size_t capacity, 434*bb611c8fSApple OSS Distributions vm_offset_t alignment, 435*bb611c8fSApple OSS Distributions uint32_t kernTag, 436*bb611c8fSApple OSS Distributions uint32_t userTag) 437*bb611c8fSApple OSS Distributions { 438*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> me = OSMakeShared<IOBufferMemoryDescriptor>(); 439*bb611c8fSApple OSS Distributions 440*bb611c8fSApple OSS Distributions if (me) { 441*bb611c8fSApple OSS Distributions me->setVMTags(kernTag, userTag); 442*bb611c8fSApple OSS Distributions 443*bb611c8fSApple OSS Distributions if (!me->initWithPhysicalMask(inTask, options, capacity, alignment, 0)) { 444*bb611c8fSApple OSS Distributions me.reset(); 445*bb611c8fSApple OSS Distributions } 446*bb611c8fSApple OSS Distributions } 447*bb611c8fSApple OSS Distributions return me; 448*bb611c8fSApple OSS Distributions } 449*bb611c8fSApple OSS Distributions 450*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 451a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::inTaskWithPhysicalMask( 452e13b1fa5SApple OSS Distributions task_t inTask, 453e13b1fa5SApple OSS Distributions IOOptionBits options, 454e13b1fa5SApple OSS Distributions mach_vm_size_t capacity, 455e13b1fa5SApple OSS Distributions mach_vm_address_t physicalMask) 456e13b1fa5SApple OSS Distributions { 457*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> me = OSMakeShared<IOBufferMemoryDescriptor>(); 458e13b1fa5SApple OSS Distributions 459a5e72196SApple OSS Distributions if (me && !me->initWithPhysicalMask(inTask, options, capacity, 1, physicalMask)) { 460*bb611c8fSApple OSS Distributions me.reset(); 461fad439e7SApple OSS Distributions } 462fad439e7SApple OSS Distributions return me; 463fad439e7SApple OSS Distributions } 464fad439e7SApple OSS Distributions 4653ca3bd55SApple OSS Distributions #ifndef __LP64__ 466a5e72196SApple OSS Distributions bool 467a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::initWithOptions( 468fad439e7SApple OSS Distributions IOOptionBits options, 469fad439e7SApple OSS Distributions vm_size_t capacity, 470fad439e7SApple OSS Distributions vm_offset_t alignment) 471fad439e7SApple OSS Distributions { 472a5e72196SApple OSS Distributions return initWithPhysicalMask(kernel_task, options, capacity, alignment, (mach_vm_address_t)0); 473fad439e7SApple OSS Distributions } 4743ca3bd55SApple OSS Distributions #endif /* !__LP64__ */ 475fad439e7SApple OSS Distributions 476*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 477a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::withOptions( 478c1dac77fSApple OSS Distributions IOOptionBits options, 479c1dac77fSApple OSS Distributions vm_size_t capacity, 480368ad365SApple OSS Distributions vm_offset_t alignment) 481c1dac77fSApple OSS Distributions { 482*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> me = OSMakeShared<IOBufferMemoryDescriptor>(); 4833ca3bd55SApple OSS Distributions 4843ca3bd55SApple OSS Distributions if (me && !me->initWithPhysicalMask(kernel_task, options, capacity, alignment, 0)) { 485*bb611c8fSApple OSS Distributions me.reset(); 4863ca3bd55SApple OSS Distributions } 4873ca3bd55SApple OSS Distributions return me; 488c1dac77fSApple OSS Distributions } 489c1dac77fSApple OSS Distributions 490c1dac77fSApple OSS Distributions 491c1dac77fSApple OSS Distributions /* 492c1dac77fSApple OSS Distributions * withCapacity: 493c1dac77fSApple OSS Distributions * 494c1dac77fSApple OSS Distributions * Returns a new IOBufferMemoryDescriptor with a buffer large enough to 495c1dac77fSApple OSS Distributions * hold capacity bytes. The descriptor's length is initially set to the capacity. 496c1dac77fSApple OSS Distributions */ 497*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 498c1dac77fSApple OSS Distributions IOBufferMemoryDescriptor::withCapacity(vm_size_t inCapacity, 499c1dac77fSApple OSS Distributions IODirection inDirection, 500c1dac77fSApple OSS Distributions bool inContiguous) 501c1dac77fSApple OSS Distributions { 502a5e72196SApple OSS Distributions return IOBufferMemoryDescriptor::withOptions( 503c1dac77fSApple OSS Distributions inDirection | kIOMemoryUnshared 504c1dac77fSApple OSS Distributions | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), 505a5e72196SApple OSS Distributions inCapacity, inContiguous ? inCapacity : 1 ); 506c1dac77fSApple OSS Distributions } 507c1dac77fSApple OSS Distributions 5083ca3bd55SApple OSS Distributions #ifndef __LP64__ 509c1dac77fSApple OSS Distributions /* 510c1dac77fSApple OSS Distributions * initWithBytes: 511c1dac77fSApple OSS Distributions * 512c1dac77fSApple OSS Distributions * Initialize a new IOBufferMemoryDescriptor preloaded with bytes (copied). 513c1dac77fSApple OSS Distributions * The descriptor's length and capacity are set to the input buffer's size. 514c1dac77fSApple OSS Distributions */ 515a5e72196SApple OSS Distributions bool 516a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::initWithBytes(const void * inBytes, 517c1dac77fSApple OSS Distributions vm_size_t inLength, 518c1dac77fSApple OSS Distributions IODirection inDirection, 519c1dac77fSApple OSS Distributions bool inContiguous) 520c1dac77fSApple OSS Distributions { 5213ca3bd55SApple OSS Distributions if (!initWithPhysicalMask(kernel_task, inDirection | kIOMemoryUnshared 522c1dac77fSApple OSS Distributions | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), 523a5e72196SApple OSS Distributions inLength, inLength, (mach_vm_address_t)0)) { 524c1dac77fSApple OSS Distributions return false; 525a5e72196SApple OSS Distributions } 526c1dac77fSApple OSS Distributions 527c1dac77fSApple OSS Distributions // start out with no data 528c1dac77fSApple OSS Distributions setLength(0); 529c1dac77fSApple OSS Distributions 530a5e72196SApple OSS Distributions if (!appendBytes(inBytes, inLength)) { 531c1dac77fSApple OSS Distributions return false; 532a5e72196SApple OSS Distributions } 533c1dac77fSApple OSS Distributions 534c1dac77fSApple OSS Distributions return true; 535c1dac77fSApple OSS Distributions } 5363ca3bd55SApple OSS Distributions #endif /* !__LP64__ */ 537c1dac77fSApple OSS Distributions 538c1dac77fSApple OSS Distributions /* 539c1dac77fSApple OSS Distributions * withBytes: 540c1dac77fSApple OSS Distributions * 541c1dac77fSApple OSS Distributions * Returns a new IOBufferMemoryDescriptor preloaded with bytes (copied). 542c1dac77fSApple OSS Distributions * The descriptor's length and capacity are set to the input buffer's size. 543c1dac77fSApple OSS Distributions */ 544*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> 545c1dac77fSApple OSS Distributions IOBufferMemoryDescriptor::withBytes(const void * inBytes, 546c1dac77fSApple OSS Distributions vm_size_t inLength, 547c1dac77fSApple OSS Distributions IODirection inDirection, 548c1dac77fSApple OSS Distributions bool inContiguous) 549c1dac77fSApple OSS Distributions { 550*bb611c8fSApple OSS Distributions OSSharedPtr<IOBufferMemoryDescriptor> me = OSMakeShared<IOBufferMemoryDescriptor>(); 551c1dac77fSApple OSS Distributions 5523ca3bd55SApple OSS Distributions if (me && !me->initWithPhysicalMask( 5533ca3bd55SApple OSS Distributions kernel_task, inDirection | kIOMemoryUnshared 5543ca3bd55SApple OSS Distributions | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), 555a5e72196SApple OSS Distributions inLength, inLength, 0 )) { 556*bb611c8fSApple OSS Distributions me.reset(); 557c1dac77fSApple OSS Distributions } 5583ca3bd55SApple OSS Distributions 559a5e72196SApple OSS Distributions if (me) { 5603ca3bd55SApple OSS Distributions // start out with no data 5613ca3bd55SApple OSS Distributions me->setLength(0); 5623ca3bd55SApple OSS Distributions 563a5e72196SApple OSS Distributions if (!me->appendBytes(inBytes, inLength)) { 564*bb611c8fSApple OSS Distributions me.reset(); 5653ca3bd55SApple OSS Distributions } 5663ca3bd55SApple OSS Distributions } 567c1dac77fSApple OSS Distributions return me; 568c1dac77fSApple OSS Distributions } 569c1dac77fSApple OSS Distributions 570c1dac77fSApple OSS Distributions /* 571c1dac77fSApple OSS Distributions * free: 572c1dac77fSApple OSS Distributions * 573c1dac77fSApple OSS Distributions * Free resources 574c1dac77fSApple OSS Distributions */ 575a5e72196SApple OSS Distributions void 576a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::free() 577c1dac77fSApple OSS Distributions { 578368ad365SApple OSS Distributions // Cache all of the relevant information on the stack for use 579368ad365SApple OSS Distributions // after we call super::free()! 580e13b1fa5SApple OSS Distributions IOOptionBits flags = _flags; 581855239e5SApple OSS Distributions IOOptionBits internalFlags = _internalFlags; 582c1dac77fSApple OSS Distributions IOOptionBits options = _options; 583c1dac77fSApple OSS Distributions vm_size_t size = _capacity; 584c1dac77fSApple OSS Distributions void * buffer = _buffer; 585a5e72196SApple OSS Distributions IOMemoryMap * map = NULL; 5863ca3bd55SApple OSS Distributions IOAddressRange * range = _ranges.v64; 587c1dac77fSApple OSS Distributions vm_offset_t alignment = _alignment; 588c1dac77fSApple OSS Distributions 589a5e72196SApple OSS Distributions if (alignment >= page_size) { 5903ca3bd55SApple OSS Distributions size = round_page(size); 591a5e72196SApple OSS Distributions } 5923ca3bd55SApple OSS Distributions 593a5e72196SApple OSS Distributions if (reserved) { 594e13b1fa5SApple OSS Distributions map = reserved->map; 595fad439e7SApple OSS Distributions IODelete( reserved, ExpansionData, 1 ); 596a5e72196SApple OSS Distributions if (map) { 597e13b1fa5SApple OSS Distributions map->release(); 598fad439e7SApple OSS Distributions } 599a5e72196SApple OSS Distributions } 600fad439e7SApple OSS Distributions 60176e12aa3SApple OSS Distributions if ((options & kIOMemoryPageable) 602a5e72196SApple OSS Distributions || (kInternalFlagPageSized & internalFlags)) { 603a5e72196SApple OSS Distributions size = round_page(size); 604a5e72196SApple OSS Distributions } 60576e12aa3SApple OSS Distributions 60676e12aa3SApple OSS Distributions #if IOTRACKING 60776e12aa3SApple OSS Distributions if (!(options & kIOMemoryPageable) 60876e12aa3SApple OSS Distributions && buffer 609a5e72196SApple OSS Distributions && (kInternalFlagInit & _internalFlags)) { 610a5e72196SApple OSS Distributions trackingAccumSize(-size); 611a5e72196SApple OSS Distributions } 61276e12aa3SApple OSS Distributions #endif /* IOTRACKING */ 61376e12aa3SApple OSS Distributions 614c1dac77fSApple OSS Distributions /* super::free may unwire - deallocate buffer afterwards */ 615c1dac77fSApple OSS Distributions super::free(); 616c1dac77fSApple OSS Distributions 617a5e72196SApple OSS Distributions if (options & kIOMemoryPageable) { 61814e3d835SApple OSS Distributions #if IOALLOCDEBUG 61976e12aa3SApple OSS Distributions OSAddAtomicLong(-size, &debug_iomallocpageable_size); 62014e3d835SApple OSS Distributions #endif 621a5e72196SApple OSS Distributions } else if (buffer) { 622a5e72196SApple OSS Distributions if (kInternalFlagPhysical & internalFlags) { 623855239e5SApple OSS Distributions IOKernelFreePhysical((mach_vm_address_t) buffer, size); 624a5e72196SApple OSS Distributions } else if (kInternalFlagPageAllocated & internalFlags) { 625186b8fceSApple OSS Distributions uintptr_t page; 626186b8fceSApple OSS Distributions page = iopa_free(&gIOBMDPageAllocator, (uintptr_t) buffer, size); 627a5e72196SApple OSS Distributions if (page) { 628186b8fceSApple OSS Distributions kmem_free(kernel_map, page, page_size); 629186b8fceSApple OSS Distributions } 630186b8fceSApple OSS Distributions #if IOALLOCDEBUG 631*bb611c8fSApple OSS Distributions OSAddAtomicLong(-size, &debug_iomalloc_size); 632186b8fceSApple OSS Distributions #endif 633186b8fceSApple OSS Distributions IOStatisticsAlloc(kIOStatisticsFreeAligned, size); 634a5e72196SApple OSS Distributions } else if (alignment > 1) { 635c1dac77fSApple OSS Distributions IOFreeAligned(buffer, size); 636a5e72196SApple OSS Distributions } else { 637c1dac77fSApple OSS Distributions IOFree(buffer, size); 638c1dac77fSApple OSS Distributions } 639186b8fceSApple OSS Distributions } 640a5e72196SApple OSS Distributions if (range && (kIOMemoryAsReference & flags)) { 6413ca3bd55SApple OSS Distributions IODelete(range, IOAddressRange, 1); 642c1dac77fSApple OSS Distributions } 643a5e72196SApple OSS Distributions } 644c1dac77fSApple OSS Distributions 645c1dac77fSApple OSS Distributions /* 646c1dac77fSApple OSS Distributions * getCapacity: 647c1dac77fSApple OSS Distributions * 648c1dac77fSApple OSS Distributions * Get the buffer capacity 649c1dac77fSApple OSS Distributions */ 650a5e72196SApple OSS Distributions vm_size_t 651a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::getCapacity() const 652c1dac77fSApple OSS Distributions { 653c1dac77fSApple OSS Distributions return _capacity; 654c1dac77fSApple OSS Distributions } 655c1dac77fSApple OSS Distributions 656c1dac77fSApple OSS Distributions /* 657c1dac77fSApple OSS Distributions * setLength: 658c1dac77fSApple OSS Distributions * 659c1dac77fSApple OSS Distributions * Change the buffer length of the memory descriptor. When a new buffer 660c1dac77fSApple OSS Distributions * is created, the initial length of the buffer is set to be the same as 661c1dac77fSApple OSS Distributions * the capacity. The length can be adjusted via setLength for a shorter 662c1dac77fSApple OSS Distributions * transfer (there is no need to create more buffer descriptors when you 663c1dac77fSApple OSS Distributions * can reuse an existing one, even for different transfer sizes). Note 664c1dac77fSApple OSS Distributions * that the specified length must not exceed the capacity of the buffer. 665c1dac77fSApple OSS Distributions */ 666a5e72196SApple OSS Distributions void 667a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::setLength(vm_size_t length) 668c1dac77fSApple OSS Distributions { 669c1dac77fSApple OSS Distributions assert(length <= _capacity); 670a5e72196SApple OSS Distributions if (length > _capacity) { 671a5e72196SApple OSS Distributions return; 672a5e72196SApple OSS Distributions } 673c1dac77fSApple OSS Distributions 674c1dac77fSApple OSS Distributions _length = length; 675e13b1fa5SApple OSS Distributions _ranges.v64->length = length; 676c1dac77fSApple OSS Distributions } 677c1dac77fSApple OSS Distributions 678c1dac77fSApple OSS Distributions /* 679c1dac77fSApple OSS Distributions * setDirection: 680c1dac77fSApple OSS Distributions * 681c1dac77fSApple OSS Distributions * Change the direction of the transfer. This method allows one to redirect 682c1dac77fSApple OSS Distributions * the descriptor's transfer direction. This eliminates the need to destroy 683c1dac77fSApple OSS Distributions * and create new buffers when different transfer directions are needed. 684c1dac77fSApple OSS Distributions */ 685a5e72196SApple OSS Distributions void 686a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::setDirection(IODirection direction) 687c1dac77fSApple OSS Distributions { 6883ca3bd55SApple OSS Distributions _flags = (_flags & ~kIOMemoryDirectionMask) | direction; 6893ca3bd55SApple OSS Distributions #ifndef __LP64__ 6903ca3bd55SApple OSS Distributions _direction = (IODirection) (_flags & kIOMemoryDirectionMask); 6913ca3bd55SApple OSS Distributions #endif /* !__LP64__ */ 692c1dac77fSApple OSS Distributions } 693c1dac77fSApple OSS Distributions 694c1dac77fSApple OSS Distributions /* 695c1dac77fSApple OSS Distributions * appendBytes: 696c1dac77fSApple OSS Distributions * 697c1dac77fSApple OSS Distributions * Add some data to the end of the buffer. This method automatically 698c1dac77fSApple OSS Distributions * maintains the memory descriptor buffer length. Note that appendBytes 699c1dac77fSApple OSS Distributions * will not copy past the end of the memory descriptor's current capacity. 700c1dac77fSApple OSS Distributions */ 701c1dac77fSApple OSS Distributions bool 702c1dac77fSApple OSS Distributions IOBufferMemoryDescriptor::appendBytes(const void * bytes, vm_size_t withLength) 703c1dac77fSApple OSS Distributions { 704c1dac77fSApple OSS Distributions vm_size_t actualBytesToCopy = min(withLength, _capacity - _length); 705e13b1fa5SApple OSS Distributions IOByteCount offset; 706c1dac77fSApple OSS Distributions 707c1dac77fSApple OSS Distributions assert(_length <= _capacity); 708e13b1fa5SApple OSS Distributions 709e13b1fa5SApple OSS Distributions offset = _length; 710c1dac77fSApple OSS Distributions _length += actualBytesToCopy; 711e13b1fa5SApple OSS Distributions _ranges.v64->length += actualBytesToCopy; 712e13b1fa5SApple OSS Distributions 713a5e72196SApple OSS Distributions if (_task == kernel_task) { 714e13b1fa5SApple OSS Distributions bcopy(/* from */ bytes, (void *)(_ranges.v64->address + offset), 715e13b1fa5SApple OSS Distributions actualBytesToCopy); 716a5e72196SApple OSS Distributions } else { 717e13b1fa5SApple OSS Distributions writeBytes(offset, bytes, actualBytesToCopy); 718a5e72196SApple OSS Distributions } 719c1dac77fSApple OSS Distributions 720c1dac77fSApple OSS Distributions return true; 721c1dac77fSApple OSS Distributions } 722c1dac77fSApple OSS Distributions 723c1dac77fSApple OSS Distributions /* 724c1dac77fSApple OSS Distributions * getBytesNoCopy: 725c1dac77fSApple OSS Distributions * 726c1dac77fSApple OSS Distributions * Return the virtual address of the beginning of the buffer 727c1dac77fSApple OSS Distributions */ 728a5e72196SApple OSS Distributions void * 729a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::getBytesNoCopy() 730c1dac77fSApple OSS Distributions { 731a5e72196SApple OSS Distributions if (kIOMemoryTypePhysical64 == (_flags & kIOMemoryTypeMask)) { 732e13b1fa5SApple OSS Distributions return _buffer; 733a5e72196SApple OSS Distributions } else { 734e13b1fa5SApple OSS Distributions return (void *)_ranges.v64->address; 735c1dac77fSApple OSS Distributions } 736a5e72196SApple OSS Distributions } 737c1dac77fSApple OSS Distributions 738e13b1fa5SApple OSS Distributions 739c1dac77fSApple OSS Distributions /* 740c1dac77fSApple OSS Distributions * getBytesNoCopy: 741c1dac77fSApple OSS Distributions * 742c1dac77fSApple OSS Distributions * Return the virtual address of an offset from the beginning of the buffer 743c1dac77fSApple OSS Distributions */ 744c1dac77fSApple OSS Distributions void * 745c1dac77fSApple OSS Distributions IOBufferMemoryDescriptor::getBytesNoCopy(vm_size_t start, vm_size_t withLength) 746c1dac77fSApple OSS Distributions { 747e13b1fa5SApple OSS Distributions IOVirtualAddress address; 74888cc0b97SApple OSS Distributions 749a5e72196SApple OSS Distributions if ((start + withLength) < start) { 750a5e72196SApple OSS Distributions return NULL; 751a5e72196SApple OSS Distributions } 75288cc0b97SApple OSS Distributions 753a5e72196SApple OSS Distributions if (kIOMemoryTypePhysical64 == (_flags & kIOMemoryTypeMask)) { 754e13b1fa5SApple OSS Distributions address = (IOVirtualAddress) _buffer; 755a5e72196SApple OSS Distributions } else { 756e13b1fa5SApple OSS Distributions address = _ranges.v64->address; 757a5e72196SApple OSS Distributions } 758e13b1fa5SApple OSS Distributions 759a5e72196SApple OSS Distributions if (start < _length && (start + withLength) <= _length) { 760e13b1fa5SApple OSS Distributions return (void *)(address + start); 761a5e72196SApple OSS Distributions } 762a5e72196SApple OSS Distributions return NULL; 763c1dac77fSApple OSS Distributions } 764c1dac77fSApple OSS Distributions 7653ca3bd55SApple OSS Distributions #ifndef __LP64__ 766a5e72196SApple OSS Distributions void * 767a5e72196SApple OSS Distributions IOBufferMemoryDescriptor::getVirtualSegment(IOByteCount offset, 7683ca3bd55SApple OSS Distributions IOByteCount * lengthOfSegment) 769e13b1fa5SApple OSS Distributions { 770e13b1fa5SApple OSS Distributions void * bytes = getBytesNoCopy(offset, 0); 771e13b1fa5SApple OSS Distributions 772a5e72196SApple OSS Distributions if (bytes && lengthOfSegment) { 773e13b1fa5SApple OSS Distributions *lengthOfSegment = _length - offset; 774a5e72196SApple OSS Distributions } 775e13b1fa5SApple OSS Distributions 776e13b1fa5SApple OSS Distributions return bytes; 777e13b1fa5SApple OSS Distributions } 7783ca3bd55SApple OSS Distributions #endif /* !__LP64__ */ 779e13b1fa5SApple OSS Distributions 7803ca3bd55SApple OSS Distributions #ifdef __LP64__ 7813ca3bd55SApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 0); 7823ca3bd55SApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 1); 7833ca3bd55SApple OSS Distributions #else /* !__LP64__ */ 784*bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOBufferMemoryDescriptor, 0); 785*bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOBufferMemoryDescriptor, 1); 7863ca3bd55SApple OSS Distributions #endif /* !__LP64__ */ 787c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 2); 788c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 3); 789c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 4); 790c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 5); 791c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 6); 792c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 7); 793c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 8); 794c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 9); 795c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 10); 796c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 11); 797c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 12); 798c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 13); 799c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 14); 800c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 15); 801