]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOMemoryCursor.cpp
xnu-201.19.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 *
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.
11 *
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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{
64 if (!super::init())
65 return false;
66
67 if (!inSegFunc)
68 return false;
69
70 outSeg = inSegFunc;
71 maxSegmentSize = inMaxSegmentSize;
72 if (inMaxTransferSize)
73 maxTransferSize = inMaxTransferSize;
74 else
75 maxTransferSize = (IOPhysicalLength) -1;
76 alignMask = inAlignment - 1;
77 assert(alignMask == 0); // No alignment code yet!
78
79 return true;
80}
81
82/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
83
84UInt32
85IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor,
86 IOPhysicalLength fromPosition,
87 void * inSegments,
88 UInt32 inMaxSegments,
89 UInt32 inMaxTransferSize,
90 IOByteCount *outTransferSize)
91{
92 if (!inDescriptor)
93 return 0;
94
95 if (!inMaxSegments)
96 return 0;
97
98 if (!inMaxTransferSize)
99 inMaxTransferSize = maxTransferSize;
100
101 /*
102 * Iterate over the packet, translating segments where allowed
103 *
104 * If we finished cleanly return number of segments found
105 * and update the position in the descriptor.
106 */
107 UInt curSegIndex = 0;
108 UInt curTransferSize = 0;
109 PhysicalSegment seg;
110
111 while ((curSegIndex < inMaxSegments)
112 && (curTransferSize < inMaxTransferSize)
113 && (seg.location = inDescriptor->getPhysicalSegment(
114 fromPosition + curTransferSize, &seg.length)))
115 {
116 assert(seg.length);
117 seg.length = min(inMaxTransferSize-curTransferSize,
118 (min(seg.length, maxSegmentSize)));
119 (*outSeg)(seg, inSegments, curSegIndex++);
120 curTransferSize += seg.length;
121 }
122
123 if (outTransferSize)
124 *outTransferSize = curTransferSize;
125
126 return curSegIndex;
127}
128
129/************************ class IONaturalMemoryCursor ************************/
130
131#undef super
132#define super IOMemoryCursor
133OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
134
135void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
136 void * outSegments,
137 UInt32 outSegmentIndex)
138{
139 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
140}
141
142IONaturalMemoryCursor *
143IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
144 IOPhysicalLength inMaxTransferSize,
145 IOPhysicalLength inAlignment)
146{
147 IONaturalMemoryCursor *me = new IONaturalMemoryCursor;
148
149 if (me && !me->initWithSpecification(inMaxSegmentSize,
150 inMaxTransferSize,
151 inAlignment))
152 {
153 me->release();
154 return 0;
155 }
156
157 return me;
158}
159
160bool
161IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
162 IOPhysicalLength inMaxTransferSize,
163 IOPhysicalLength inAlignment)
164{
165 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment,
166 inMaxSegmentSize,
167 inMaxTransferSize,
168 inAlignment);
169}
170
171/************************** class IOBigMemoryCursor **************************/
172
173#undef super
174#define super IOMemoryCursor
175OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
176
177void
178IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment,
179 void * inSegments,
180 UInt32 inSegmentIndex)
181{
182 IOPhysicalAddress * segment;
183
184 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
185 OSWriteBigInt(segment, 0, inSegment.location);
186 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
187}
188
189IOBigMemoryCursor *
190IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
191 IOPhysicalLength inMaxTransferSize,
192 IOPhysicalLength inAlignment)
193{
194 IOBigMemoryCursor * me = new IOBigMemoryCursor;
195
196 if (me && !me->initWithSpecification(inMaxSegmentSize,
197 inMaxTransferSize,
198 inAlignment))
199 {
200 me->release();
201 return 0;
202 }
203
204 return me;
205}
206
207bool
208IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
209 IOPhysicalLength inMaxTransferSize,
210 IOPhysicalLength inAlignment)
211{
212 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
213 inMaxSegmentSize,
214 inMaxTransferSize,
215 inAlignment);
216}
217
218/************************* class IOLittleMemoryCursor ************************/
219
220#undef super
221#define super IOMemoryCursor
222OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
223
224void
225IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
226 void * inSegments,
227 UInt32 inSegmentIndex)
228{
229 IOPhysicalAddress * segment;
230
231 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
232 OSWriteLittleInt(segment, 0, inSegment.location);
233 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
234}
235
236IOLittleMemoryCursor *
237IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
238 IOPhysicalLength inMaxTransferSize,
239 IOPhysicalLength inAlignment)
240{
241 IOLittleMemoryCursor * me = new IOLittleMemoryCursor;
242
243 if (me && !me->initWithSpecification(inMaxSegmentSize,
244 inMaxTransferSize,
245 inAlignment))
246 {
247 me->release();
248 return 0;
249 }
250
251 return me;
252}
253
254/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
255
256bool
257IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
258 IOPhysicalLength inMaxTransferSize,
259 IOPhysicalLength inAlignment)
260{
261 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
262 inMaxSegmentSize,
263 inMaxTransferSize,
264 inAlignment);
265}
266
267/************************* class IODBDMAMemoryCursor *************************/
268
269#if defined(__ppc__)
270
271#include <IOKit/ppc/IODBDMA.h>
272
273#undef super
274#define super IOMemoryCursor
275OSDefineMetaClassAndStructors(IODBDMAMemoryCursor, IOMemoryCursor)
276
277void
278IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment,
279 void * inSegments,
280 UInt32 inSegmentIndex)
281{
282 IODBDMADescriptor *segment;
283
284 segment = &((IODBDMADescriptor *) inSegments)[inSegmentIndex];
285
286 // Write location into address field
287 OSWriteSwapInt32((UInt32 *) segment, 4, inSegment.location);
288
289 // Write count into 1st two bytes of operation field.
290 // DO NOT touch rest of operation field as it should contain a STOP command.
291 OSWriteSwapInt16((UInt16 *) segment, 0, inSegment.length);
292}
293
294/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
295
296IODBDMAMemoryCursor *
297IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
298 IOPhysicalLength inMaxTransferSize,
299 IOPhysicalLength inAlignment)
300{
301 IODBDMAMemoryCursor *me = new IODBDMAMemoryCursor;
302
303 if (me && !me->initWithSpecification(inMaxSegmentSize,
304 inMaxTransferSize,
305 inAlignment))
306 {
307 me->release();
308 return 0;
309 }
310
311 return me;
312}
313
314/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
315
316bool
317IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
318 IOPhysicalLength inMaxTransferSize,
319 IOPhysicalLength inAlignment)
320{
321 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment,
322 inMaxSegmentSize,
323 inMaxTransferSize,
324 inAlignment);
325}
326
327#endif /* defined(__ppc__) */
328