1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <IOKit/IOLib.h>
30 #include <IOKit/IOInterleavedMemoryDescriptor.h>
31
32 #define super IOMemoryDescriptor
33 OSDefineMetaClassAndStructors(IOInterleavedMemoryDescriptor, IOMemoryDescriptor)
34
35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
36
37 bool IOInterleavedMemoryDescriptor::initWithAddress(
38 void * /* address */ ,
39 IOByteCount /* withLength */ ,
40 IODirection /* withDirection */ )
41 {
42 return false;
43 }
44
45 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
46
47 bool IOInterleavedMemoryDescriptor::initWithAddress(
48 vm_address_t /* address */ ,
49 IOByteCount /* withLength */ ,
50 IODirection /* withDirection */ ,
51 task_t /* withTask */ )
52 {
53 return false;
54 }
55
56 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57
58 bool IOInterleavedMemoryDescriptor::initWithPhysicalAddress(
59 IOPhysicalAddress /* address */ ,
60 IOByteCount /* withLength */ ,
61 IODirection /* withDirection */ )
62 {
63 return false;
64 }
65
66
67 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68
69 bool IOInterleavedMemoryDescriptor::initWithPhysicalRanges(
70 IOPhysicalRange * /* ranges */ ,
71 UInt32 /* withCount */ ,
72 IODirection /* withDirection */ ,
73 bool /* asReference */ )
74 {
75 return false;
76 }
77
78 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
79
80 bool IOInterleavedMemoryDescriptor::initWithRanges(
81 IOVirtualRange * /* ranges */ ,
82 UInt32 /* withCount */ ,
83 IODirection /* withDirection */ ,
84 task_t /* withTask */ ,
85 bool /* asReference */ )
86 {
87 return false;
88 }
89
90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
91
92 IOInterleavedMemoryDescriptor * IOInterleavedMemoryDescriptor::withCapacity(
93 UInt32 capacity,
94 IODirection direction )
95 {
96 //
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.
100 //
101
102 IOInterleavedMemoryDescriptor * me = new IOInterleavedMemoryDescriptor;
103
104 if ( me && !me->initWithCapacity(
105 /* capacity */ capacity,
106 /* direction */ direction ))
107 {
108 me->release();
109 me = 0;
110 }
111
112 return me;
113 }
114
115 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116
117 bool IOInterleavedMemoryDescriptor::initWithCapacity(
118 UInt32 capacity,
119 IODirection direction )
120 {
121 //
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.
125 //
126
127 assert(capacity);
128
129 // Ask our superclass' opinion.
130 if ( super::init() == false ) return false;
131
132 // Initialize our minimal state.
133
134 _direction = direction;
135 _length = 0;
136 _mappings = 0;
137 _tag = 0;
138 _descriptorCount = 0;
139 _descriptors = IONew(IOMemoryDescriptor *, capacity);
140 _descriptorOffsets = IONew(IOByteCount, capacity);
141 _descriptorLengths = IONew(IOByteCount, capacity);
142
143 if ( (_descriptors == 0) || (_descriptorOffsets == 0) || (_descriptorLengths == 0) )
144 return false;
145
146 _descriptorCapacity = capacity;
147
148 return true;
149 }
150
151 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
152
153 void IOInterleavedMemoryDescriptor::clearMemoryDescriptors( IODirection direction )
154 {
155 UInt32 index;
156
157 for ( index = 0; index < _descriptorCount; index++ )
158 {
159 if ( _descriptorPrepared )
160 _descriptors[index]->complete(_direction);
161
162 _descriptors[index]->release();
163 _descriptors[index] = 0;
164
165 _descriptorOffsets[index] = 0;
166 _descriptorLengths[index] = 0;
167 }
168
169 if ( direction != kIODirectionNone )
170 _direction = direction;
171
172 _descriptorCount = 0;
173 _length = 0;
174 _mappings = 0;
175 _tag = 0;
176
177 };
178
179 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
180
181 bool IOInterleavedMemoryDescriptor::setMemoryDescriptor(
182 IOMemoryDescriptor * descriptor,
183 IOByteCount offset,
184 IOByteCount length )
185 {
186 if ( _descriptorPrepared || (_descriptorCount == _descriptorCapacity) )
187 return false;
188
189 if ( (offset + length) > descriptor->getLength() )
190 return false;
191
192 // if ( descriptor->getDirection() != _direction )
193 // return false;
194
195 descriptor->retain();
196 _descriptors[_descriptorCount] = descriptor;
197 _descriptorOffsets[_descriptorCount] = offset;
198 _descriptorLengths[_descriptorCount] = length;
199
200 _descriptorCount++;
201
202 _length += length;
203
204 return true;
205 }
206
207 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
208
209 void IOInterleavedMemoryDescriptor::free()
210 {
211 //
212 // Free all of this object's outstanding resources.
213 //
214
215 if ( _descriptors )
216 {
217 for ( unsigned index = 0; index < _descriptorCount; index++ )
218 _descriptors[index]->release();
219
220 if ( _descriptors != 0 )
221 IODelete(_descriptors, IOMemoryDescriptor *, _descriptorCapacity);
222
223 if ( _descriptorOffsets != 0 )
224 IODelete(_descriptorOffsets, IOMemoryDescriptor *, _descriptorCapacity);
225
226 if ( _descriptorLengths != 0 )
227 IODelete(_descriptorLengths, IOMemoryDescriptor *, _descriptorCapacity);
228 }
229
230 super::free();
231 }
232
233 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234
235 IOReturn IOInterleavedMemoryDescriptor::prepare(IODirection forDirection)
236 {
237 //
238 // Prepare the memory for an I/O transfer.
239 //
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.
243 //
244
245 unsigned index;
246 IOReturn status = kIOReturnSuccess;
247 IOReturn statusUndo;
248
249 if ( forDirection == kIODirectionNone )
250 {
251 forDirection = _direction;
252 }
253
254 for ( index = 0; index < _descriptorCount; index++ )
255 {
256 status = _descriptors[index]->prepare(forDirection);
257 if ( status != kIOReturnSuccess ) break;
258 }
259
260 if ( status != kIOReturnSuccess )
261 {
262 for ( unsigned indexUndo = 0; indexUndo < index; indexUndo++ )
263 {
264 statusUndo = _descriptors[index]->complete(forDirection);
265 assert(statusUndo == kIOReturnSuccess);
266 }
267 }
268
269 if ( status == kIOReturnSuccess ) _descriptorPrepared = true;
270
271 return status;
272 }
273
274 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
275
276 IOReturn IOInterleavedMemoryDescriptor::complete(IODirection forDirection)
277 {
278 //
279 // Complete processing of the memory after an I/O transfer finishes.
280 //
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
283 // transfer.
284 //
285
286 IOReturn status;
287 IOReturn statusFinal = kIOReturnSuccess;
288
289 if ( forDirection == kIODirectionNone )
290 {
291 forDirection = _direction;
292 }
293
294 for ( unsigned index = 0; index < _descriptorCount; index++ )
295 {
296 status = _descriptors[index]->complete(forDirection);
297 if ( status != kIOReturnSuccess ) statusFinal = status;
298 assert(status == kIOReturnSuccess);
299 }
300
301 _descriptorPrepared = false;
302
303 return statusFinal;
304 }
305
306 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
307
308 addr64_t IOInterleavedMemoryDescriptor::getPhysicalSegment64(
309 IOByteCount offset, IOByteCount * length )
310 {
311 //
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.
315 //
316
317 addr64_t pa;
318
319 assert(offset <= _length);
320
321 for ( unsigned index = 0; index < _descriptorCount; index++ )
322 {
323 if ( offset < _descriptorLengths[index] )
324 {
325 pa = _descriptors[index]->getPhysicalSegment64(_descriptorOffsets[index] + offset, length);
326 if ((_descriptorLengths[index] - offset) < *length) *length = _descriptorLengths[index] - offset;
327 return pa;
328 }
329 offset -= _descriptorLengths[index];
330 }
331
332 if ( length ) *length = 0;
333
334 return 0;
335 }
336
337 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
338
339 IOPhysicalAddress IOInterleavedMemoryDescriptor::getPhysicalSegment(
340 IOByteCount offset, IOByteCount * length )
341 {
342 //
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.
346 //
347
348 IOPhysicalAddress pa;
349
350 assert(offset <= _length);
351
352 for ( unsigned index = 0; index < _descriptorCount; index++ )
353 {
354 if ( offset < _descriptorLengths[index] )
355 {
356 pa = _descriptors[index]->getPhysicalSegment(_descriptorOffsets[index] + offset, length);
357 if ((_descriptorLengths[index] - offset) < *length) *length = _descriptorLengths[index] - offset;
358 return pa;
359 }
360 offset -= _descriptorLengths[index];
361 }
362
363 if ( length ) *length = 0;
364
365 return 0;
366 }
367
368 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
369
370 IOPhysicalAddress IOInterleavedMemoryDescriptor::getSourceSegment(
371 IOByteCount offset,
372 IOByteCount * length )
373 {
374 //
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.
378 //
379
380 IOPhysicalAddress pa;
381
382 assert(offset <= _length);
383
384 for ( unsigned index = 0; index < _descriptorCount; index++ )
385 {
386 if ( offset < _descriptorLengths[index] )
387 {
388 pa = _descriptors[index]->getSourceSegment(_descriptorOffsets[index] + offset, length);
389 if ((_descriptorLengths[index] - offset) < *length) *length = _descriptorLengths[index] - offset;
390 return pa;
391 }
392 offset -= _descriptorLengths[index];
393 }
394
395 if ( length ) *length = 0;
396
397 return 0;
398 }
399
400 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
401
402 void * IOInterleavedMemoryDescriptor::getVirtualSegment( IOByteCount /* offset */ ,
403 IOByteCount * /* length */ )
404 {
405 return 0;
406 }
Cache object: 881116eb1473cbfa58f7eb06c81d78a4
|