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