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@
25 /* IOMemoryCursor.cpp created by wgulland on 1999-3-02 */
27 #include <IOKit/assert.h>
28 #include <IOKit/IOLib.h>
29 #include <IOKit/IOMemoryCursor.h>
30 #include <IOKit/IOMemoryDescriptor.h>
31 #include <libkern/OSByteOrder.h>
33 /**************************** class IOMemoryCursor ***************************/
36 #define super OSObject
37 OSDefineMetaClassAndStructors(IOMemoryCursor
, OSObject
)
40 IOMemoryCursor::withSpecification(SegmentFunction inSegFunc
,
41 IOPhysicalLength inMaxSegmentSize
,
42 IOPhysicalLength inMaxTransferSize
,
43 IOPhysicalLength inAlignment
)
45 IOMemoryCursor
* me
= new IOMemoryCursor
;
47 if (me
&& !me
->initWithSpecification(inSegFunc
,
59 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62 IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc
,
63 IOPhysicalLength inMaxSegmentSize
,
64 IOPhysicalLength inMaxTransferSize
,
65 IOPhysicalLength inAlignment
)
67 // @@@ gvdl: Remove me
69 static UInt sMaxDBDMASegment
;
70 if (!sMaxDBDMASegment
) {
71 sMaxDBDMASegment
= (UInt
) -1;
72 if (PE_parse_boot_arg("mseg", &sMaxDBDMASegment
))
73 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment
);
76 if (inMaxSegmentSize
> sMaxDBDMASegment
) inMaxSegmentSize
= sMaxDBDMASegment
;
86 maxSegmentSize
= inMaxSegmentSize
;
87 if (inMaxTransferSize
)
88 maxTransferSize
= inMaxTransferSize
;
90 maxTransferSize
= (IOPhysicalLength
) -1;
91 alignMask
= inAlignment
- 1;
92 assert(alignMask
== 0); // No alignment code yet!
97 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
100 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor
*inDescriptor
,
101 IOPhysicalLength fromPosition
,
103 UInt32 inMaxSegments
,
104 UInt32 inMaxTransferSize
,
105 IOByteCount
*outTransferSize
)
113 if (!inMaxTransferSize
)
114 inMaxTransferSize
= maxTransferSize
;
117 * Iterate over the packet, translating segments where allowed
119 * If we finished cleanly return number of segments found
120 * and update the position in the descriptor.
122 PhysicalSegment curSeg
= { 0 };
123 UInt curSegIndex
= 0;
124 UInt curTransferSize
= 0;
125 IOByteCount inDescriptorLength
= inDescriptor
->getLength();
126 PhysicalSegment seg
= { 0 };
128 while ((seg
.location
) || (fromPosition
< inDescriptorLength
))
132 seg
.location
= inDescriptor
->getPhysicalSegment(
133 fromPosition
, &seg
.length
);
134 assert(seg
.location
);
136 fromPosition
+= seg
.length
;
139 if (!curSeg
.location
)
141 curTransferSize
+= seg
.length
;
145 else if ((curSeg
.location
+ curSeg
.length
== seg
.location
))
147 curTransferSize
+= seg
.length
;
148 curSeg
.length
+= seg
.length
;
154 if ((curSeg
.length
> maxSegmentSize
))
156 seg
.location
= curSeg
.location
+ maxSegmentSize
;
157 seg
.length
= curSeg
.length
- maxSegmentSize
;
158 curTransferSize
-= seg
.length
;
159 curSeg
.length
-= seg
.length
;
162 if ((curTransferSize
>= inMaxTransferSize
))
164 curSeg
.length
-= curTransferSize
- inMaxTransferSize
;
165 curTransferSize
= inMaxTransferSize
;
172 if ((curSegIndex
+ 1 == inMaxSegments
))
174 (*outSeg
)(curSeg
, inSegments
, curSegIndex
++);
180 (*outSeg
)(curSeg
, inSegments
, curSegIndex
++);
183 *outTransferSize
= curTransferSize
;
188 /************************ class IONaturalMemoryCursor ************************/
191 #define super IOMemoryCursor
192 OSDefineMetaClassAndStructors(IONaturalMemoryCursor
, IOMemoryCursor
)
194 void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment
,
196 UInt32 outSegmentIndex
)
198 ((PhysicalSegment
*) outSegments
)[outSegmentIndex
] = segment
;
201 IONaturalMemoryCursor
*
202 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
203 IOPhysicalLength inMaxTransferSize
,
204 IOPhysicalLength inAlignment
)
206 IONaturalMemoryCursor
*me
= new IONaturalMemoryCursor
;
208 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
220 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
221 IOPhysicalLength inMaxTransferSize
,
222 IOPhysicalLength inAlignment
)
224 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment
,
230 /************************** class IOBigMemoryCursor **************************/
233 #define super IOMemoryCursor
234 OSDefineMetaClassAndStructors(IOBigMemoryCursor
, IOMemoryCursor
)
237 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment
,
239 UInt32 inSegmentIndex
)
241 IOPhysicalAddress
* segment
;
243 segment
= &((PhysicalSegment
*) inSegments
)[inSegmentIndex
].location
;
244 OSWriteBigInt(segment
, 0, inSegment
.location
);
245 OSWriteBigInt(segment
, sizeof(IOPhysicalAddress
), inSegment
.length
);
249 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
250 IOPhysicalLength inMaxTransferSize
,
251 IOPhysicalLength inAlignment
)
253 IOBigMemoryCursor
* me
= new IOBigMemoryCursor
;
255 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
267 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
268 IOPhysicalLength inMaxTransferSize
,
269 IOPhysicalLength inAlignment
)
271 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment
,
277 /************************* class IOLittleMemoryCursor ************************/
280 #define super IOMemoryCursor
281 OSDefineMetaClassAndStructors(IOLittleMemoryCursor
, IOMemoryCursor
)
284 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment
,
286 UInt32 inSegmentIndex
)
288 IOPhysicalAddress
* segment
;
290 segment
= &((PhysicalSegment
*) inSegments
)[inSegmentIndex
].location
;
291 OSWriteLittleInt(segment
, 0, inSegment
.location
);
292 OSWriteLittleInt(segment
, sizeof(IOPhysicalAddress
), inSegment
.length
);
295 IOLittleMemoryCursor
*
296 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
297 IOPhysicalLength inMaxTransferSize
,
298 IOPhysicalLength inAlignment
)
300 IOLittleMemoryCursor
* me
= new IOLittleMemoryCursor
;
302 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
313 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
316 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
317 IOPhysicalLength inMaxTransferSize
,
318 IOPhysicalLength inAlignment
)
320 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment
,
326 /************************* class IODBDMAMemoryCursor *************************/
330 #include <IOKit/ppc/IODBDMA.h>
333 #define super IOMemoryCursor
334 OSDefineMetaClassAndStructors(IODBDMAMemoryCursor
, IOMemoryCursor
)
337 IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment
,
339 UInt32 inSegmentIndex
)
341 IODBDMADescriptor
*segment
;
343 segment
= &((IODBDMADescriptor
*) inSegments
)[inSegmentIndex
];
345 // Write location into address field
346 OSWriteSwapInt32((UInt32
*) segment
, 4, inSegment
.location
);
348 // Write count into 1st two bytes of operation field.
349 // DO NOT touch rest of operation field as it should contain a STOP command.
350 OSWriteSwapInt16((UInt16
*) segment
, 0, inSegment
.length
);
353 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
355 IODBDMAMemoryCursor
*
356 IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
357 IOPhysicalLength inMaxTransferSize
,
358 IOPhysicalLength inAlignment
)
360 IODBDMAMemoryCursor
*me
= new IODBDMAMemoryCursor
;
362 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
373 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
376 IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
377 IOPhysicalLength inMaxTransferSize
,
378 IOPhysicalLength inAlignment
)
380 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment
,
386 #endif /* defined(__ppc__) */