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