]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOMemoryCursor.cpp
xnu-792.13.8.tar.gz
[apple/xnu.git] / iokit / Kernel / IOMemoryCursor.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
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
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
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.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/* IOMemoryCursor.cpp created by wgulland on 1999-3-02 */
31
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>
37
38/**************************** class IOMemoryCursor ***************************/
39
40#undef super
41#define super OSObject
42OSDefineMetaClassAndStructors(IOMemoryCursor, OSObject)
43
44IOMemoryCursor *
45IOMemoryCursor::withSpecification(SegmentFunction inSegFunc,
46 IOPhysicalLength inMaxSegmentSize,
47 IOPhysicalLength inMaxTransferSize,
48 IOPhysicalLength inAlignment)
49{
50 IOMemoryCursor * me = new IOMemoryCursor;
51
52 if (me && !me->initWithSpecification(inSegFunc,
53 inMaxSegmentSize,
54 inMaxTransferSize,
55 inAlignment))
56 {
57 me->release();
58 return 0;
59 }
60
61 return me;
62}
63
64/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
65
66bool
67IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc,
68 IOPhysicalLength inMaxSegmentSize,
69 IOPhysicalLength inMaxTransferSize,
70 IOPhysicalLength inAlignment)
71{
55e303ae
A
72// @@@ gvdl: Remove me
73#if 1
74static UInt sMaxDBDMASegment;
75if (!sMaxDBDMASegment) {
76 sMaxDBDMASegment = (UInt) -1;
77 if (PE_parse_boot_arg("mseg", &sMaxDBDMASegment))
78 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment);
79}
80
81if (inMaxSegmentSize > sMaxDBDMASegment) inMaxSegmentSize = sMaxDBDMASegment;
82#endif
83
1c79356b
A
84 if (!super::init())
85 return false;
86
87 if (!inSegFunc)
88 return false;
89
90 outSeg = inSegFunc;
91 maxSegmentSize = inMaxSegmentSize;
92 if (inMaxTransferSize)
93 maxTransferSize = inMaxTransferSize;
94 else
95 maxTransferSize = (IOPhysicalLength) -1;
96 alignMask = inAlignment - 1;
97 assert(alignMask == 0); // No alignment code yet!
98
99 return true;
100}
101
102/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103
104UInt32
105IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor,
106 IOPhysicalLength fromPosition,
107 void * inSegments,
108 UInt32 inMaxSegments,
109 UInt32 inMaxTransferSize,
110 IOByteCount *outTransferSize)
111{
112 if (!inDescriptor)
113 return 0;
114
115 if (!inMaxSegments)
116 return 0;
117
118 if (!inMaxTransferSize)
119 inMaxTransferSize = maxTransferSize;
120
121 /*
122 * Iterate over the packet, translating segments where allowed
123 *
124 * If we finished cleanly return number of segments found
125 * and update the position in the descriptor.
126 */
91447636 127 PhysicalSegment curSeg = { 0, 0 };
1c79356b
A
128 UInt curSegIndex = 0;
129 UInt curTransferSize = 0;
55e303ae 130 IOByteCount inDescriptorLength = inDescriptor->getLength();
91447636 131 PhysicalSegment seg = { 0, 0 };
1c79356b 132
55e303ae 133 while ((seg.location) || (fromPosition < inDescriptorLength))
1c79356b 134 {
55e303ae
A
135 if (!seg.location)
136 {
137 seg.location = inDescriptor->getPhysicalSegment(
138 fromPosition, &seg.length);
139 assert(seg.location);
140 assert(seg.length);
141 fromPosition += seg.length;
142 }
143
144 if (!curSeg.location)
145 {
146 curTransferSize += seg.length;
147 curSeg = seg;
148 seg.location = 0;
149 }
150 else if ((curSeg.location + curSeg.length == seg.location))
151 {
152 curTransferSize += seg.length;
153 curSeg.length += seg.length;
154 seg.location = 0;
155 }
156
157 if (!seg.location)
158 {
159 if ((curSeg.length > maxSegmentSize))
160 {
161 seg.location = curSeg.location + maxSegmentSize;
162 seg.length = curSeg.length - maxSegmentSize;
163 curTransferSize -= seg.length;
164 curSeg.length -= seg.length;
165 }
166
167 if ((curTransferSize >= inMaxTransferSize))
168 {
169 curSeg.length -= curTransferSize - inMaxTransferSize;
170 curTransferSize = inMaxTransferSize;
171 break;
172 }
173 }
174
175 if (seg.location)
176 {
177 if ((curSegIndex + 1 == inMaxSegments))
178 break;
179 (*outSeg)(curSeg, inSegments, curSegIndex++);
180 curSeg.location = 0;
181 }
1c79356b
A
182 }
183
55e303ae
A
184 if (curSeg.location)
185 (*outSeg)(curSeg, inSegments, curSegIndex++);
186
1c79356b
A
187 if (outTransferSize)
188 *outTransferSize = curTransferSize;
189
190 return curSegIndex;
191}
192
193/************************ class IONaturalMemoryCursor ************************/
194
195#undef super
196#define super IOMemoryCursor
197OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
198
199void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
200 void * outSegments,
201 UInt32 outSegmentIndex)
202{
203 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
204}
205
206IONaturalMemoryCursor *
207IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
208 IOPhysicalLength inMaxTransferSize,
209 IOPhysicalLength inAlignment)
210{
211 IONaturalMemoryCursor *me = new IONaturalMemoryCursor;
212
213 if (me && !me->initWithSpecification(inMaxSegmentSize,
214 inMaxTransferSize,
215 inAlignment))
216 {
217 me->release();
218 return 0;
219 }
220
221 return me;
222}
223
224bool
225IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
226 IOPhysicalLength inMaxTransferSize,
227 IOPhysicalLength inAlignment)
228{
229 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment,
230 inMaxSegmentSize,
231 inMaxTransferSize,
232 inAlignment);
233}
234
235/************************** class IOBigMemoryCursor **************************/
236
237#undef super
238#define super IOMemoryCursor
239OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
240
241void
242IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment,
243 void * inSegments,
244 UInt32 inSegmentIndex)
245{
246 IOPhysicalAddress * segment;
247
248 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
249 OSWriteBigInt(segment, 0, inSegment.location);
250 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
251}
252
253IOBigMemoryCursor *
254IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
255 IOPhysicalLength inMaxTransferSize,
256 IOPhysicalLength inAlignment)
257{
258 IOBigMemoryCursor * me = new IOBigMemoryCursor;
259
260 if (me && !me->initWithSpecification(inMaxSegmentSize,
261 inMaxTransferSize,
262 inAlignment))
263 {
264 me->release();
265 return 0;
266 }
267
268 return me;
269}
270
271bool
272IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
273 IOPhysicalLength inMaxTransferSize,
274 IOPhysicalLength inAlignment)
275{
276 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
277 inMaxSegmentSize,
278 inMaxTransferSize,
279 inAlignment);
280}
281
282/************************* class IOLittleMemoryCursor ************************/
283
284#undef super
285#define super IOMemoryCursor
286OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
287
288void
289IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
290 void * inSegments,
291 UInt32 inSegmentIndex)
292{
293 IOPhysicalAddress * segment;
294
295 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
296 OSWriteLittleInt(segment, 0, inSegment.location);
297 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
298}
299
300IOLittleMemoryCursor *
301IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
302 IOPhysicalLength inMaxTransferSize,
303 IOPhysicalLength inAlignment)
304{
305 IOLittleMemoryCursor * me = new IOLittleMemoryCursor;
306
307 if (me && !me->initWithSpecification(inMaxSegmentSize,
308 inMaxTransferSize,
309 inAlignment))
310 {
311 me->release();
312 return 0;
313 }
314
315 return me;
316}
317
318/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
319
320bool
321IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
322 IOPhysicalLength inMaxTransferSize,
323 IOPhysicalLength inAlignment)
324{
325 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
326 inMaxSegmentSize,
327 inMaxTransferSize,
328 inAlignment);
329}
330
331/************************* class IODBDMAMemoryCursor *************************/
332
333#if defined(__ppc__)
334
335#include <IOKit/ppc/IODBDMA.h>
336
337#undef super
338#define super IOMemoryCursor
339OSDefineMetaClassAndStructors(IODBDMAMemoryCursor, IOMemoryCursor)
340
341void
342IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment,
343 void * inSegments,
344 UInt32 inSegmentIndex)
345{
346 IODBDMADescriptor *segment;
347
348 segment = &((IODBDMADescriptor *) inSegments)[inSegmentIndex];
349
350 // Write location into address field
351 OSWriteSwapInt32((UInt32 *) segment, 4, inSegment.location);
352
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);
356}
357
358/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
359
360IODBDMAMemoryCursor *
361IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
362 IOPhysicalLength inMaxTransferSize,
363 IOPhysicalLength inAlignment)
364{
365 IODBDMAMemoryCursor *me = new IODBDMAMemoryCursor;
366
367 if (me && !me->initWithSpecification(inMaxSegmentSize,
368 inMaxTransferSize,
369 inAlignment))
370 {
371 me->release();
372 return 0;
373 }
374
375 return me;
376}
377
378/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
379
380bool
381IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
382 IOPhysicalLength inMaxTransferSize,
383 IOPhysicalLength inAlignment)
384{
385 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment,
386 inMaxSegmentSize,
387 inMaxTransferSize,
388 inAlignment);
389}
390
391#endif /* defined(__ppc__) */
392