2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <IOKit/IOLib.h>
24 #include <IOKit/IOMultiMemoryDescriptor.h>
26 #define super IOMemoryDescriptor
27 OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor
, IOMemoryDescriptor
)
29 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
31 bool IOMultiMemoryDescriptor::initWithAddress(
32 void * /* address */ ,
33 IOByteCount
/* withLength */ ,
34 IODirection
/* withDirection */ )
39 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
41 bool IOMultiMemoryDescriptor::initWithAddress(
42 vm_address_t
/* address */ ,
43 IOByteCount
/* withLength */ ,
44 IODirection
/* withDirection */ ,
45 task_t
/* withTask */ )
50 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
52 bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
53 IOPhysicalAddress
/* address */ ,
54 IOByteCount
/* withLength */ ,
55 IODirection
/* withDirection */ )
61 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
63 bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
64 IOPhysicalRange
* /* ranges */ ,
65 UInt32
/* withCount */ ,
66 IODirection
/* withDirection */ ,
67 bool /* asReference */ )
72 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
74 bool IOMultiMemoryDescriptor::initWithRanges(
75 IOVirtualRange
* /* ranges */ ,
76 UInt32
/* withCount */ ,
77 IODirection
/* withDirection */ ,
78 task_t
/* withTask */ ,
79 bool /* asReference */ )
84 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
86 IOMultiMemoryDescriptor
* IOMultiMemoryDescriptor::withDescriptors(
87 IOMemoryDescriptor
** descriptors
,
89 IODirection withDirection
,
90 bool asReference
= false )
93 // Create a new IOMultiMemoryDescriptor. The "buffer" is made up of several
94 // memory descriptors, that are to be chained end-to-end to make up a single
97 // Passing the ranges as a reference will avoid an extra allocation.
100 IOMultiMemoryDescriptor
* me
= new IOMultiMemoryDescriptor
;
102 if ( me
&& me
->initWithDescriptors(
103 /* descriptors */ descriptors
,
104 /* withCount */ withCount
,
105 /* withDirection */ withDirection
,
106 /* asReference */ asReference
) == false )
115 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
117 bool IOMultiMemoryDescriptor::initWithDescriptors(
118 IOMemoryDescriptor
** descriptors
,
120 IODirection withDirection
,
121 bool asReference
= false )
124 // Initialize an IOMultiMemoryDescriptor. The "buffer" is made up of several
125 // memory descriptors, that are to be chained end-to-end to make up a single
126 // memory descriptor.
128 // Passing the ranges as a reference will avoid an extra allocation.
134 // Ask our superclass' opinion.
136 if ( super::init() == false ) return false;
138 // Initialize our minimal state.
141 _descriptorsCount
= withCount
;
142 _descriptorsIsAllocated
= asReference
? false : true;
143 _direction
= withDirection
;
150 _descriptors
= descriptors
;
154 _descriptors
= IONew(IOMemoryDescriptor
*, withCount
);
155 if ( _descriptors
== 0 ) return false;
157 bcopy( /* from */ descriptors
,
158 /* to */ _descriptors
,
159 /* bytes */ withCount
* sizeof(IOMemoryDescriptor
*) );
162 for ( unsigned index
= 0; index
< withCount
; index
++ )
164 descriptors
[index
]->retain();
165 _length
+= descriptors
[index
]->getLength();
166 if ( _tag
== 0 ) _tag
= descriptors
[index
]->getTag();
167 assert(descriptors
[index
]->getDirection() == withDirection
);
173 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175 void IOMultiMemoryDescriptor::free()
178 // Free all of this object's outstanding resources.
183 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
184 _descriptors
[index
]->release();
186 if ( _descriptorsIsAllocated
)
187 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
193 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
195 IOReturn
IOMultiMemoryDescriptor::prepare(IODirection forDirection
)
198 // Prepare the memory for an I/O transfer.
200 // This involves paging in the memory and wiring it down for the duration
201 // of the transfer. The complete() method finishes the processing of the
202 // memory after the I/O transfer finishes.
206 IOReturn status
= kIOReturnInternalError
;
209 if ( forDirection
== kIODirectionNone
)
211 forDirection
= _direction
;
214 for ( index
= 0; index
< _descriptorsCount
; index
++ )
216 status
= _descriptors
[index
]->prepare(forDirection
);
217 if ( status
!= kIOReturnSuccess
) break;
220 if ( status
!= kIOReturnSuccess
)
222 for ( unsigned indexUndo
= 0; indexUndo
<= index
; indexUndo
++ )
224 statusUndo
= _descriptors
[index
]->complete(forDirection
);
225 assert(statusUndo
== kIOReturnSuccess
);
232 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234 IOReturn
IOMultiMemoryDescriptor::complete(IODirection forDirection
)
237 // Complete processing of the memory after an I/O transfer finishes.
239 // This method shouldn't be called unless a prepare() was previously issued;
240 // the prepare() and complete() must occur in pairs, before and after an I/O
245 IOReturn statusFinal
= kIOReturnSuccess
;
247 if ( forDirection
== kIODirectionNone
)
249 forDirection
= _direction
;
252 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
254 status
= _descriptors
[index
]->complete(forDirection
);
255 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
256 assert(status
== kIOReturnSuccess
);
262 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
266 IOByteCount
* length
)
269 // This method returns the physical address of the byte at the given offset
270 // into the memory, and optionally the length of the physically contiguous
271 // segment from that offset.
274 assert(offset
<= _length
);
276 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
278 if ( offset
< _descriptors
[index
]->getLength() )
280 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
282 offset
-= _descriptors
[index
]->getLength();
285 if ( length
) *length
= 0;
290 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
292 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
294 IOByteCount
* length
)
297 // This method returns the physical address of the byte at the given offset
298 // into the memory, and optionally the length of the physically contiguous
299 // segment from that offset.
302 assert(offset
<= _length
);
304 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
306 if ( offset
< _descriptors
[index
]->getLength() )
308 return _descriptors
[index
]->getSourceSegment(offset
, length
);
310 offset
-= _descriptors
[index
]->getLength();
313 if ( length
) *length
= 0;
318 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
320 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
321 IOByteCount
* /* length */ )
326 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
328 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
330 IOByteCount withLength
)
333 // Copies data from the memory descriptor's buffer at the given offset, to
334 // the specified buffer. Returns the number of bytes copied.
337 IOByteCount bytesCopied
= 0;
340 for ( index
= 0; index
< _descriptorsCount
; index
++ )
342 if ( offset
< _descriptors
[index
]->getLength() ) break;
343 offset
-= _descriptors
[index
]->getLength();
346 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
348 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
349 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
351 bytesCopied
+= copied
;
352 if ( copied
!= copy
) break;
354 bytes
= ((UInt8
*) bytes
) + copied
;
355 withLength
-= copied
;
362 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
364 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
366 IOByteCount withLength
)
369 // Copies data to the memory descriptor's buffer at the given offset, from
370 // the specified buffer. Returns the number of bytes copied.
373 IOByteCount bytesCopied
= 0;
376 for ( index
= 0; index
< _descriptorsCount
; index
++ )
378 if ( offset
< _descriptors
[index
]->getLength() ) break;
379 offset
-= _descriptors
[index
]->getLength();
382 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
384 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
385 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
387 bytesCopied
+= copied
;
388 if ( copied
!= copy
) break;
390 bytes
= ((UInt8
*) bytes
) + copied
;
391 withLength
-= copied
;