]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOMemoryCursor.cpp
xnu-7195.101.1.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 #define IOKIT_ENABLE_SHARED_PTR
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 OSSharedPtr<IOMemoryCursor>
45 IOMemoryCursor::withSpecification(SegmentFunction inSegFunc,
46 IOPhysicalLength inMaxSegmentSize,
47 IOPhysicalLength inMaxTransferSize,
48 IOPhysicalLength inAlignment)
49 {
50 OSSharedPtr<IOMemoryCursor> me = OSMakeShared<IOMemoryCursor>();
51
52 if (me && !me->initWithSpecification(inSegFunc,
53 inMaxSegmentSize,
54 inMaxTransferSize,
55 inAlignment)) {
56 return nullptr;
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
80 if (inMaxSegmentSize > sMaxDBDMASegment) {
81 inMaxSegmentSize = sMaxDBDMASegment;
82 }
83 #endif
84
85 if (!super::init()) {
86 return false;
87 }
88
89 if (!inSegFunc) {
90 return false;
91 }
92 if (inMaxTransferSize > UINT_MAX) {
93 return false;
94 }
95
96 outSeg = inSegFunc;
97 maxSegmentSize = inMaxSegmentSize;
98 if (inMaxTransferSize) {
99 maxTransferSize = inMaxTransferSize;
100 } else {
101 maxTransferSize = (IOPhysicalLength) - 1;
102 }
103 alignMask = inAlignment - 1;
104 assert(alignMask == 0); // No alignment code yet!
105
106 return true;
107 }
108
109 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
110
111 UInt32
112 IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor,
113 IOByteCount fromPosition,
114 void * inSegments,
115 UInt32 inMaxSegments,
116 UInt32 inMaxTransferSize,
117 IOByteCount *outTransferSize)
118 {
119 if (!inDescriptor) {
120 return 0;
121 }
122
123 if (!inMaxSegments) {
124 return 0;
125 }
126
127 if (!inMaxTransferSize) {
128 inMaxTransferSize = (typeof(inMaxTransferSize))maxTransferSize;
129 }
130
131 /*
132 * Iterate over the packet, translating segments where allowed
133 *
134 * If we finished cleanly return number of segments found
135 * and update the position in the descriptor.
136 */
137 PhysicalSegment curSeg = { 0, 0 };
138 UInt curSegIndex = 0;
139 UInt curTransferSize = 0;
140 IOByteCount inDescriptorLength = inDescriptor->getLength();
141 PhysicalSegment seg = { 0, 0 };
142
143 while ((seg.location) || (fromPosition < inDescriptorLength)) {
144 if (!seg.location) {
145 seg.location = inDescriptor->getPhysicalSegment(
146 fromPosition, (IOByteCount*)&seg.length);
147 assert(seg.location);
148 assert(seg.length);
149 fromPosition += seg.length;
150 }
151
152 if (!curSeg.location) {
153 curTransferSize += seg.length;
154 curSeg = seg;
155 seg.location = 0;
156 } else if ((curSeg.location + curSeg.length == seg.location)) {
157 curTransferSize += seg.length;
158 curSeg.length += seg.length;
159 seg.location = 0;
160 }
161
162 if (!seg.location) {
163 if ((curSeg.length > maxSegmentSize)) {
164 seg.location = curSeg.location + maxSegmentSize;
165 seg.length = curSeg.length - maxSegmentSize;
166 curTransferSize -= seg.length;
167 curSeg.length -= seg.length;
168 }
169
170 if ((curTransferSize >= inMaxTransferSize)) {
171 curSeg.length -= curTransferSize - inMaxTransferSize;
172 curTransferSize = inMaxTransferSize;
173 break;
174 }
175 }
176
177 if (seg.location) {
178 if ((curSegIndex + 1 == inMaxSegments)) {
179 break;
180 }
181 (*outSeg)(curSeg, inSegments, curSegIndex++);
182 curSeg.location = 0;
183 }
184 }
185
186 if (curSeg.location) {
187 (*outSeg)(curSeg, inSegments, curSegIndex++);
188 }
189
190 if (outTransferSize) {
191 *outTransferSize = curTransferSize;
192 }
193
194 return curSegIndex;
195 }
196
197 /************************ class IONaturalMemoryCursor ************************/
198
199 #undef super
200 #define super IOMemoryCursor
201 OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
202
203 void
204 IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
205 void * outSegments,
206 UInt32 outSegmentIndex)
207 {
208 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
209 }
210
211 OSSharedPtr<IONaturalMemoryCursor>
212 IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
213 IOPhysicalLength inMaxTransferSize,
214 IOPhysicalLength inAlignment)
215 {
216 OSSharedPtr<IONaturalMemoryCursor> me = OSMakeShared<IONaturalMemoryCursor>();
217
218 if (me && !me->initWithSpecification(inMaxSegmentSize,
219 inMaxTransferSize,
220 inAlignment)) {
221 return nullptr;
222 }
223
224 return me;
225 }
226
227 bool
228 IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
229 IOPhysicalLength inMaxTransferSize,
230 IOPhysicalLength inAlignment)
231 {
232 return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment,
233 inMaxSegmentSize,
234 inMaxTransferSize,
235 inAlignment);
236 }
237
238 /************************** class IOBigMemoryCursor **************************/
239
240 #undef super
241 #define super IOMemoryCursor
242 OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
243
244 void
245 IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment,
246 void * inSegments,
247 UInt32 inSegmentIndex)
248 {
249 IOPhysicalAddress * segment;
250
251 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
252 #if IOPhysSize == 64
253 OSWriteBigInt64(segment, 0, inSegment.location);
254 OSWriteBigInt64(segment, sizeof(IOPhysicalAddress), inSegment.length);
255 #else
256 OSWriteBigInt(segment, 0, inSegment.location);
257 OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
258 #endif
259 }
260
261 OSSharedPtr<IOBigMemoryCursor>
262 IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
263 IOPhysicalLength inMaxTransferSize,
264 IOPhysicalLength inAlignment)
265 {
266 OSSharedPtr<IOBigMemoryCursor> me = OSMakeShared<IOBigMemoryCursor>();
267
268 if (me && !me->initWithSpecification(inMaxSegmentSize,
269 inMaxTransferSize,
270 inAlignment)) {
271 return nullptr;
272 }
273
274 return me;
275 }
276
277 bool
278 IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
279 IOPhysicalLength inMaxTransferSize,
280 IOPhysicalLength inAlignment)
281 {
282 return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
283 inMaxSegmentSize,
284 inMaxTransferSize,
285 inAlignment);
286 }
287
288 /************************* class IOLittleMemoryCursor ************************/
289
290 #undef super
291 #define super IOMemoryCursor
292 OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
293
294 void
295 IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
296 void * inSegments,
297 UInt32 inSegmentIndex)
298 {
299 IOPhysicalAddress * segment;
300
301 segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
302 #if IOPhysSize == 64
303 OSWriteLittleInt64(segment, 0, inSegment.location);
304 OSWriteLittleInt64(segment, sizeof(IOPhysicalAddress), inSegment.length);
305 #else
306 OSWriteLittleInt(segment, 0, inSegment.location);
307 OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
308 #endif
309 }
310
311 OSSharedPtr<IOLittleMemoryCursor>
312 IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
313 IOPhysicalLength inMaxTransferSize,
314 IOPhysicalLength inAlignment)
315 {
316 OSSharedPtr<IOLittleMemoryCursor> me = OSMakeShared<IOLittleMemoryCursor>();
317
318 if (me && !me->initWithSpecification(inMaxSegmentSize,
319 inMaxTransferSize,
320 inAlignment)) {
321 return nullptr;
322 }
323
324 return me;
325 }
326
327 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
328
329 bool
330 IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
331 IOPhysicalLength inMaxTransferSize,
332 IOPhysicalLength inAlignment)
333 {
334 return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
335 inMaxSegmentSize,
336 inMaxTransferSize,
337 inAlignment);
338 }