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