2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* IOMemoryCursor.cpp created by wgulland on 1999-3-02 */
25 #include <IOKit/assert.h>
26 #include <IOKit/IOLib.h>
27 #include <IOKit/IOMemoryCursor.h>
28 #include <IOKit/IOMemoryDescriptor.h>
29 #include <libkern/OSByteOrder.h>
31 /**************************** class IOMemoryCursor ***************************/
34 #define super OSObject
35 OSDefineMetaClassAndStructors(IOMemoryCursor
, OSObject
)
38 IOMemoryCursor::withSpecification(SegmentFunction inSegFunc
,
39 IOPhysicalLength inMaxSegmentSize
,
40 IOPhysicalLength inMaxTransferSize
,
41 IOPhysicalLength inAlignment
)
43 IOMemoryCursor
* me
= new IOMemoryCursor
;
45 if (me
&& !me
->initWithSpecification(inSegFunc
,
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
60 IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc
,
61 IOPhysicalLength inMaxSegmentSize
,
62 IOPhysicalLength inMaxTransferSize
,
63 IOPhysicalLength inAlignment
)
65 // @@@ gvdl: Remove me
67 static UInt sMaxDBDMASegment
;
68 if (!sMaxDBDMASegment
) {
69 sMaxDBDMASegment
= (UInt
) -1;
70 if (PE_parse_boot_arg("mseg", &sMaxDBDMASegment
))
71 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment
);
74 if (inMaxSegmentSize
> sMaxDBDMASegment
) inMaxSegmentSize
= sMaxDBDMASegment
;
84 maxSegmentSize
= inMaxSegmentSize
;
85 if (inMaxTransferSize
)
86 maxTransferSize
= inMaxTransferSize
;
88 maxTransferSize
= (IOPhysicalLength
) -1;
89 alignMask
= inAlignment
- 1;
90 assert(alignMask
== 0); // No alignment code yet!
95 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
98 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor
*inDescriptor
,
99 IOPhysicalLength fromPosition
,
101 UInt32 inMaxSegments
,
102 UInt32 inMaxTransferSize
,
103 IOByteCount
*outTransferSize
)
111 if (!inMaxTransferSize
)
112 inMaxTransferSize
= maxTransferSize
;
115 * Iterate over the packet, translating segments where allowed
117 * If we finished cleanly return number of segments found
118 * and update the position in the descriptor.
120 PhysicalSegment curSeg
= { 0, 0 };
121 UInt curSegIndex
= 0;
122 UInt curTransferSize
= 0;
123 IOByteCount inDescriptorLength
= inDescriptor
->getLength();
124 PhysicalSegment seg
= { 0, 0 };
126 while ((seg
.location
) || (fromPosition
< inDescriptorLength
))
130 seg
.location
= inDescriptor
->getPhysicalSegment(
131 fromPosition
, &seg
.length
);
132 assert(seg
.location
);
134 fromPosition
+= seg
.length
;
137 if (!curSeg
.location
)
139 curTransferSize
+= seg
.length
;
143 else if ((curSeg
.location
+ curSeg
.length
== seg
.location
))
145 curTransferSize
+= seg
.length
;
146 curSeg
.length
+= seg
.length
;
152 if ((curSeg
.length
> maxSegmentSize
))
154 seg
.location
= curSeg
.location
+ maxSegmentSize
;
155 seg
.length
= curSeg
.length
- maxSegmentSize
;
156 curTransferSize
-= seg
.length
;
157 curSeg
.length
-= seg
.length
;
160 if ((curTransferSize
>= inMaxTransferSize
))
162 curSeg
.length
-= curTransferSize
- inMaxTransferSize
;
163 curTransferSize
= inMaxTransferSize
;
170 if ((curSegIndex
+ 1 == inMaxSegments
))
172 (*outSeg
)(curSeg
, inSegments
, curSegIndex
++);
178 (*outSeg
)(curSeg
, inSegments
, curSegIndex
++);
181 *outTransferSize
= curTransferSize
;
186 /************************ class IONaturalMemoryCursor ************************/
189 #define super IOMemoryCursor
190 OSDefineMetaClassAndStructors(IONaturalMemoryCursor
, IOMemoryCursor
)
192 void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment
,
194 UInt32 outSegmentIndex
)
196 ((PhysicalSegment
*) outSegments
)[outSegmentIndex
] = segment
;
199 IONaturalMemoryCursor
*
200 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
201 IOPhysicalLength inMaxTransferSize
,
202 IOPhysicalLength inAlignment
)
204 IONaturalMemoryCursor
*me
= new IONaturalMemoryCursor
;
206 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
218 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
219 IOPhysicalLength inMaxTransferSize
,
220 IOPhysicalLength inAlignment
)
222 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment
,
228 /************************** class IOBigMemoryCursor **************************/
231 #define super IOMemoryCursor
232 OSDefineMetaClassAndStructors(IOBigMemoryCursor
, IOMemoryCursor
)
235 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment
,
237 UInt32 inSegmentIndex
)
239 IOPhysicalAddress
* segment
;
241 segment
= &((PhysicalSegment
*) inSegments
)[inSegmentIndex
].location
;
242 OSWriteBigInt(segment
, 0, inSegment
.location
);
243 OSWriteBigInt(segment
, sizeof(IOPhysicalAddress
), inSegment
.length
);
247 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
248 IOPhysicalLength inMaxTransferSize
,
249 IOPhysicalLength inAlignment
)
251 IOBigMemoryCursor
* me
= new IOBigMemoryCursor
;
253 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
265 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
266 IOPhysicalLength inMaxTransferSize
,
267 IOPhysicalLength inAlignment
)
269 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment
,
275 /************************* class IOLittleMemoryCursor ************************/
278 #define super IOMemoryCursor
279 OSDefineMetaClassAndStructors(IOLittleMemoryCursor
, IOMemoryCursor
)
282 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment
,
284 UInt32 inSegmentIndex
)
286 IOPhysicalAddress
* segment
;
288 segment
= &((PhysicalSegment
*) inSegments
)[inSegmentIndex
].location
;
289 OSWriteLittleInt(segment
, 0, inSegment
.location
);
290 OSWriteLittleInt(segment
, sizeof(IOPhysicalAddress
), inSegment
.length
);
293 IOLittleMemoryCursor
*
294 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
295 IOPhysicalLength inMaxTransferSize
,
296 IOPhysicalLength inAlignment
)
298 IOLittleMemoryCursor
* me
= new IOLittleMemoryCursor
;
300 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
311 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
314 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
315 IOPhysicalLength inMaxTransferSize
,
316 IOPhysicalLength inAlignment
)
318 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment
,
324 /************************* class IODBDMAMemoryCursor *************************/
328 #include <IOKit/ppc/IODBDMA.h>
331 #define super IOMemoryCursor
332 OSDefineMetaClassAndStructors(IODBDMAMemoryCursor
, IOMemoryCursor
)
335 IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment
,
337 UInt32 inSegmentIndex
)
339 IODBDMADescriptor
*segment
;
341 segment
= &((IODBDMADescriptor
*) inSegments
)[inSegmentIndex
];
343 // Write location into address field
344 OSWriteSwapInt32((UInt32
*) segment
, 4, inSegment
.location
);
346 // Write count into 1st two bytes of operation field.
347 // DO NOT touch rest of operation field as it should contain a STOP command.
348 OSWriteSwapInt16((UInt16
*) segment
, 0, inSegment
.length
);
351 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
353 IODBDMAMemoryCursor
*
354 IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
355 IOPhysicalLength inMaxTransferSize
,
356 IOPhysicalLength inAlignment
)
358 IODBDMAMemoryCursor
*me
= new IODBDMAMemoryCursor
;
360 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
371 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374 IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
375 IOPhysicalLength inMaxTransferSize
,
376 IOPhysicalLength inAlignment
)
378 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment
,
384 #endif /* defined(__ppc__) */