2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IOLib.h>
30 #include <IOKit/IOInterleavedMemoryDescriptor.h>
32 #define super IOMemoryDescriptor
33 OSDefineMetaClassAndStructors(IOInterleavedMemoryDescriptor
, IOMemoryDescriptor
)
35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
37 bool IOInterleavedMemoryDescriptor::initWithAddress(
38 void * /* address */ ,
39 IOByteCount
/* withLength */ ,
40 IODirection
/* withDirection */ )
45 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47 bool IOInterleavedMemoryDescriptor::initWithAddress(
48 vm_address_t
/* address */ ,
49 IOByteCount
/* withLength */ ,
50 IODirection
/* withDirection */ ,
51 task_t
/* withTask */ )
56 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58 bool IOInterleavedMemoryDescriptor::initWithPhysicalAddress(
59 IOPhysicalAddress
/* address */ ,
60 IOByteCount
/* withLength */ ,
61 IODirection
/* withDirection */ )
67 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69 bool IOInterleavedMemoryDescriptor::initWithPhysicalRanges(
70 IOPhysicalRange
* /* ranges */ ,
71 UInt32
/* withCount */ ,
72 IODirection
/* withDirection */ ,
73 bool /* asReference */ )
78 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
80 bool IOInterleavedMemoryDescriptor::initWithRanges(
81 IOVirtualRange
* /* ranges */ ,
82 UInt32
/* withCount */ ,
83 IODirection
/* withDirection */ ,
84 task_t
/* withTask */ ,
85 bool /* asReference */ )
90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92 IOInterleavedMemoryDescriptor
* IOInterleavedMemoryDescriptor::withCapacity(
94 IODirection direction
)
97 // Create a new IOInterleavedMemoryDescriptor. The "buffer" will be made up
98 // of several memory descriptors, that are to be chained end-to-end to make up
99 // a single memory descriptor.
102 IOInterleavedMemoryDescriptor
* me
= new IOInterleavedMemoryDescriptor
;
104 if ( me
&& !me
->initWithCapacity(
105 /* capacity */ capacity
,
106 /* direction */ direction
))
115 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
117 bool IOInterleavedMemoryDescriptor::initWithCapacity(
119 IODirection direction
)
122 // Initialize an IOInterleavedMemoryDescriptor. The "buffer" will be made up
123 // of several memory descriptors, that are to be chained end-to-end to make up
124 // a single memory descriptor.
129 // Ask our superclass' opinion.
130 if ( super::init() == false ) return false;
132 // Initialize our minimal state.
134 _direction
= direction
;
138 _descriptorCount
= 0;
139 _descriptors
= IONew(IOMemoryDescriptor
*, capacity
);
140 _descriptorOffsets
= IONew(IOByteCount
, capacity
);
141 _descriptorLengths
= IONew(IOByteCount
, capacity
);
143 if ( (_descriptors
== 0) || (_descriptorOffsets
== 0) || (_descriptorLengths
== 0) )
146 _descriptorCapacity
= capacity
;
151 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153 void IOInterleavedMemoryDescriptor::clearMemoryDescriptors( IODirection direction
)
157 for ( index
= 0; index
< _descriptorCount
; index
++ )
159 if ( _descriptorPrepared
)
160 _descriptors
[index
]->complete(_direction
);
162 _descriptors
[index
]->release();
163 _descriptors
[index
] = 0;
165 _descriptorOffsets
[index
] = 0;
166 _descriptorLengths
[index
] = 0;
169 if ( direction
!= kIODirectionNone
)
170 _direction
= direction
;
172 _descriptorCount
= 0;
179 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
181 bool IOInterleavedMemoryDescriptor::setMemoryDescriptor(
182 IOMemoryDescriptor
* descriptor
,
186 if ( _descriptorPrepared
|| (_descriptorCount
== _descriptorCapacity
) )
189 if ( (offset
+ length
) > descriptor
->getLength() )
192 // if ( descriptor->getDirection() != _direction )
195 descriptor
->retain();
196 _descriptors
[_descriptorCount
] = descriptor
;
197 _descriptorOffsets
[_descriptorCount
] = offset
;
198 _descriptorLengths
[_descriptorCount
] = length
;
207 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
209 void IOInterleavedMemoryDescriptor::free()
212 // Free all of this object's outstanding resources.
217 for ( unsigned index
= 0; index
< _descriptorCount
; index
++ )
218 _descriptors
[index
]->release();
220 if ( _descriptors
!= 0 )
221 IODelete(_descriptors
, IOMemoryDescriptor
*, _descriptorCapacity
);
223 if ( _descriptorOffsets
!= 0 )
224 IODelete(_descriptorOffsets
, IOMemoryDescriptor
*, _descriptorCapacity
);
226 if ( _descriptorLengths
!= 0 )
227 IODelete(_descriptorLengths
, IOMemoryDescriptor
*, _descriptorCapacity
);
233 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
235 IOReturn
IOInterleavedMemoryDescriptor::prepare(IODirection forDirection
)
238 // Prepare the memory for an I/O transfer.
240 // This involves paging in the memory and wiring it down for the duration
241 // of the transfer. The complete() method finishes the processing of the
242 // memory after the I/O transfer finishes.
246 IOReturn status
= kIOReturnSuccess
;
249 if ( forDirection
== kIODirectionNone
)
251 forDirection
= _direction
;
254 for ( index
= 0; index
< _descriptorCount
; index
++ )
256 status
= _descriptors
[index
]->prepare(forDirection
);
257 if ( status
!= kIOReturnSuccess
) break;
260 if ( status
!= kIOReturnSuccess
)
262 for ( unsigned indexUndo
= 0; indexUndo
< index
; indexUndo
++ )
264 statusUndo
= _descriptors
[index
]->complete(forDirection
);
265 assert(statusUndo
== kIOReturnSuccess
);
269 if ( status
== kIOReturnSuccess
) _descriptorPrepared
= true;
274 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276 IOReturn
IOInterleavedMemoryDescriptor::complete(IODirection forDirection
)
279 // Complete processing of the memory after an I/O transfer finishes.
281 // This method shouldn't be called unless a prepare() was previously issued;
282 // the prepare() and complete() must occur in pairs, before and after an I/O
287 IOReturn statusFinal
= kIOReturnSuccess
;
289 if ( forDirection
== kIODirectionNone
)
291 forDirection
= _direction
;
294 for ( unsigned index
= 0; index
< _descriptorCount
; index
++ )
296 status
= _descriptors
[index
]->complete(forDirection
);
297 if ( status
!= kIOReturnSuccess
) statusFinal
= status
;
298 assert(status
== kIOReturnSuccess
);
301 _descriptorPrepared
= false;
306 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
308 addr64_t
IOInterleavedMemoryDescriptor::getPhysicalSegment64(
309 IOByteCount offset
, IOByteCount
* length
)
312 // This method returns the physical address of the byte at the given offset
313 // into the memory, and optionally the length of the physically contiguous
314 // segment from that offset.
319 assert(offset
<= _length
);
321 for ( unsigned index
= 0; index
< _descriptorCount
; index
++ )
323 if ( offset
< _descriptorLengths
[index
] )
325 pa
= _descriptors
[index
]->getPhysicalSegment64(_descriptorOffsets
[index
] + offset
, length
);
326 if ((_descriptorLengths
[index
] - offset
) < *length
) *length
= _descriptorLengths
[index
] - offset
;
329 offset
-= _descriptorLengths
[index
];
332 if ( length
) *length
= 0;
337 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
339 IOPhysicalAddress
IOInterleavedMemoryDescriptor::getPhysicalSegment(
340 IOByteCount offset
, IOByteCount
* length
)
343 // This method returns the physical address of the byte at the given offset
344 // into the memory, and optionally the length of the physically contiguous
345 // segment from that offset.
348 IOPhysicalAddress pa
;
350 assert(offset
<= _length
);
352 for ( unsigned index
= 0; index
< _descriptorCount
; index
++ )
354 if ( offset
< _descriptorLengths
[index
] )
356 pa
= _descriptors
[index
]->getPhysicalSegment(_descriptorOffsets
[index
] + offset
, length
);
357 if ((_descriptorLengths
[index
] - offset
) < *length
) *length
= _descriptorLengths
[index
] - offset
;
360 offset
-= _descriptorLengths
[index
];
363 if ( length
) *length
= 0;
368 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
370 IOPhysicalAddress
IOInterleavedMemoryDescriptor::getSourceSegment(
372 IOByteCount
* length
)
375 // This method returns the physical address of the byte at the given offset
376 // into the memory, and optionally the length of the physically contiguous
377 // segment from that offset.
380 IOPhysicalAddress pa
;
382 assert(offset
<= _length
);
384 for ( unsigned index
= 0; index
< _descriptorCount
; index
++ )
386 if ( offset
< _descriptorLengths
[index
] )
388 pa
= _descriptors
[index
]->getSourceSegment(_descriptorOffsets
[index
] + offset
, length
);
389 if ((_descriptorLengths
[index
] - offset
) < *length
) *length
= _descriptorLengths
[index
] - offset
;
392 offset
-= _descriptorLengths
[index
];
395 if ( length
) *length
= 0;
400 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
402 void * IOInterleavedMemoryDescriptor::getVirtualSegment( IOByteCount
/* offset */ ,
403 IOByteCount
* /* length */ )