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