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 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
283 IOByteCount
* length
)
286 // This method returns the physical address of the byte at the given offset
287 // into the memory, and optionally the length of the physically contiguous
288 // segment from that offset.
291 assert(offset
<= _length
);
293 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
295 if ( offset
< _descriptors
[index
]->getLength() )
297 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
299 offset
-= _descriptors
[index
]->getLength();
302 if ( length
) *length
= 0;
307 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
309 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
311 IOByteCount
* length
)
314 // This method returns the physical address of the byte at the given offset
315 // into the memory, and optionally the length of the physically contiguous
316 // segment from that offset.
319 assert(offset
<= _length
);
321 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
323 if ( offset
< _descriptors
[index
]->getLength() )
325 return _descriptors
[index
]->getSourceSegment(offset
, length
);
327 offset
-= _descriptors
[index
]->getLength();
330 if ( length
) *length
= 0;
335 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
337 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
338 IOByteCount
* /* length */ )
343 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
345 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
347 IOByteCount withLength
)
350 // Copies data from the memory descriptor's buffer at the given offset, to
351 // the specified buffer. Returns the number of bytes copied.
354 IOByteCount bytesCopied
= 0;
357 for ( index
= 0; index
< _descriptorsCount
; index
++ )
359 if ( offset
< _descriptors
[index
]->getLength() ) break;
360 offset
-= _descriptors
[index
]->getLength();
363 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
365 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
366 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
368 bytesCopied
+= copied
;
369 if ( copied
!= copy
) break;
371 bytes
= ((UInt8
*) bytes
) + copied
;
372 withLength
-= copied
;
379 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
381 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
383 IOByteCount withLength
)
386 // Copies data to the memory descriptor's buffer at the given offset, from
387 // the specified buffer. Returns the number of bytes copied.
390 IOByteCount bytesCopied
= 0;
393 for ( index
= 0; index
< _descriptorsCount
; index
++ )
395 if ( offset
< _descriptors
[index
]->getLength() ) break;
396 offset
-= _descriptors
[index
]->getLength();
399 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
401 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
402 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
404 bytesCopied
+= copied
;
405 if ( copied
!= copy
) break;
407 bytes
= ((UInt8
*) bytes
) + copied
;
408 withLength
-= copied
;