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