2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 /* IOMemoryCursor.cpp created by wgulland on 1999-3-02 */
32 #include <IOKit/assert.h>
33 #include <IOKit/IOLib.h>
34 #include <IOKit/IOMemoryCursor.h>
35 #include <IOKit/IOMemoryDescriptor.h>
36 #include <libkern/OSByteOrder.h>
38 /**************************** class IOMemoryCursor ***************************/
41 #define super OSObject
42 OSDefineMetaClassAndStructors(IOMemoryCursor
, OSObject
)
45 IOMemoryCursor::withSpecification(SegmentFunction inSegFunc
,
46 IOPhysicalLength inMaxSegmentSize
,
47 IOPhysicalLength inMaxTransferSize
,
48 IOPhysicalLength inAlignment
)
50 IOMemoryCursor
* me
= new IOMemoryCursor
;
52 if (me
&& !me
->initWithSpecification(inSegFunc
,
64 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
67 IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc
,
68 IOPhysicalLength inMaxSegmentSize
,
69 IOPhysicalLength inMaxTransferSize
,
70 IOPhysicalLength inAlignment
)
72 // @@@ gvdl: Remove me
74 static UInt sMaxDBDMASegment
;
75 if (!sMaxDBDMASegment
) {
76 sMaxDBDMASegment
= (UInt
) -1;
77 if (PE_parse_boot_arg("mseg", &sMaxDBDMASegment
))
78 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment
);
81 if (inMaxSegmentSize
> sMaxDBDMASegment
) inMaxSegmentSize
= sMaxDBDMASegment
;
91 maxSegmentSize
= inMaxSegmentSize
;
92 if (inMaxTransferSize
)
93 maxTransferSize
= inMaxTransferSize
;
95 maxTransferSize
= (IOPhysicalLength
) -1;
96 alignMask
= inAlignment
- 1;
97 assert(alignMask
== 0); // No alignment code yet!
102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
105 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor
*inDescriptor
,
106 IOPhysicalLength fromPosition
,
108 UInt32 inMaxSegments
,
109 UInt32 inMaxTransferSize
,
110 IOByteCount
*outTransferSize
)
118 if (!inMaxTransferSize
)
119 inMaxTransferSize
= maxTransferSize
;
122 * Iterate over the packet, translating segments where allowed
124 * If we finished cleanly return number of segments found
125 * and update the position in the descriptor.
127 PhysicalSegment curSeg
= { 0, 0 };
128 UInt curSegIndex
= 0;
129 UInt curTransferSize
= 0;
130 IOByteCount inDescriptorLength
= inDescriptor
->getLength();
131 PhysicalSegment seg
= { 0, 0 };
133 while ((seg
.location
) || (fromPosition
< inDescriptorLength
))
137 seg
.location
= inDescriptor
->getPhysicalSegment(
138 fromPosition
, &seg
.length
);
139 assert(seg
.location
);
141 fromPosition
+= seg
.length
;
144 if (!curSeg
.location
)
146 curTransferSize
+= seg
.length
;
150 else if ((curSeg
.location
+ curSeg
.length
== seg
.location
))
152 curTransferSize
+= seg
.length
;
153 curSeg
.length
+= seg
.length
;
159 if ((curSeg
.length
> maxSegmentSize
))
161 seg
.location
= curSeg
.location
+ maxSegmentSize
;
162 seg
.length
= curSeg
.length
- maxSegmentSize
;
163 curTransferSize
-= seg
.length
;
164 curSeg
.length
-= seg
.length
;
167 if ((curTransferSize
>= inMaxTransferSize
))
169 curSeg
.length
-= curTransferSize
- inMaxTransferSize
;
170 curTransferSize
= inMaxTransferSize
;
177 if ((curSegIndex
+ 1 == inMaxSegments
))
179 (*outSeg
)(curSeg
, inSegments
, curSegIndex
++);
185 (*outSeg
)(curSeg
, inSegments
, curSegIndex
++);
188 *outTransferSize
= curTransferSize
;
193 /************************ class IONaturalMemoryCursor ************************/
196 #define super IOMemoryCursor
197 OSDefineMetaClassAndStructors(IONaturalMemoryCursor
, IOMemoryCursor
)
199 void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment
,
201 UInt32 outSegmentIndex
)
203 ((PhysicalSegment
*) outSegments
)[outSegmentIndex
] = segment
;
206 IONaturalMemoryCursor
*
207 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
208 IOPhysicalLength inMaxTransferSize
,
209 IOPhysicalLength inAlignment
)
211 IONaturalMemoryCursor
*me
= new IONaturalMemoryCursor
;
213 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
225 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
226 IOPhysicalLength inMaxTransferSize
,
227 IOPhysicalLength inAlignment
)
229 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment
,
235 /************************** class IOBigMemoryCursor **************************/
238 #define super IOMemoryCursor
239 OSDefineMetaClassAndStructors(IOBigMemoryCursor
, IOMemoryCursor
)
242 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment
,
244 UInt32 inSegmentIndex
)
246 IOPhysicalAddress
* segment
;
248 segment
= &((PhysicalSegment
*) inSegments
)[inSegmentIndex
].location
;
249 OSWriteBigInt(segment
, 0, inSegment
.location
);
250 OSWriteBigInt(segment
, sizeof(IOPhysicalAddress
), inSegment
.length
);
254 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
255 IOPhysicalLength inMaxTransferSize
,
256 IOPhysicalLength inAlignment
)
258 IOBigMemoryCursor
* me
= new IOBigMemoryCursor
;
260 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
272 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
273 IOPhysicalLength inMaxTransferSize
,
274 IOPhysicalLength inAlignment
)
276 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment
,
282 /************************* class IOLittleMemoryCursor ************************/
285 #define super IOMemoryCursor
286 OSDefineMetaClassAndStructors(IOLittleMemoryCursor
, IOMemoryCursor
)
289 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment
,
291 UInt32 inSegmentIndex
)
293 IOPhysicalAddress
* segment
;
295 segment
= &((PhysicalSegment
*) inSegments
)[inSegmentIndex
].location
;
296 OSWriteLittleInt(segment
, 0, inSegment
.location
);
297 OSWriteLittleInt(segment
, sizeof(IOPhysicalAddress
), inSegment
.length
);
300 IOLittleMemoryCursor
*
301 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
302 IOPhysicalLength inMaxTransferSize
,
303 IOPhysicalLength inAlignment
)
305 IOLittleMemoryCursor
* me
= new IOLittleMemoryCursor
;
307 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
318 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
321 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
322 IOPhysicalLength inMaxTransferSize
,
323 IOPhysicalLength inAlignment
)
325 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment
,
331 /************************* class IODBDMAMemoryCursor *************************/
335 #include <IOKit/ppc/IODBDMA.h>
338 #define super IOMemoryCursor
339 OSDefineMetaClassAndStructors(IODBDMAMemoryCursor
, IOMemoryCursor
)
342 IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment
,
344 UInt32 inSegmentIndex
)
346 IODBDMADescriptor
*segment
;
348 segment
= &((IODBDMADescriptor
*) inSegments
)[inSegmentIndex
];
350 // Write location into address field
351 OSWriteSwapInt32((UInt32
*) segment
, 4, inSegment
.location
);
353 // Write count into 1st two bytes of operation field.
354 // DO NOT touch rest of operation field as it should contain a STOP command.
355 OSWriteSwapInt16((UInt16
*) segment
, 0, inSegment
.length
);
358 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
360 IODBDMAMemoryCursor
*
361 IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize
,
362 IOPhysicalLength inMaxTransferSize
,
363 IOPhysicalLength inAlignment
)
365 IODBDMAMemoryCursor
*me
= new IODBDMAMemoryCursor
;
367 if (me
&& !me
->initWithSpecification(inMaxSegmentSize
,
378 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
381 IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize
,
382 IOPhysicalLength inMaxTransferSize
,
383 IOPhysicalLength inAlignment
)
385 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment
,
391 #endif /* defined(__ppc__) */