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