1 /* 2 * Copyright (c) 1998-2007 Apple 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/IOSubMemoryDescriptor.h> 30 31 #include "IOKitKernelInternal.h" 32 33 #define super IOMemoryDescriptor 34 35 OSDefineMetaClassAndStructors(IOSubMemoryDescriptor, IOMemoryDescriptor) 36 37 IOReturn 38 IOSubMemoryDescriptor::redirect( task_t safeTask, bool doRedirect ) 39 { 40 #ifdef __LP64__ 41 super::redirect( safeTask, doRedirect ); 42 #endif /* __LP64__ */ 43 return _parent->redirect( safeTask, doRedirect ); 44 } 45 46 IOSubMemoryDescriptor * 47 IOSubMemoryDescriptor::withSubRange(IOMemoryDescriptor * of, 48 IOByteCount offset, 49 IOByteCount length, 50 IOOptionBits options) 51 { 52 IOSubMemoryDescriptor *self = new IOSubMemoryDescriptor; 53 54 if (self && !self->initSubRange(of, offset, length, (IODirection) options)) { 55 self->release(); 56 self = NULL; 57 } 58 return self; 59 } 60 61 bool 62 IOSubMemoryDescriptor::initSubRange( IOMemoryDescriptor * parent, 63 IOByteCount offset, IOByteCount length, 64 IODirection direction ) 65 { 66 if (parent && ((offset + length) > parent->getLength())) { 67 return false; 68 } 69 70 /* 71 * We can check the _parent instance variable before having ever set it 72 * to an initial value because I/O Kit guarantees that all our instance 73 * variables are zeroed on an object's allocation. 74 */ 75 76 if (!_parent) { 77 if (!super::init()) { 78 return false; 79 } 80 } else { 81 /* 82 * An existing memory descriptor is being retargeted to 83 * point to somewhere else. Clean up our present state. 84 */ 85 86 _parent->release(); 87 } 88 89 if (parent) { 90 parent->retain(); 91 _tag = parent->getTag(); 92 } else { 93 _tag = 0; 94 } 95 _parent = parent; 96 _start = offset; 97 _length = length; 98 _flags = direction; 99 _flags |= kIOMemoryThreadSafe; 100 101 #ifndef __LP64__ 102 _direction = (IODirection) (_flags & kIOMemoryDirectionMask); 103 #endif /* !__LP64__ */ 104 105 return true; 106 } 107 108 void 109 IOSubMemoryDescriptor::free( void ) 110 { 111 if (_parent) { 112 _parent->release(); 113 } 114 115 super::free(); 116 } 117 118 addr64_t 119 IOSubMemoryDescriptor::getPhysicalSegment(IOByteCount offset, IOByteCount * length, IOOptionBits options) 120 { 121 addr64_t address; 122 IOByteCount actualLength; 123 124 assert(offset <= _length); 125 126 if (length) { 127 *length = 0; 128 } 129 130 if (offset >= _length) { 131 return 0; 132 } 133 134 address = _parent->getPhysicalSegment( offset + _start, &actualLength, options ); 135 136 if (address && length) { 137 *length = min( _length - offset, actualLength ); 138 } 139 140 return address; 141 } 142 143 IOReturn 144 IOSubMemoryDescriptor::setPurgeable( IOOptionBits newState, 145 IOOptionBits * oldState ) 146 { 147 IOReturn err; 148 149 err = _parent->setPurgeable( newState, oldState ); 150 151 return err; 152 } 153 154 IOReturn 155 IOSubMemoryDescriptor::setOwnership( task_t newOwner, 156 int newLedgerTag, 157 IOOptionBits newLedgerOptions ) 158 { 159 IOReturn err; 160 161 if (iokit_iomd_setownership_enabled == FALSE) { 162 return kIOReturnUnsupported; 163 } 164 165 err = _parent->setOwnership( newOwner, newLedgerTag, newLedgerOptions ); 166 167 return err; 168 } 169 170 IOReturn 171 IOSubMemoryDescriptor::prepare( 172 IODirection forDirection) 173 { 174 IOReturn err; 175 176 err = _parent->prepare( forDirection); 177 178 return err; 179 } 180 181 IOReturn 182 IOSubMemoryDescriptor::complete( 183 IODirection forDirection) 184 { 185 IOReturn err; 186 187 err = _parent->complete( forDirection); 188 189 return err; 190 } 191 192 IOMemoryMap * 193 IOSubMemoryDescriptor::makeMapping( 194 IOMemoryDescriptor * owner, 195 task_t intoTask, 196 IOVirtualAddress address, 197 IOOptionBits options, 198 IOByteCount offset, 199 IOByteCount length ) 200 { 201 IOMemoryMap * mapping = NULL; 202 203 #ifndef __LP64__ 204 if (!(kIOMap64Bit & options)) { 205 panic("IOSubMemoryDescriptor::makeMapping !64bit"); 206 } 207 #endif /* !__LP64__ */ 208 209 mapping = (IOMemoryMap *) _parent->makeMapping( 210 owner, 211 intoTask, 212 address, 213 options, _start + offset, length ); 214 215 return mapping; 216 } 217 218 uint64_t 219 IOSubMemoryDescriptor::getPreparationID( void ) 220 { 221 uint64_t pID; 222 223 if (!super::getKernelReserved()) { 224 return kIOPreparationIDUnsupported; 225 } 226 227 pID = _parent->getPreparationID(); 228 if (reserved->kernReserved[0] != pID) { 229 reserved->kernReserved[0] = pID; 230 reserved->preparationID = kIOPreparationIDUnprepared; 231 super::setPreparationID(); 232 } 233 234 return super::getPreparationID(); 235 } 236 237 IOReturn 238 IOSubMemoryDescriptor::getPageCounts(IOByteCount * residentPageCount, 239 IOByteCount * dirtyPageCount) 240 { 241 return _parent->getPageCounts(residentPageCount, dirtyPageCount); 242 } 243