2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMultiMemoryDescriptor.h>
34 #define super IOMemoryDescriptor
35 OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor
, IOMemoryDescriptor
)
37 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
39 bool IOMultiMemoryDescriptor::initWithAddress(
40 void * /* address */ ,
41 IOByteCount
/* withLength */ ,
42 IODirection
/* withDirection */ )
47 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49 bool IOMultiMemoryDescriptor::initWithAddress(
50 vm_address_t
/* address */ ,
51 IOByteCount
/* withLength */ ,
52 IODirection
/* withDirection */ ,
53 task_t
/* withTask */ )
58 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
60 bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
61 IOPhysicalAddress
/* address */ ,
62 IOByteCount
/* withLength */ ,
63 IODirection
/* withDirection */ )
69 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
71 bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
72 IOPhysicalRange
* /* ranges */ ,
73 UInt32
/* withCount */ ,
74 IODirection
/* withDirection */ ,
75 bool /* asReference */ )
80 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82 bool IOMultiMemoryDescriptor::initWithRanges(
83 IOVirtualRange
* /* ranges */ ,
84 UInt32
/* withCount */ ,
85 IODirection
/* withDirection */ ,
86 task_t
/* withTask */ ,
87 bool /* asReference */ )
92 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94 IOMultiMemoryDescriptor
* IOMultiMemoryDescriptor::withDescriptors(
95 IOMemoryDescriptor
** descriptors
,
97 IODirection withDirection
,
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.
105 // Passing the ranges as a reference will avoid an extra allocation.
108 IOMultiMemoryDescriptor
* me
= new IOMultiMemoryDescriptor
;
110 if ( me
&& me
->initWithDescriptors(
111 /* descriptors */ descriptors
,
112 /* withCount */ withCount
,
113 /* withDirection */ withDirection
,
114 /* asReference */ asReference
) == false )
123 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
125 bool IOMultiMemoryDescriptor::initWithDescriptors(
126 IOMemoryDescriptor
** descriptors
,
128 IODirection withDirection
,
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.
136 // Passing the ranges as a reference will avoid an extra allocation.
142 // Release existing descriptors, if any
145 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
146 _descriptors
[index
]->release();
148 if ( _descriptorsIsAllocated
)
149 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
151 // Ask our superclass' opinion.
152 if ( super::init() == false ) return false;
155 // Initialize our minimal state.
158 _descriptorsCount
= withCount
;
159 _descriptorsIsAllocated
= asReference
? false : true;
160 _direction
= withDirection
;
167 _descriptors
= descriptors
;
171 _descriptors
= IONew(IOMemoryDescriptor
*, withCount
);
172 if ( _descriptors
== 0 ) return false;
174 bcopy( /* from */ descriptors
,
175 /* to */ _descriptors
,
176 /* bytes */ withCount
* sizeof(IOMemoryDescriptor
*) );
179 for ( unsigned index
= 0; index
< withCount
; index
++ )
181 descriptors
[index
]->retain();
182 _length
+= descriptors
[index
]->getLength();
183 if ( _tag
== 0 ) _tag
= descriptors
[index
]->getTag();
184 assert(descriptors
[index
]->getDirection() == withDirection
);
190 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
192 void IOMultiMemoryDescriptor::free()
195 // Free all of this object's outstanding resources.
200 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
201 _descriptors
[index
]->release();
203 if ( _descriptorsIsAllocated
)
204 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
210 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
212 IOReturn
IOMultiMemoryDescriptor::prepare(IODirection forDirection
)
215 // Prepare the memory for an I/O transfer.
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.
223 IOReturn status
= kIOReturnInternalError
;
226 if ( forDirection
== kIODirectionNone
)
228 forDirection
= _direction
;
231 for ( index
= 0; index
< _descriptorsCount
; index
++ )
233 status
= _descriptors
[index
]->prepare(forDirection
);
234 if ( status
!= kIOReturnSuccess
) break;
237 if ( status
!= kIOReturnSuccess
)
239 for ( unsigned indexUndo
= 0; indexUndo
<= index
; indexUndo
++ )
241 statusUndo
= _descriptors
[index
]->complete(forDirection
);
242 assert(statusUndo
== kIOReturnSuccess
);
249 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
251 IOReturn
IOMultiMemoryDescriptor::complete(IODirection forDirection
)
254 // Complete processing of the memory after an I/O transfer finishes.
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
262 IOReturn statusFinal
= kIOReturnSuccess
;
264 if ( forDirection
== kIODirectionNone
)
266 forDirection
= _direction
;
269 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
271 status
= _descriptors
[index
]->complete(forDirection
);
272 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
273 assert(status
== kIOReturnSuccess
);
279 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
281 addr64_t
IOMultiMemoryDescriptor::getPhysicalSegment64(
282 IOByteCount offset
, IOByteCount
* length
)
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.
290 assert(offset
<= _length
);
292 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
294 if ( offset
< _descriptors
[index
]->getLength() )
296 return _descriptors
[index
]->getPhysicalSegment64(offset
, length
);
298 offset
-= _descriptors
[index
]->getLength();
301 if ( length
) *length
= 0;
306 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
308 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
309 IOByteCount offset
, IOByteCount
* length
)
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.
317 assert(offset
<= _length
);
319 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
321 if ( offset
< _descriptors
[index
]->getLength() )
323 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
325 offset
-= _descriptors
[index
]->getLength();
328 if ( length
) *length
= 0;
333 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
335 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
337 IOByteCount
* length
)
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.
345 assert(offset
<= _length
);
347 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
349 if ( offset
< _descriptors
[index
]->getLength() )
351 return _descriptors
[index
]->getSourceSegment(offset
, length
);
353 offset
-= _descriptors
[index
]->getLength();
356 if ( length
) *length
= 0;
361 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
363 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
364 IOByteCount
* /* length */ )
369 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
371 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
373 IOByteCount withLength
)
376 // Copies data from the memory descriptor's buffer at the given offset, to
377 // the specified buffer. Returns the number of bytes copied.
380 IOByteCount bytesCopied
= 0;
383 for ( index
= 0; index
< _descriptorsCount
; index
++ )
385 if ( offset
< _descriptors
[index
]->getLength() ) break;
386 offset
-= _descriptors
[index
]->getLength();
389 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
391 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
392 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
394 bytesCopied
+= copied
;
395 if ( copied
!= copy
) break;
397 bytes
= ((UInt8
*) bytes
) + copied
;
398 withLength
-= copied
;
405 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
407 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
409 IOByteCount withLength
)
412 // Copies data to the memory descriptor's buffer at the given offset, from
413 // the specified buffer. Returns the number of bytes copied.
416 IOByteCount bytesCopied
= 0;
419 for ( index
= 0; index
< _descriptorsCount
; index
++ )
421 if ( offset
< _descriptors
[index
]->getLength() ) break;
422 offset
-= _descriptors
[index
]->getLength();
425 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
427 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
428 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
430 bytesCopied
+= copied
;
431 if ( copied
!= copy
) break;
433 bytes
= ((UInt8
*) bytes
) + copied
;
434 withLength
-= copied
;