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
,
93 bool asReference
= false )
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
,
124 bool asReference
= false )
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 // Ask our superclass' opinion.
139 if ( super::init() == false ) return false;
141 // Initialize our minimal state.
144 _descriptorsCount
= withCount
;
145 _descriptorsIsAllocated
= asReference
? false : true;
146 _direction
= withDirection
;
153 _descriptors
= descriptors
;
157 _descriptors
= IONew(IOMemoryDescriptor
*, withCount
);
158 if ( _descriptors
== 0 ) return false;
160 bcopy( /* from */ descriptors
,
161 /* to */ _descriptors
,
162 /* bytes */ withCount
* sizeof(IOMemoryDescriptor
*) );
165 for ( unsigned index
= 0; index
< withCount
; index
++ )
167 descriptors
[index
]->retain();
168 _length
+= descriptors
[index
]->getLength();
169 if ( _tag
== 0 ) _tag
= descriptors
[index
]->getTag();
170 assert(descriptors
[index
]->getDirection() == withDirection
);
176 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
178 void IOMultiMemoryDescriptor::free()
181 // Free all of this object's outstanding resources.
186 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
187 _descriptors
[index
]->release();
189 if ( _descriptorsIsAllocated
)
190 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
196 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
198 IOReturn
IOMultiMemoryDescriptor::prepare(IODirection forDirection
)
201 // Prepare the memory for an I/O transfer.
203 // This involves paging in the memory and wiring it down for the duration
204 // of the transfer. The complete() method finishes the processing of the
205 // memory after the I/O transfer finishes.
209 IOReturn status
= kIOReturnInternalError
;
212 if ( forDirection
== kIODirectionNone
)
214 forDirection
= _direction
;
217 for ( index
= 0; index
< _descriptorsCount
; index
++ )
219 status
= _descriptors
[index
]->prepare(forDirection
);
220 if ( status
!= kIOReturnSuccess
) break;
223 if ( status
!= kIOReturnSuccess
)
225 for ( unsigned indexUndo
= 0; indexUndo
<= index
; indexUndo
++ )
227 statusUndo
= _descriptors
[index
]->complete(forDirection
);
228 assert(statusUndo
== kIOReturnSuccess
);
235 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
237 IOReturn
IOMultiMemoryDescriptor::complete(IODirection forDirection
)
240 // Complete processing of the memory after an I/O transfer finishes.
242 // This method shouldn't be called unless a prepare() was previously issued;
243 // the prepare() and complete() must occur in pairs, before and after an I/O
248 IOReturn statusFinal
= kIOReturnSuccess
;
250 if ( forDirection
== kIODirectionNone
)
252 forDirection
= _direction
;
255 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
257 status
= _descriptors
[index
]->complete(forDirection
);
258 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
259 assert(status
== kIOReturnSuccess
);
265 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
267 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
269 IOByteCount
* length
)
272 // This method returns the physical address of the byte at the given offset
273 // into the memory, and optionally the length of the physically contiguous
274 // segment from that offset.
277 assert(offset
<= _length
);
279 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
281 if ( offset
< _descriptors
[index
]->getLength() )
283 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
285 offset
-= _descriptors
[index
]->getLength();
288 if ( length
) *length
= 0;
293 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
295 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
297 IOByteCount
* length
)
300 // This method returns the physical address of the byte at the given offset
301 // into the memory, and optionally the length of the physically contiguous
302 // segment from that offset.
305 assert(offset
<= _length
);
307 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
309 if ( offset
< _descriptors
[index
]->getLength() )
311 return _descriptors
[index
]->getSourceSegment(offset
, length
);
313 offset
-= _descriptors
[index
]->getLength();
316 if ( length
) *length
= 0;
321 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
323 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
324 IOByteCount
* /* length */ )
329 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
331 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
333 IOByteCount withLength
)
336 // Copies data from the memory descriptor's buffer at the given offset, to
337 // the specified buffer. Returns the number of bytes copied.
340 IOByteCount bytesCopied
= 0;
343 for ( index
= 0; index
< _descriptorsCount
; index
++ )
345 if ( offset
< _descriptors
[index
]->getLength() ) break;
346 offset
-= _descriptors
[index
]->getLength();
349 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
351 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
352 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
354 bytesCopied
+= copied
;
355 if ( copied
!= copy
) break;
357 bytes
= ((UInt8
*) bytes
) + copied
;
358 withLength
-= copied
;
365 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
367 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
369 IOByteCount withLength
)
372 // Copies data to the memory descriptor's buffer at the given offset, from
373 // the specified buffer. Returns the number of bytes copied.
376 IOByteCount bytesCopied
= 0;
379 for ( index
= 0; index
< _descriptorsCount
; index
++ )
381 if ( offset
< _descriptors
[index
]->getLength() ) break;
382 offset
-= _descriptors
[index
]->getLength();
385 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
387 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
388 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
390 bytesCopied
+= copied
;
391 if ( copied
!= copy
) break;
393 bytes
= ((UInt8
*) bytes
) + copied
;
394 withLength
-= copied
;