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