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