]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOMultiMemoryDescriptor.cpp
xnu-792.18.15.tar.gz
[apple/xnu.git] / iokit / Kernel / IOMultiMemoryDescriptor.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
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
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28
29#include <IOKit/IOLib.h>
30#include <IOKit/IOMultiMemoryDescriptor.h>
31
32#define super IOMemoryDescriptor
33OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor, IOMemoryDescriptor)
34
35// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
36
37bool IOMultiMemoryDescriptor::initWithAddress(
38 void * /* address */ ,
39 IOByteCount /* withLength */ ,
40 IODirection /* withDirection */ )
41{
42 return false;
43}
44
45// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
46
47bool IOMultiMemoryDescriptor::initWithAddress(
48 vm_address_t /* address */ ,
49 IOByteCount /* withLength */ ,
50 IODirection /* withDirection */ ,
51 task_t /* withTask */ )
52{
53 return false;
54}
55
56// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57
58bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
59 IOPhysicalAddress /* address */ ,
60 IOByteCount /* withLength */ ,
61 IODirection /* withDirection */ )
62{
63 return false;
64}
65
66
67// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68
69bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
70 IOPhysicalRange * /* ranges */ ,
71 UInt32 /* withCount */ ,
72 IODirection /* withDirection */ ,
73 bool /* asReference */ )
74{
75 return false;
76}
77
78// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
79
80bool IOMultiMemoryDescriptor::initWithRanges(
81 IOVirtualRange * /* ranges */ ,
82 UInt32 /* withCount */ ,
83 IODirection /* withDirection */ ,
84 task_t /* withTask */ ,
85 bool /* asReference */ )
86{
87 return false;
88}
89
90// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
91
92IOMultiMemoryDescriptor * IOMultiMemoryDescriptor::withDescriptors(
93 IOMemoryDescriptor ** descriptors,
94 UInt32 withCount,
95 IODirection withDirection,
55e303ae 96 bool asReference )
1c79356b
A
97{
98 //
99 // Create a new IOMultiMemoryDescriptor. The "buffer" is made up of several
100 // memory descriptors, that are to be chained end-to-end to make up a single
101 // memory descriptor.
102 //
103 // Passing the ranges as a reference will avoid an extra allocation.
104 //
105
106 IOMultiMemoryDescriptor * me = new IOMultiMemoryDescriptor;
107
108 if ( me && me->initWithDescriptors(
109 /* descriptors */ descriptors,
110 /* withCount */ withCount,
111 /* withDirection */ withDirection,
112 /* asReference */ asReference ) == false )
113 {
114 me->release();
115 me = 0;
116 }
117
118 return me;
119}
120
121// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
122
123bool IOMultiMemoryDescriptor::initWithDescriptors(
124 IOMemoryDescriptor ** descriptors,
125 UInt32 withCount,
126 IODirection withDirection,
55e303ae 127 bool asReference )
1c79356b
A
128{
129 //
130 // Initialize an IOMultiMemoryDescriptor. The "buffer" is made up of several
131 // memory descriptors, that are to be chained end-to-end to make up a single
132 // memory descriptor.
133 //
134 // Passing the ranges as a reference will avoid an extra allocation.
135 //
136
137 assert(descriptors);
138 assert(withCount);
139
55e303ae
A
140 // Release existing descriptors, if any
141 if ( _descriptors )
142 {
143 for ( unsigned index = 0; index < _descriptorsCount; index++ )
144 _descriptors[index]->release();
145
146 if ( _descriptorsIsAllocated )
147 IODelete(_descriptors, IOMemoryDescriptor *, _descriptorsCount);
148 } else {
149 // Ask our superclass' opinion.
150 if ( super::init() == false ) return false;
151 }
152
1c79356b
A
153 // Initialize our minimal state.
154
155 _descriptors = 0;
156 _descriptorsCount = withCount;
157 _descriptorsIsAllocated = asReference ? false : true;
158 _direction = withDirection;
159 _length = 0;
160 _mappings = 0;
161 _tag = 0;
162
163 if ( asReference )
164 {
165 _descriptors = descriptors;
166 }
167 else
168 {
169 _descriptors = IONew(IOMemoryDescriptor *, withCount);
170 if ( _descriptors == 0 ) return false;
171
172 bcopy( /* from */ descriptors,
173 /* to */ _descriptors,
174 /* bytes */ withCount * sizeof(IOMemoryDescriptor *) );
175 }
176
177 for ( unsigned index = 0; index < withCount; index++ )
178 {
179 descriptors[index]->retain();
180 _length += descriptors[index]->getLength();
181 if ( _tag == 0 ) _tag = descriptors[index]->getTag();
182 assert(descriptors[index]->getDirection() == withDirection);
183 }
184
185 return true;
186}
187
188// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
189
190void IOMultiMemoryDescriptor::free()
191{
192 //
193 // Free all of this object's outstanding resources.
194 //
195
196 if ( _descriptors )
197 {
198 for ( unsigned index = 0; index < _descriptorsCount; index++ )
199 _descriptors[index]->release();
200
201 if ( _descriptorsIsAllocated )
202 IODelete(_descriptors, IOMemoryDescriptor *, _descriptorsCount);
203 }
204
205 super::free();
206}
207
208// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
209
210IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection)
211{
212 //
213 // Prepare the memory for an I/O transfer.
214 //
215 // This involves paging in the memory and wiring it down for the duration
216 // of the transfer. The complete() method finishes the processing of the
217 // memory after the I/O transfer finishes.
218 //
219
220 unsigned index;
221 IOReturn status = kIOReturnInternalError;
222 IOReturn statusUndo;
223
224 if ( forDirection == kIODirectionNone )
225 {
226 forDirection = _direction;
227 }
228
229 for ( index = 0; index < _descriptorsCount; index++ )
230 {
231 status = _descriptors[index]->prepare(forDirection);
232 if ( status != kIOReturnSuccess ) break;
233 }
234
235 if ( status != kIOReturnSuccess )
236 {
237 for ( unsigned indexUndo = 0; indexUndo <= index; indexUndo++ )
238 {
239 statusUndo = _descriptors[index]->complete(forDirection);
240 assert(statusUndo == kIOReturnSuccess);
241 }
242 }
243
244 return status;
245}
246
247// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
248
249IOReturn IOMultiMemoryDescriptor::complete(IODirection forDirection)
250{
251 //
252 // Complete processing of the memory after an I/O transfer finishes.
253 //
254 // This method shouldn't be called unless a prepare() was previously issued;
255 // the prepare() and complete() must occur in pairs, before and after an I/O
256 // transfer.
257 //
258
259 IOReturn status;
260 IOReturn statusFinal = kIOReturnSuccess;
261
262 if ( forDirection == kIODirectionNone )
263 {
264 forDirection = _direction;
265 }
266
267 for ( unsigned index = 0; index < _descriptorsCount; index++ )
268 {
269 status = _descriptors[index]->complete(forDirection);
270 if ( status != kIOReturnSuccess ) statusFinal = status;
271 assert(status == kIOReturnSuccess);
272 }
273
274 return statusFinal;
275}
276
277// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
278
89b3af67
A
279addr64_t IOMultiMemoryDescriptor::getPhysicalSegment64(
280 IOByteCount offset, IOByteCount * length )
281{
282 //
283 // This method returns the physical address of the byte at the given offset
284 // into the memory, and optionally the length of the physically contiguous
285 // segment from that offset.
286 //
287
288 assert(offset <= _length);
289
290 for ( unsigned index = 0; index < _descriptorsCount; index++ )
291 {
292 if ( offset < _descriptors[index]->getLength() )
293 {
294 return _descriptors[index]->getPhysicalSegment64(offset, length);
295 }
296 offset -= _descriptors[index]->getLength();
297 }
298
299 if ( length ) *length = 0;
300
301 return 0;
302}
303
304// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
305
306IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment(
307 IOByteCount offset, IOByteCount * length )
1c79356b
A
308{
309 //
310 // This method returns the physical address of the byte at the given offset
311 // into the memory, and optionally the length of the physically contiguous
312 // segment from that offset.
313 //
314
315 assert(offset <= _length);
316
317 for ( unsigned index = 0; index < _descriptorsCount; index++ )
318 {
319 if ( offset < _descriptors[index]->getLength() )
320 {
321 return _descriptors[index]->getPhysicalSegment(offset, length);
322 }
323 offset -= _descriptors[index]->getLength();
324 }
325
326 if ( length ) *length = 0;
327
328 return 0;
329}
330
331// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
332
0b4e3aa0
A
333IOPhysicalAddress IOMultiMemoryDescriptor::getSourceSegment(
334 IOByteCount offset,
335 IOByteCount * length )
336{
337 //
338 // This method returns the physical address of the byte at the given offset
339 // into the memory, and optionally the length of the physically contiguous
340 // segment from that offset.
341 //
342
343 assert(offset <= _length);
344
345 for ( unsigned index = 0; index < _descriptorsCount; index++ )
346 {
347 if ( offset < _descriptors[index]->getLength() )
348 {
349 return _descriptors[index]->getSourceSegment(offset, length);
350 }
351 offset -= _descriptors[index]->getLength();
352 }
353
354 if ( length ) *length = 0;
355
356 return 0;
357}
358
359// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
360
1c79356b
A
361void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount /* offset */ ,
362 IOByteCount * /* length */ )
363{
364 return 0;
365}
366
367// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
368
369IOByteCount IOMultiMemoryDescriptor::readBytes( IOByteCount offset,
370 void * bytes,
371 IOByteCount withLength )
372{
373 //
374 // Copies data from the memory descriptor's buffer at the given offset, to
375 // the specified buffer. Returns the number of bytes copied.
376 //
377
378 IOByteCount bytesCopied = 0;
379 unsigned index;
380
381 for ( index = 0; index < _descriptorsCount; index++ )
382 {
383 if ( offset < _descriptors[index]->getLength() ) break;
384 offset -= _descriptors[index]->getLength();
385 }
386
387 for ( ; index < _descriptorsCount && withLength; index++)
388 {
389 IOByteCount copy = min(_descriptors[index]->getLength(), withLength);
390 IOByteCount copied = _descriptors[index]->readBytes(offset,bytes,copy);
391
392 bytesCopied += copied;
393 if ( copied != copy ) break;
394
395 bytes = ((UInt8 *) bytes) + copied;
396 withLength -= copied;
397 offset = 0;
398 }
399
400 return bytesCopied;
401}
402
403// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
404
405IOByteCount IOMultiMemoryDescriptor::writeBytes( IOByteCount offset,
406 const void * bytes,
407 IOByteCount withLength )
408{
409 //
410 // Copies data to the memory descriptor's buffer at the given offset, from
411 // the specified buffer. Returns the number of bytes copied.
412 //
413
414 IOByteCount bytesCopied = 0;
415 unsigned index;
416
417 for ( index = 0; index < _descriptorsCount; index++ )
418 {
419 if ( offset < _descriptors[index]->getLength() ) break;
420 offset -= _descriptors[index]->getLength();
421 }
422
423 for ( ; index < _descriptorsCount && withLength; index++)
424 {
425 IOByteCount copy = min(_descriptors[index]->getLength(), withLength);
426 IOByteCount copied = _descriptors[index]->writeBytes(offset,bytes,copy);
427
428 bytesCopied += copied;
429 if ( copied != copy ) break;
430
431 bytes = ((UInt8 *) bytes) + copied;
432 withLength -= copied;
433 offset = 0;
434 }
435
436 return bytesCopied;
437}