| 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, redirect: doRedirect ); | 
| 43 | #endif /* __LP64__ */ | 
| 44 | 	return _parent->redirect( safeTask, redirect: 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(parent: of, offset, length, withDirection: (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: offset + _start, length: &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 | 		atAddress: address, | 
| 214 | 		options, offset: _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 |  |