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
,
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
,
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 // Release existing descriptors, if any
137 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
138 _descriptors
[index
]->release();
140 if ( _descriptorsIsAllocated
)
141 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
143 // Ask our superclass' opinion.
144 if ( super::init() == false ) return false;
147 // Initialize our minimal state.
150 _descriptorsCount
= withCount
;
151 _descriptorsIsAllocated
= asReference
? false : true;
152 _direction
= withDirection
;
159 _descriptors
= descriptors
;
163 _descriptors
= IONew(IOMemoryDescriptor
*, withCount
);
164 if ( _descriptors
== 0 ) return false;
166 bcopy( /* from */ descriptors
,
167 /* to */ _descriptors
,
168 /* bytes */ withCount
* sizeof(IOMemoryDescriptor
*) );
171 for ( unsigned index
= 0; index
< withCount
; index
++ )
173 descriptors
[index
]->retain();
174 _length
+= descriptors
[index
]->getLength();
175 if ( _tag
== 0 ) _tag
= descriptors
[index
]->getTag();
176 assert(descriptors
[index
]->getDirection() == withDirection
);
182 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
184 void IOMultiMemoryDescriptor::free()
187 // Free all of this object's outstanding resources.
192 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
193 _descriptors
[index
]->release();
195 if ( _descriptorsIsAllocated
)
196 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorsCount
);
202 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
204 IOReturn
IOMultiMemoryDescriptor::prepare(IODirection forDirection
)
207 // Prepare the memory for an I/O transfer.
209 // This involves paging in the memory and wiring it down for the duration
210 // of the transfer. The complete() method finishes the processing of the
211 // memory after the I/O transfer finishes.
215 IOReturn status
= kIOReturnInternalError
;
218 if ( forDirection
== kIODirectionNone
)
220 forDirection
= _direction
;
223 for ( index
= 0; index
< _descriptorsCount
; index
++ )
225 status
= _descriptors
[index
]->prepare(forDirection
);
226 if ( status
!= kIOReturnSuccess
) break;
229 if ( status
!= kIOReturnSuccess
)
231 for ( unsigned indexUndo
= 0; indexUndo
<= index
; indexUndo
++ )
233 statusUndo
= _descriptors
[index
]->complete(forDirection
);
234 assert(statusUndo
== kIOReturnSuccess
);
241 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
243 IOReturn
IOMultiMemoryDescriptor::complete(IODirection forDirection
)
246 // Complete processing of the memory after an I/O transfer finishes.
248 // This method shouldn't be called unless a prepare() was previously issued;
249 // the prepare() and complete() must occur in pairs, before and after an I/O
254 IOReturn statusFinal
= kIOReturnSuccess
;
256 if ( forDirection
== kIODirectionNone
)
258 forDirection
= _direction
;
261 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
263 status
= _descriptors
[index
]->complete(forDirection
);
264 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
265 assert(status
== kIOReturnSuccess
);
271 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
273 addr64_t
IOMultiMemoryDescriptor::getPhysicalSegment64(
274 IOByteCount offset
, IOByteCount
* length
)
277 // This method returns the physical address of the byte at the given offset
278 // into the memory, and optionally the length of the physically contiguous
279 // segment from that offset.
282 assert(offset
<= _length
);
284 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
286 if ( offset
< _descriptors
[index
]->getLength() )
288 return _descriptors
[index
]->getPhysicalSegment64(offset
, length
);
290 offset
-= _descriptors
[index
]->getLength();
293 if ( length
) *length
= 0;
298 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
300 IOPhysicalAddress
IOMultiMemoryDescriptor::getPhysicalSegment(
301 IOByteCount offset
, IOByteCount
* length
)
304 // This method returns the physical address of the byte at the given offset
305 // into the memory, and optionally the length of the physically contiguous
306 // segment from that offset.
309 assert(offset
<= _length
);
311 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
313 if ( offset
< _descriptors
[index
]->getLength() )
315 return _descriptors
[index
]->getPhysicalSegment(offset
, length
);
317 offset
-= _descriptors
[index
]->getLength();
320 if ( length
) *length
= 0;
325 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
327 IOPhysicalAddress
IOMultiMemoryDescriptor::getSourceSegment(
329 IOByteCount
* length
)
332 // This method returns the physical address of the byte at the given offset
333 // into the memory, and optionally the length of the physically contiguous
334 // segment from that offset.
337 assert(offset
<= _length
);
339 for ( unsigned index
= 0; index
< _descriptorsCount
; index
++ )
341 if ( offset
< _descriptors
[index
]->getLength() )
343 return _descriptors
[index
]->getSourceSegment(offset
, length
);
345 offset
-= _descriptors
[index
]->getLength();
348 if ( length
) *length
= 0;
353 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
355 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
356 IOByteCount
* /* length */ )
361 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
363 IOByteCount
IOMultiMemoryDescriptor::readBytes( IOByteCount offset
,
365 IOByteCount withLength
)
368 // Copies data from the memory descriptor's buffer at the given offset, to
369 // the specified buffer. Returns the number of bytes copied.
372 IOByteCount bytesCopied
= 0;
375 for ( index
= 0; index
< _descriptorsCount
; index
++ )
377 if ( offset
< _descriptors
[index
]->getLength() ) break;
378 offset
-= _descriptors
[index
]->getLength();
381 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
383 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
384 IOByteCount copied
= _descriptors
[index
]->readBytes(offset
,bytes
,copy
);
386 bytesCopied
+= copied
;
387 if ( copied
!= copy
) break;
389 bytes
= ((UInt8
*) bytes
) + copied
;
390 withLength
-= copied
;
397 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
399 IOByteCount
IOMultiMemoryDescriptor::writeBytes( IOByteCount offset
,
401 IOByteCount withLength
)
404 // Copies data to the memory descriptor's buffer at the given offset, from
405 // the specified buffer. Returns the number of bytes copied.
408 IOByteCount bytesCopied
= 0;
411 for ( index
= 0; index
< _descriptorsCount
; index
++ )
413 if ( offset
< _descriptors
[index
]->getLength() ) break;
414 offset
-= _descriptors
[index
]->getLength();
417 for ( ; index
< _descriptorsCount
&& withLength
; index
++)
419 IOByteCount copy
= min(_descriptors
[index
]->getLength(), withLength
);
420 IOByteCount copied
= _descriptors
[index
]->writeBytes(offset
,bytes
,copy
);
422 bytesCopied
+= copied
;
423 if ( copied
!= copy
) break;
425 bytes
= ((UInt8
*) bytes
) + copied
;
426 withLength
-= copied
;