]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOMemoryCursor.cpp
xnu-792.24.17.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 * 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
34 OSDefineMetaClassAndStructors(IOMemoryCursor, OSObject)
35
36 IOMemoryCursor *
37 IOMemoryCursor::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
58 bool
59 IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc,
60 IOPhysicalLength inMaxSegmentSize,
61 IOPhysicalLength inMaxTransferSize,
62 IOPhysicalLength inAlignment)
63 {
64 // @@@ gvdl: Remove me
65 #if 1
66 static UInt sMaxDBDMASegment;
67 if (!sMaxDBDMASegment) {
68 sMaxDBDMASegment = (UInt) -1;
69 if (PE_parse_boot_arg("mseg", &sMaxDBDMASegment))
70 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment);
71 }
72
73 if (inMaxSegmentSize > sMaxDBDMASegment) inMaxSegmentSize = sMaxDBDMASegment;
74 #endif
75
76 if (!super::init())
77 return false;
78
79 if (!inSegFunc)
80 return false;
81
82 outSeg = inSegFunc;
83 maxSegmentSize = inMaxSegmentSize;
84 if (inMaxTransferSize)
85 maxTransferSize = inMaxTransferSize;
86 else
87 maxTransferSize = (IOPhysicalLength) -1;
88 alignMask = inAlignment - 1;
89 assert(alignMask == 0); // No alignment code yet!
90
91 return true;
92 }
93
94 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95
96 UInt32
97 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor,
98 IOPhysicalLength fromPosition,
99 void * inSegments,
100 UInt32 inMaxSegments,
101 UInt32 inMaxTransferSize,
102 IOByteCount *outTransferSize)
103 {
104 if (!inDescriptor)
105 return 0;
106
107 if (!inMaxSegments)
108 return 0;
109
110 if (!inMaxTransferSize)
111 inMaxTransferSize = maxTransferSize;
112
113 /*
114 * Iterate over the packet, translating segments where allowed
115 *
116 * If we finished cleanly return number of segments found
117 * and update the position in the descriptor.
118 */
119 PhysicalSegment curSeg = { 0, 0 };
120 UInt curSegIndex = 0;
121 UInt curTransferSize = 0;
122 IOByteCount inDescriptorLength = inDescriptor->getLength();
123 PhysicalSegment seg = { 0, 0 };
124
125 while ((seg.location) || (fromPosition < inDescriptorLength))
126 {
127 if (!seg.location)
128 {
129 seg.location = inDescriptor->getPhysicalSegment(
130 fromPosition, &seg.length);
131 assert(seg.location);
132 assert(seg.length);
133 fromPosition += seg.length;
134 }
135
136 if (!curSeg.location)
137 {
138 curTransferSize += seg.length;
139 curSeg = seg;
140 seg.location = 0;
141 }
142 else if ((curSeg.location + curSeg.length == seg.location))
143 {
144 curTransferSize += seg.length;
145 curSeg.length += seg.length;
146 seg.location = 0;
147 }
148
149 if (!seg.location)
150 {
151 if ((curSeg.length > maxSegmentSize))
152 {
153 seg.location = curSeg.location + maxSegmentSize;
154 seg.length = curSeg.length - maxSegmentSize;
155 curTransferSize -= seg.length;
156 curSeg.length -= seg.length;
157 }
158
159 if ((curTransferSize >= inMaxTransferSize))
160 {
161 curSeg.length -= curTransferSize - inMaxTransferSize;
162 curTransferSize = inMaxTransferSize;
163 break;
164 }
165 }
166
167 if (seg.location)
168 {
169 if ((curSegIndex + 1 == inMaxSegments))
170 break;
171 (*outSeg)(curSeg, inSegments, curSegIndex++);
172 curSeg.location = 0;
173 }
174 }
175
176 if (curSeg.location)
177 (*outSeg)(curSeg, inSegments, curSegIndex++);
178
179 if (outTransferSize)
180 *outTransferSize = curTransferSize;
181
182 return curSegIndex;
183 }
184
185 /************************ class IONaturalMemoryCursor ************************/
186
187 #undef super
188 #define super IOMemoryCursor
189 OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
190
191 void IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
192 void * outSegments,
193 UInt32 outSegmentIndex)
194 {
195 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
196 }
197
198 IONaturalMemoryCursor *
199 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
200 IOPhysicalLength inMaxTransferSize,
201 IOPhysicalLength inAlignment)
202 {
203 IONaturalMemoryCursor *me = new IONaturalMemoryCursor;
204
205 if (me && !me->initWithSpecification(inMaxSegmentSize,
206 inMaxTransferSize,
207 inAlignment))
208 {
209 me->release();
210 return 0;
211 }
212
213 return me;
214 }
215
216 bool
217 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
218 IOPhysicalLength inMaxTransferSize,
219 IOPhysicalLength inAlignment)
220 {
221 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment,
222 inMaxSegmentSize,
223 inMaxTransferSize,
224 inAlignment);
225 }
226
227 /************************** class IOBigMemoryCursor **************************/
228
229 #undef super
230 #define super IOMemoryCursor
231 OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
232
233 void
234 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment,
235 void * inSegments,
236 UInt32 inSegmentIndex)
237 {
238 IOPhysicalAddress * segment;
239
240 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
241 OSWriteBigInt(segment, 0, inSegment.location);
242 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
243 }
244
245 IOBigMemoryCursor *
246 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
247 IOPhysicalLength inMaxTransferSize,
248 IOPhysicalLength inAlignment)
249 {
250 IOBigMemoryCursor * me = new IOBigMemoryCursor;
251
252 if (me && !me->initWithSpecification(inMaxSegmentSize,
253 inMaxTransferSize,
254 inAlignment))
255 {
256 me->release();
257 return 0;
258 }
259
260 return me;
261 }
262
263 bool
264 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
265 IOPhysicalLength inMaxTransferSize,
266 IOPhysicalLength inAlignment)
267 {
268 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
269 inMaxSegmentSize,
270 inMaxTransferSize,
271 inAlignment);
272 }
273
274 /************************* class IOLittleMemoryCursor ************************/
275
276 #undef super
277 #define super IOMemoryCursor
278 OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
279
280 void
281 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
282 void * inSegments,
283 UInt32 inSegmentIndex)
284 {
285 IOPhysicalAddress * segment;
286
287 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
288 OSWriteLittleInt(segment, 0, inSegment.location);
289 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
290 }
291
292 IOLittleMemoryCursor *
293 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
294 IOPhysicalLength inMaxTransferSize,
295 IOPhysicalLength inAlignment)
296 {
297 IOLittleMemoryCursor * me = new IOLittleMemoryCursor;
298
299 if (me && !me->initWithSpecification(inMaxSegmentSize,
300 inMaxTransferSize,
301 inAlignment))
302 {
303 me->release();
304 return 0;
305 }
306
307 return me;
308 }
309
310 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
311
312 bool
313 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
314 IOPhysicalLength inMaxTransferSize,
315 IOPhysicalLength inAlignment)
316 {
317 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
318 inMaxSegmentSize,
319 inMaxTransferSize,
320 inAlignment);
321 }
322
323 /************************* class IODBDMAMemoryCursor *************************/
324
325 #if defined(__ppc__)
326
327 #include <IOKit/ppc/IODBDMA.h>
328
329 #undef super
330 #define super IOMemoryCursor
331 OSDefineMetaClassAndStructors(IODBDMAMemoryCursor, IOMemoryCursor)
332
333 void
334 IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment,
335 void * inSegments,
336 UInt32 inSegmentIndex)
337 {
338 IODBDMADescriptor *segment;
339
340 segment = &((IODBDMADescriptor *) inSegments)[inSegmentIndex];
341
342 // Write location into address field
343 OSWriteSwapInt32((UInt32 *) segment, 4, inSegment.location);
344
345 // Write count into 1st two bytes of operation field.
346 // DO NOT touch rest of operation field as it should contain a STOP command.
347 OSWriteSwapInt16((UInt16 *) segment, 0, inSegment.length);
348 }
349
350 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
351
352 IODBDMAMemoryCursor *
353 IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
354 IOPhysicalLength inMaxTransferSize,
355 IOPhysicalLength inAlignment)
356 {
357 IODBDMAMemoryCursor *me = new IODBDMAMemoryCursor;
358
359 if (me && !me->initWithSpecification(inMaxSegmentSize,
360 inMaxTransferSize,
361 inAlignment))
362 {
363 me->release();
364 return 0;
365 }
366
367 return me;
368 }
369
370 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
371
372 bool
373 IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
374 IOPhysicalLength inMaxTransferSize,
375 IOPhysicalLength inAlignment)
376 {
377 return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment,
378 inMaxSegmentSize,
379 inMaxTransferSize,
380 inAlignment);
381 }
382
383 #endif /* defined(__ppc__) */
384