2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include <IOKit/IOLib.h>
27 #include <IOKit/IOMultiMemoryDescriptor.h>
29 #define super IOMemoryDescriptor
30 OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor
, IOMemoryDescriptor
)
32 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34 bool IOMultiMemoryDescriptor::initWithAddress(
35 void * /* address */ ,
36 IOByteCount
/* withLength */ ,
37 IODirection
/* withDirection */ )
42 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44 bool IOMultiMemoryDescriptor::initWithAddress(
45 vm_address_t
/* address */ ,
46 IOByteCount
/* withLength */ ,
47 IODirection
/* withDirection */ ,
48 task_t
/* withTask */ )
53 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
55 bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
56 IOPhysicalAddress
/* address */ ,
57 IOByteCount
/* withLength */ ,
58 IODirection
/* withDirection */ )
64 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
66 bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
67 IOPhysicalRange
* /* ranges */ ,
68 UInt32
/* withCount */ ,
69 IODirection
/* withDirection */ ,
70 bool /* asReference */ )
75 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
77 bool IOMultiMemoryDescriptor::initWithRanges(
78 IOVirtualRange
* /* ranges */ ,
79 UInt32
/* withCount */ ,
80 IODirection
/* withDirection */ ,
81 task_t
/* withTask */ ,
82 bool /* asReference */ )
87 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89 IOMultiMemoryDescriptor
* IOMultiMemoryDescriptor::withDescriptors(
90 IOMemoryDescriptor
** descriptors
,
92 IODirection withDirection
,
96 // Create a new IOMultiMemoryDescriptor. The "buffer" is made up of several
97 // memory descriptors, that are to be chained end-to-end to make up a single
100 // Passing the ranges as a reference will avoid an extra allocation.
103 IOMultiMemoryDescriptor
* me
= new IOMultiMemoryDescriptor
;
105 if ( me
&& me
->initWithDescriptors(
106 /* descriptors */ descriptors
,
107 /* withCount */ withCount
,
108 /* withDirection */ withDirection
,
109 /* asReference */ asReference
) == false )
118 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
120 bool IOMultiMemoryDescriptor::initWithDescriptors(
121 IOMemoryDescriptor
** descriptors
,
123 IODirection withDirection
,
127 // Initialize an IOMultiMemoryDescriptor. The "buffer" is made up of several
128 // memory descriptors, that are to be chained end-to-end to make up a single
129 // memory descriptor.
131 // Passing the ranges as a reference will avoid an extra allocation.
137 // Release existing descriptors, if any
140 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
141 _descriptors
[index
]->release();
143 if ( _descriptorsIsAllocated
)
144 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
146 // Ask our superclass' opinion.
147 if ( super::init() == false ) return false;
150 // Initialize our minimal state.
153 _descriptorsCount
= withCount
;
154 _descriptorsIsAllocated
= asReference
? false : true;
155 _direction
= withDirection
;
162 _descriptors
= descriptors
;
166 _descriptors
= IONew(IOMemoryDescriptor
*, withCount
);
167 if ( _descriptors
== 0 ) return false;
169 bcopy( /* from */ descriptors
,
170 /* to */ _descriptors
,
171 /* bytes */ withCount
* sizeof(IOMemoryDescriptor
*) );
174 for ( unsigned index
= 0; index
< withCount
; index
++ )
176 descriptors
[index
]->retain();
177 _length
+= descriptors
[index
]->getLength();
178 if ( _tag
== 0 ) _tag
= descriptors
[index
]->getTag();
179 assert(descriptors
[index
]->getDirection() == withDirection
);
185 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187 void IOMultiMemoryDescriptor::free()
190 // Free all of this object's outstanding resources.
195 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
196 _descriptors
[index
]->release();
198 if ( _descriptorsIsAllocated
)
199 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
205 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
207 IOReturn
IOMultiMemoryDescriptor::prepare(IODirection forDirection
)
210 // Prepare the memory for an I/O transfer.
212 // This involves paging in the memory and wiring it down for the duration
213 // of the transfer. The complete() method finishes the processing of the
214 // memory after the I/O transfer finishes.
218 IOReturn status
= kIOReturnInternalError
;
221 if ( forDirection
== kIODirectionNone
)
223 forDirection
= _direction
;
226 for ( index
= 0; index
< _descriptorsCount
; index
++ )
228 status
= _descriptors
[index
]->prepare(forDirection
);
229 if ( status
!= kIOReturnSuccess
) break;
232 if ( status
!= kIOReturnSuccess
)
234 for ( unsigned indexUndo
= 0; indexUndo
<= index
; indexUndo
++ )
236 statusUndo
= _descriptors
[index
]->complete(forDirection
);
237 assert(statusUndo
== kIOReturnSuccess
);
244 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
246 IOReturn
IOMultiMemoryDescriptor::complete(IODirection forDirection
)
249 // Complete processing of the memory after an I/O transfer finishes.
251 // This method shouldn't be called unless a prepare() was previously issued;
252 // the prepare() and complete() must occur in pairs, before and after an I/O
257 IOReturn statusFinal
= kIOReturnSuccess
;
259 if ( forDirection
== kIODirectionNone
)
261 forDirection
= _direction
;
264 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
266 status
= _descriptors
[index
]->complete(forDirection
);
267 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
268 assert(status
== kIOReturnSuccess
);
274 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
278 IOByteCount
* length
)
281 // This method returns the physical address of the byte at the given offset
282 // into the memory, and optionally the length of the physically contiguous
283 // segment from that offset.
286 assert(offset
<= _length
);
288 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
290 if ( offset
< _descriptors
[index
]->getLength() )
292 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
294 offset
-= _descriptors
[index
]->getLength();
297 if ( length
) *length
= 0;
302 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
304 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
306 IOByteCount
* length
)
309 // This method returns the physical address of the byte at the given offset
310 // into the memory, and optionally the length of the physically contiguous
311 // segment from that offset.
314 assert(offset
<= _length
);
316 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
318 if ( offset
< _descriptors
[index
]->getLength() )
320 return _descriptors
[index
]->getSourceSegment(offset
, length
);
322 offset
-= _descriptors
[index
]->getLength();
325 if ( length
) *length
= 0;
330 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
332 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
333 IOByteCount
* /* length */ )
338 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
340 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
342 IOByteCount withLength
)
345 // Copies data from the memory descriptor's buffer at the given offset, to
346 // the specified buffer. Returns the number of bytes copied.
349 IOByteCount bytesCopied
= 0;
352 for ( index
= 0; index
< _descriptorsCount
; index
++ )
354 if ( offset
< _descriptors
[index
]->getLength() ) break;
355 offset
-= _descriptors
[index
]->getLength();
358 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
360 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
361 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
363 bytesCopied
+= copied
;
364 if ( copied
!= copy
) break;
366 bytes
= ((UInt8
*) bytes
) + copied
;
367 withLength
-= copied
;
374 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
376 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
378 IOByteCount withLength
)
381 // Copies data to the memory descriptor's buffer at the given offset, from
382 // the specified buffer. Returns the number of bytes copied.
385 IOByteCount bytesCopied
= 0;
388 for ( index
= 0; index
< _descriptorsCount
; index
++ )
390 if ( offset
< _descriptors
[index
]->getLength() ) break;
391 offset
-= _descriptors
[index
]->getLength();
394 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
396 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
397 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
399 bytesCopied
+= copied
;
400 if ( copied
!= copy
) break;
402 bytes
= ((UInt8
*) bytes
) + copied
;
403 withLength
-= copied
;