]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOMemoryCursor.cpp
xnu-6153.41.3.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 me->release();
55 return NULL;
56 }
57
58 return me;
59 }
60
61 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62
63 bool
64 IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc,
65 IOPhysicalLength inMaxSegmentSize,
66 IOPhysicalLength inMaxTransferSize,
67 IOPhysicalLength inAlignment)
68 {
69 // @@@ gvdl: Remove me
70 #if 1
71 static UInt sMaxDBDMASegment;
72 if (!sMaxDBDMASegment) {
73 sMaxDBDMASegment = (UInt) - 1;
74 if (PE_parse_boot_argn("mseg", &sMaxDBDMASegment, sizeof(sMaxDBDMASegment))) {
75 IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment);
76 }
77 }
78
79 if (inMaxSegmentSize > sMaxDBDMASegment) {
80 inMaxSegmentSize = sMaxDBDMASegment;
81 }
82 #endif
83
84 if (!super::init()) {
85 return false;
86 }
87
88 if (!inSegFunc) {
89 return false;
90 }
91
92 outSeg = inSegFunc;
93 maxSegmentSize = inMaxSegmentSize;
94 if (inMaxTransferSize) {
95 maxTransferSize = inMaxTransferSize;
96 } else {
97 maxTransferSize = (IOPhysicalLength) - 1;
98 }
99 alignMask = inAlignment - 1;
100 assert(alignMask == 0); // No alignment code yet!
101
102 return true;
103 }
104
105 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
106
107 UInt32
108 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor,
109 IOByteCount fromPosition,
110 void * inSegments,
111 UInt32 inMaxSegments,
112 UInt32 inMaxTransferSize,
113 IOByteCount *outTransferSize)
114 {
115 if (!inDescriptor) {
116 return 0;
117 }
118
119 if (!inMaxSegments) {
120 return 0;
121 }
122
123 if (!inMaxTransferSize) {
124 inMaxTransferSize = maxTransferSize;
125 }
126
127 /*
128 * Iterate over the packet, translating segments where allowed
129 *
130 * If we finished cleanly return number of segments found
131 * and update the position in the descriptor.
132 */
133 PhysicalSegment curSeg = { 0, 0 };
134 UInt curSegIndex = 0;
135 UInt curTransferSize = 0;
136 IOByteCount inDescriptorLength = inDescriptor->getLength();
137 PhysicalSegment seg = { 0, 0 };
138
139 while ((seg.location) || (fromPosition < inDescriptorLength)) {
140 if (!seg.location) {
141 seg.location = inDescriptor->getPhysicalSegment(
142 fromPosition, (IOByteCount*)&seg.length);
143 assert(seg.location);
144 assert(seg.length);
145 fromPosition += seg.length;
146 }
147
148 if (!curSeg.location) {
149 curTransferSize += seg.length;
150 curSeg = seg;
151 seg.location = 0;
152 } else if ((curSeg.location + curSeg.length == seg.location)) {
153 curTransferSize += seg.length;
154 curSeg.length += seg.length;
155 seg.location = 0;
156 }
157
158 if (!seg.location) {
159 if ((curSeg.length > maxSegmentSize)) {
160 seg.location = curSeg.location + maxSegmentSize;
161 seg.length = curSeg.length - maxSegmentSize;
162 curTransferSize -= seg.length;
163 curSeg.length -= seg.length;
164 }
165
166 if ((curTransferSize >= inMaxTransferSize)) {
167 curSeg.length -= curTransferSize - inMaxTransferSize;
168 curTransferSize = inMaxTransferSize;
169 break;
170 }
171 }
172
173 if (seg.location) {
174 if ((curSegIndex + 1 == inMaxSegments)) {
175 break;
176 }
177 (*outSeg)(curSeg, inSegments, curSegIndex++);
178 curSeg.location = 0;
179 }
180 }
181
182 if (curSeg.location) {
183 (*outSeg)(curSeg, inSegments, curSegIndex++);
184 }
185
186 if (outTransferSize) {
187 *outTransferSize = curTransferSize;
188 }
189
190 return curSegIndex;
191 }
192
193 /************************ class IONaturalMemoryCursor ************************/
194
195 #undef super
196 #define super IOMemoryCursor
197 OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
198
199 void
200 IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
201 void * outSegments,
202 UInt32 outSegmentIndex)
203 {
204 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
205 }
206
207 IONaturalMemoryCursor *
208 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
209 IOPhysicalLength inMaxTransferSize,
210 IOPhysicalLength inAlignment)
211 {
212 IONaturalMemoryCursor *me = new IONaturalMemoryCursor;
213
214 if (me && !me->initWithSpecification(inMaxSegmentSize,
215 inMaxTransferSize,
216 inAlignment)) {
217 me->release();
218 return NULL;
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 #if IOPhysSize == 64
250 OSWriteBigInt64(segment, 0, inSegment.location);
251 OSWriteBigInt64(segment, sizeof(IOPhysicalAddress), inSegment.length);
252 #else
253 OSWriteBigInt(segment, 0, inSegment.location);
254 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
255 #endif
256 }
257
258 IOBigMemoryCursor *
259 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
260 IOPhysicalLength inMaxTransferSize,
261 IOPhysicalLength inAlignment)
262 {
263 IOBigMemoryCursor * me = new IOBigMemoryCursor;
264
265 if (me && !me->initWithSpecification(inMaxSegmentSize,
266 inMaxTransferSize,
267 inAlignment)) {
268 me->release();
269 return NULL;
270 }
271
272 return me;
273 }
274
275 bool
276 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
277 IOPhysicalLength inMaxTransferSize,
278 IOPhysicalLength inAlignment)
279 {
280 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
281 inMaxSegmentSize,
282 inMaxTransferSize,
283 inAlignment);
284 }
285
286 /************************* class IOLittleMemoryCursor ************************/
287
288 #undef super
289 #define super IOMemoryCursor
290 OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
291
292 void
293 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
294 void * inSegments,
295 UInt32 inSegmentIndex)
296 {
297 IOPhysicalAddress * segment;
298
299 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
300 #if IOPhysSize == 64
301 OSWriteLittleInt64(segment, 0, inSegment.location);
302 OSWriteLittleInt64(segment, sizeof(IOPhysicalAddress), inSegment.length);
303 #else
304 OSWriteLittleInt(segment, 0, inSegment.location);
305 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
306 #endif
307 }
308
309 IOLittleMemoryCursor *
310 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
311 IOPhysicalLength inMaxTransferSize,
312 IOPhysicalLength inAlignment)
313 {
314 IOLittleMemoryCursor * me = new IOLittleMemoryCursor;
315
316 if (me && !me->initWithSpecification(inMaxSegmentSize,
317 inMaxTransferSize,
318 inAlignment)) {
319 me->release();
320 return NULL;
321 }
322
323 return me;
324 }
325
326 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
327
328 bool
329 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
330 IOPhysicalLength inMaxTransferSize,
331 IOPhysicalLength inAlignment)
332 {
333 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
334 inMaxSegmentSize,
335 inMaxTransferSize,
336 inAlignment);
337 }