2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IOLib.h>
30 #include <IOKit/IOMultiMemoryDescriptor.h>
32 #define super IOMemoryDescriptor
33 OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor
, IOMemoryDescriptor
)
35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
37 bool IOMultiMemoryDescriptor::initWithAddress(
38 void * /* address */ ,
39 IOByteCount
/* withLength */ ,
40 IODirection
/* withDirection */ )
45 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47 bool IOMultiMemoryDescriptor::initWithAddress(
48 vm_address_t
/* address */ ,
49 IOByteCount
/* withLength */ ,
50 IODirection
/* withDirection */ ,
51 task_t
/* withTask */ )
56 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58 bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
59 IOPhysicalAddress
/* address */ ,
60 IOByteCount
/* withLength */ ,
61 IODirection
/* withDirection */ )
67 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69 bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
70 IOPhysicalRange
* /* ranges */ ,
71 UInt32
/* withCount */ ,
72 IODirection
/* withDirection */ ,
73 bool /* asReference */ )
78 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
80 bool IOMultiMemoryDescriptor::initWithRanges(
81 IOVirtualRange
* /* ranges */ ,
82 UInt32
/* withCount */ ,
83 IODirection
/* withDirection */ ,
84 task_t
/* withTask */ ,
85 bool /* asReference */ )
90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92 IOMultiMemoryDescriptor
* IOMultiMemoryDescriptor::withDescriptors(
93 IOMemoryDescriptor
** descriptors
,
95 IODirection withDirection
,
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.
103 // Passing the ranges as a reference will avoid an extra allocation.
106 IOMultiMemoryDescriptor
* me
= new IOMultiMemoryDescriptor
;
108 if ( me
&& me
->initWithDescriptors(
109 /* descriptors */ descriptors
,
110 /* withCount */ withCount
,
111 /* withDirection */ withDirection
,
112 /* asReference */ asReference
) == false )
121 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123 bool IOMultiMemoryDescriptor::initWithDescriptors(
124 IOMemoryDescriptor
** descriptors
,
126 IODirection withDirection
,
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.
134 // Passing the ranges as a reference will avoid an extra allocation.
140 // Release existing descriptors, if any
143 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
144 _descriptors
[index
]->release();
146 if ( _descriptorsIsAllocated
)
147 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
149 // Ask our superclass' opinion.
150 if ( super::init() == false ) return false;
153 // Initialize our minimal state.
156 _descriptorsCount
= withCount
;
157 _descriptorsIsAllocated
= asReference
? false : true;
158 _direction
= withDirection
;
165 _descriptors
= descriptors
;
169 _descriptors
= IONew(IOMemoryDescriptor
*, withCount
);
170 if ( _descriptors
== 0 ) return false;
172 bcopy( /* from */ descriptors
,
173 /* to */ _descriptors
,
174 /* bytes */ withCount
* sizeof(IOMemoryDescriptor
*) );
177 for ( unsigned index
= 0; index
< withCount
; index
++ )
179 descriptors
[index
]->retain();
180 _length
+= descriptors
[index
]->getLength();
181 if ( _tag
== 0 ) _tag
= descriptors
[index
]->getTag();
182 assert(descriptors
[index
]->getDirection() == withDirection
);
188 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190 void IOMultiMemoryDescriptor::free()
193 // Free all of this object's outstanding resources.
198 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
199 _descriptors
[index
]->release();
201 if ( _descriptorsIsAllocated
)
202 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
208 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
210 IOReturn
IOMultiMemoryDescriptor::prepare(IODirection forDirection
)
213 // Prepare the memory for an I/O transfer.
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.
221 IOReturn status
= kIOReturnInternalError
;
224 if ( forDirection
== kIODirectionNone
)
226 forDirection
= _direction
;
229 for ( index
= 0; index
< _descriptorsCount
; index
++ )
231 status
= _descriptors
[index
]->prepare(forDirection
);
232 if ( status
!= kIOReturnSuccess
) break;
235 if ( status
!= kIOReturnSuccess
)
237 for ( unsigned indexUndo
= 0; indexUndo
<= index
; indexUndo
++ )
239 statusUndo
= _descriptors
[index
]->complete(forDirection
);
240 assert(statusUndo
== kIOReturnSuccess
);
247 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
249 IOReturn
IOMultiMemoryDescriptor::complete(IODirection forDirection
)
252 // Complete processing of the memory after an I/O transfer finishes.
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
260 IOReturn statusFinal
= kIOReturnSuccess
;
262 if ( forDirection
== kIODirectionNone
)
264 forDirection
= _direction
;
267 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
269 status
= _descriptors
[index
]->complete(forDirection
);
270 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
271 assert(status
== kIOReturnSuccess
);
277 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
279 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
281 IOByteCount
* length
)
284 // This method returns the physical address of the byte at the given offset
285 // into the memory, and optionally the length of the physically contiguous
286 // segment from that offset.
289 assert(offset
<= _length
);
291 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
293 if ( offset
< _descriptors
[index
]->getLength() )
295 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
297 offset
-= _descriptors
[index
]->getLength();
300 if ( length
) *length
= 0;
305 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
307 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
309 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
]->getSourceSegment(offset
, length
);
325 offset
-= _descriptors
[index
]->getLength();
328 if ( length
) *length
= 0;
333 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
335 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
336 IOByteCount
* /* length */ )
341 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
343 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
345 IOByteCount withLength
)
348 // Copies data from the memory descriptor's buffer at the given offset, to
349 // the specified buffer. Returns the number of bytes copied.
352 IOByteCount bytesCopied
= 0;
355 for ( index
= 0; index
< _descriptorsCount
; index
++ )
357 if ( offset
< _descriptors
[index
]->getLength() ) break;
358 offset
-= _descriptors
[index
]->getLength();
361 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
363 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
364 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
366 bytesCopied
+= copied
;
367 if ( copied
!= copy
) break;
369 bytes
= ((UInt8
*) bytes
) + copied
;
370 withLength
-= copied
;
377 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
379 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
381 IOByteCount withLength
)
384 // Copies data to the memory descriptor's buffer at the given offset, from
385 // the specified buffer. Returns the number of bytes copied.
388 IOByteCount bytesCopied
= 0;
391 for ( index
= 0; index
< _descriptorsCount
; index
++ )
393 if ( offset
< _descriptors
[index
]->getLength() ) break;
394 offset
-= _descriptors
[index
]->getLength();
397 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
399 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
400 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
402 bytesCopied
+= copied
;
403 if ( copied
!= copy
) break;
405 bytes
= ((UInt8
*) bytes
) + copied
;
406 withLength
-= copied
;