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