]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOMemoryCursor.cpp
xnu-517.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 PhysicalSegment curSeg = { 0 };
123 UInt curSegIndex = 0;
124 UInt curTransferSize = 0;
125 IOByteCount inDescriptorLength = inDescriptor->getLength();
126 PhysicalSegment seg = { 0 };
127
128 while ((seg.location) || (fromPosition < inDescriptorLength))
129 {
130 if (!seg.location)
131 {
132 seg.location = inDescriptor->getPhysicalSegment(
133 fromPosition, &seg.length);
134 assert(seg.location);
135 assert(seg.length);
136 fromPosition += seg.length;
137 }
138
139 if (!curSeg.location)
140 {
141 curTransferSize += seg.length;
142 curSeg = seg;
143 seg.location = 0;
144 }
145 else if ((curSeg.location + curSeg.length == seg.location))
146 {
147 curTransferSize += seg.length;
148 curSeg.length += seg.length;
149 seg.location = 0;
150 }
151
152 if (!seg.location)
153 {
154 if ((curSeg.length > maxSegmentSize))
155 {
156 seg.location = curSeg.location + maxSegmentSize;
157 seg.length = curSeg.length - maxSegmentSize;
158 curTransferSize -= seg.length;
159 curSeg.length -= seg.length;
160 }
161
162 if ((curTransferSize >= inMaxTransferSize))
163 {
164 curSeg.length -= curTransferSize - inMaxTransferSize;
165 curTransferSize = inMaxTransferSize;
166 break;
167 }
168 }
169
170 if (seg.location)
171 {
172 if ((curSegIndex + 1 == inMaxSegments))
173 break;
174 (*outSeg)(curSeg, inSegments, curSegIndex++);
175 curSeg.location = 0;
176 }
177 }
178
179 if (curSeg.location)
180 (*outSeg)(curSeg, inSegments, curSegIndex++);
181
182 if (outTransferSize)
183 *outTransferSize = curTransferSize;
184
185 return curSegIndex;
186 }
187
188 /************************ class IONaturalMemoryCursor ************************/
189
190 #undef super
191 #define super IOMemoryCursor
192 OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
193
194 void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
195 void * outSegments,
196 UInt32 outSegmentIndex)
197 {
198 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
199 }
200
201 IONaturalMemoryCursor *
202 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
203 IOPhysicalLength inMaxTransferSize,
204 IOPhysicalLength inAlignment)
205 {
206 IONaturalMemoryCursor *me = new IONaturalMemoryCursor;
207
208 if (me && !me->initWithSpecification(inMaxSegmentSize,
209 inMaxTransferSize,
210 inAlignment))
211 {
212 me->release();
213 return 0;
214 }
215
216 return me;
217 }
218
219 bool
220 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
221 IOPhysicalLength inMaxTransferSize,
222 IOPhysicalLength inAlignment)
223 {
224 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment,
225 inMaxSegmentSize,
226 inMaxTransferSize,
227 inAlignment);
228 }
229
230 /************************** class IOBigMemoryCursor **************************/
231
232 #undef super
233 #define super IOMemoryCursor
234 OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
235
236 void
237 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment,
238 void * inSegments,
239 UInt32 inSegmentIndex)
240 {
241 IOPhysicalAddress * segment;
242
243 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
244 OSWriteBigInt(segment, 0, inSegment.location);
245 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
246 }
247
248 IOBigMemoryCursor *
249 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
250 IOPhysicalLength inMaxTransferSize,
251 IOPhysicalLength inAlignment)
252 {
253 IOBigMemoryCursor * me = new IOBigMemoryCursor;
254
255 if (me && !me->initWithSpecification(inMaxSegmentSize,
256 inMaxTransferSize,
257 inAlignment))
258 {
259 me->release();
260 return 0;
261 }
262
263 return me;
264 }
265
266 bool
267 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
268 IOPhysicalLength inMaxTransferSize,
269 IOPhysicalLength inAlignment)
270 {
271 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
272 inMaxSegmentSize,
273 inMaxTransferSize,
274 inAlignment);
275 }
276
277 /************************* class IOLittleMemoryCursor ************************/
278
279 #undef super
280 #define super IOMemoryCursor
281 OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
282
283 void
284 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
285 void * inSegments,
286 UInt32 inSegmentIndex)
287 {
288 IOPhysicalAddress * segment;
289
290 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
291 OSWriteLittleInt(segment, 0, inSegment.location);
292 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
293 }
294
295 IOLittleMemoryCursor *
296 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
297 IOPhysicalLength inMaxTransferSize,
298 IOPhysicalLength inAlignment)
299 {
300 IOLittleMemoryCursor * me = new IOLittleMemoryCursor;
301
302 if (me && !me->initWithSpecification(inMaxSegmentSize,
303 inMaxTransferSize,
304 inAlignment))
305 {
306 me->release();
307 return 0;
308 }
309
310 return me;
311 }
312
313 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
314
315 bool
316 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
317 IOPhysicalLength inMaxTransferSize,
318 IOPhysicalLength inAlignment)
319 {
320 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
321 inMaxSegmentSize,
322 inMaxTransferSize,
323 inAlignment);
324 }
325
326 /************************* class IODBDMAMemoryCursor *************************/
327
328 #if defined(__ppc__)
329
330 #include <IOKit/ppc/IODBDMA.h>
331
332 #undef super
333 #define super IOMemoryCursor
334 OSDefineMetaClassAndStructors(IODBDMAMemoryCursor, IOMemoryCursor)
335
336 void
337 IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment,
338 void * inSegments,
339 UInt32 inSegmentIndex)
340 {
341 IODBDMADescriptor *segment;
342
343 segment = &((IODBDMADescriptor *) inSegments)[inSegmentIndex];
344
345 // Write location into address field
346 OSWriteSwapInt32((UInt32 *) segment, 4, inSegment.location);
347
348 // Write count into 1st two bytes of operation field.
349 // DO NOT touch rest of operation field as it should contain a STOP command.
350 OSWriteSwapInt16((UInt16 *) segment, 0, inSegment.length);
351 }
352
353 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
354
355 IODBDMAMemoryCursor *
356 IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
357 IOPhysicalLength inMaxTransferSize,
358 IOPhysicalLength inAlignment)
359 {
360 IODBDMAMemoryCursor *me = new IODBDMAMemoryCursor;
361
362 if (me && !me->initWithSpecification(inMaxSegmentSize,
363 inMaxTransferSize,
364 inAlignment))
365 {
366 me->release();
367 return 0;
368 }
369
370 return me;
371 }
372
373 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374
375 bool
376 IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
377 IOPhysicalLength inMaxTransferSize,
378 IOPhysicalLength inAlignment)
379 {
380 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment,
381 inMaxSegmentSize,
382 inMaxTransferSize,
383 inAlignment);
384 }
385
386 #endif /* defined(__ppc__) */
387