]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
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 | { | |
55e303ae A |
70 | // @@@ gvdl: Remove me |
71 | #if 1 | |
72 | static UInt sMaxDBDMASegment; | |
73 | if (!sMaxDBDMASegment) { | |
74 | sMaxDBDMASegment = (UInt) -1; | |
593a1d5f | 75 | if (PE_parse_boot_argn("mseg", &sMaxDBDMASegment, sizeof (sMaxDBDMASegment))) |
55e303ae A |
76 | IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment); |
77 | } | |
78 | ||
79 | if (inMaxSegmentSize > sMaxDBDMASegment) inMaxSegmentSize = sMaxDBDMASegment; | |
80 | #endif | |
81 | ||
1c79356b A |
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, | |
b0d623f7 | 104 | IOByteCount fromPosition, |
1c79356b A |
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 | */ | |
91447636 | 125 | PhysicalSegment curSeg = { 0, 0 }; |
1c79356b A |
126 | UInt curSegIndex = 0; |
127 | UInt curTransferSize = 0; | |
55e303ae | 128 | IOByteCount inDescriptorLength = inDescriptor->getLength(); |
91447636 | 129 | PhysicalSegment seg = { 0, 0 }; |
1c79356b | 130 | |
55e303ae | 131 | while ((seg.location) || (fromPosition < inDescriptorLength)) |
1c79356b | 132 | { |
55e303ae A |
133 | if (!seg.location) |
134 | { | |
135 | seg.location = inDescriptor->getPhysicalSegment( | |
b0d623f7 | 136 | fromPosition, (IOByteCount*)&seg.length); |
55e303ae A |
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 | } | |
1c79356b A |
180 | } |
181 | ||
55e303ae A |
182 | if (curSeg.location) |
183 | (*outSeg)(curSeg, inSegments, curSegIndex++); | |
184 | ||
1c79356b A |
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 | } | |
328 | ||
329 | /************************* class IODBDMAMemoryCursor *************************/ | |
330 | ||
331 | #if defined(__ppc__) | |
332 | ||
333 | #include <IOKit/ppc/IODBDMA.h> | |
334 | ||
335 | #undef super | |
336 | #define super IOMemoryCursor | |
337 | OSDefineMetaClassAndStructors(IODBDMAMemoryCursor, IOMemoryCursor) | |
338 | ||
339 | void | |
340 | IODBDMAMemoryCursor::outputSegment(PhysicalSegment inSegment, | |
341 | void * inSegments, | |
342 | UInt32 inSegmentIndex) | |
343 | { | |
344 | IODBDMADescriptor *segment; | |
345 | ||
346 | segment = &((IODBDMADescriptor *) inSegments)[inSegmentIndex]; | |
347 | ||
348 | // Write location into address field | |
349 | OSWriteSwapInt32((UInt32 *) segment, 4, inSegment.location); | |
350 | ||
351 | // Write count into 1st two bytes of operation field. | |
352 | // DO NOT touch rest of operation field as it should contain a STOP command. | |
353 | OSWriteSwapInt16((UInt16 *) segment, 0, inSegment.length); | |
354 | } | |
355 | ||
356 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
357 | ||
358 | IODBDMAMemoryCursor * | |
359 | IODBDMAMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, | |
360 | IOPhysicalLength inMaxTransferSize, | |
361 | IOPhysicalLength inAlignment) | |
362 | { | |
363 | IODBDMAMemoryCursor *me = new IODBDMAMemoryCursor; | |
364 | ||
365 | if (me && !me->initWithSpecification(inMaxSegmentSize, | |
366 | inMaxTransferSize, | |
367 | inAlignment)) | |
368 | { | |
369 | me->release(); | |
370 | return 0; | |
371 | } | |
372 | ||
373 | return me; | |
374 | } | |
375 | ||
376 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
377 | ||
378 | bool | |
379 | IODBDMAMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, | |
380 | IOPhysicalLength inMaxTransferSize, | |
381 | IOPhysicalLength inAlignment) | |
382 | { | |
383 | return super::initWithSpecification(&IODBDMAMemoryCursor::outputSegment, | |
384 | inMaxSegmentSize, | |
385 | inMaxTransferSize, | |
386 | inAlignment); | |
387 | } | |
388 | ||
389 | #endif /* defined(__ppc__) */ | |
390 |