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