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