]>
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@ |
0a7de745 | 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. | |
0a7de745 | 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. | |
0a7de745 | 17 | * |
2d21ac55 A |
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. | |
0a7de745 | 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, | |
0a7de745 A |
44 | IOPhysicalLength inMaxSegmentSize, |
45 | IOPhysicalLength inMaxTransferSize, | |
46 | IOPhysicalLength inAlignment) | |
1c79356b | 47 | { |
0a7de745 A |
48 | IOMemoryCursor * me = new IOMemoryCursor; |
49 | ||
50 | if (me && !me->initWithSpecification(inSegFunc, | |
51 | inMaxSegmentSize, | |
52 | inMaxTransferSize, | |
53 | inAlignment)) { | |
54 | me->release(); | |
cb323159 | 55 | return NULL; |
0a7de745 A |
56 | } |
57 | ||
58 | return me; | |
1c79356b A |
59 | } |
60 | ||
61 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
62 | ||
63 | bool | |
64 | IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc, | |
0a7de745 A |
65 | IOPhysicalLength inMaxSegmentSize, |
66 | IOPhysicalLength inMaxTransferSize, | |
67 | IOPhysicalLength inAlignment) | |
1c79356b | 68 | { |
55e303ae A |
69 | // @@@ gvdl: Remove me |
70 | #if 1 | |
0a7de745 A |
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 | } | |
55e303ae A |
82 | #endif |
83 | ||
0a7de745 A |
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; | |
1c79356b A |
103 | } |
104 | ||
105 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
106 | ||
0a7de745 | 107 | UInt32 |
1c79356b | 108 | IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor, |
0a7de745 A |
109 | IOByteCount fromPosition, |
110 | void * inSegments, | |
111 | UInt32 inMaxSegments, | |
112 | UInt32 inMaxTransferSize, | |
113 | IOByteCount *outTransferSize) | |
1c79356b | 114 | { |
0a7de745 A |
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; | |
1c79356b A |
191 | } |
192 | ||
193 | /************************ class IONaturalMemoryCursor ************************/ | |
194 | ||
195 | #undef super | |
196 | #define super IOMemoryCursor | |
197 | OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor) | |
198 | ||
0a7de745 A |
199 | void |
200 | IONaturalMemoryCursor::outputSegment(PhysicalSegment segment, | |
201 | void * outSegments, | |
202 | UInt32 outSegmentIndex) | |
1c79356b | 203 | { |
0a7de745 | 204 | ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment; |
1c79356b A |
205 | } |
206 | ||
0a7de745 | 207 | IONaturalMemoryCursor * |
1c79356b | 208 | IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, |
0a7de745 A |
209 | IOPhysicalLength inMaxTransferSize, |
210 | IOPhysicalLength inAlignment) | |
1c79356b | 211 | { |
0a7de745 | 212 | IONaturalMemoryCursor *me = new IONaturalMemoryCursor; |
1c79356b | 213 | |
0a7de745 A |
214 | if (me && !me->initWithSpecification(inMaxSegmentSize, |
215 | inMaxTransferSize, | |
216 | inAlignment)) { | |
217 | me->release(); | |
cb323159 | 218 | return NULL; |
0a7de745 | 219 | } |
1c79356b | 220 | |
0a7de745 | 221 | return me; |
1c79356b A |
222 | } |
223 | ||
0a7de745 | 224 | bool |
1c79356b | 225 | IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, |
0a7de745 A |
226 | IOPhysicalLength inMaxTransferSize, |
227 | IOPhysicalLength inAlignment) | |
1c79356b | 228 | { |
0a7de745 A |
229 | return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment, |
230 | inMaxSegmentSize, | |
231 | inMaxTransferSize, | |
232 | inAlignment); | |
1c79356b A |
233 | } |
234 | ||
235 | /************************** class IOBigMemoryCursor **************************/ | |
236 | ||
237 | #undef super | |
238 | #define super IOMemoryCursor | |
239 | OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor) | |
240 | ||
0a7de745 | 241 | void |
1c79356b | 242 | IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment, |
0a7de745 A |
243 | void * inSegments, |
244 | UInt32 inSegmentIndex) | |
1c79356b | 245 | { |
0a7de745 | 246 | IOPhysicalAddress * segment; |
1c79356b | 247 | |
0a7de745 | 248 | segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location; |
d9a64523 | 249 | #if IOPhysSize == 64 |
0a7de745 A |
250 | OSWriteBigInt64(segment, 0, inSegment.location); |
251 | OSWriteBigInt64(segment, sizeof(IOPhysicalAddress), inSegment.length); | |
d9a64523 | 252 | #else |
0a7de745 A |
253 | OSWriteBigInt(segment, 0, inSegment.location); |
254 | OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length); | |
d9a64523 | 255 | #endif |
1c79356b A |
256 | } |
257 | ||
258 | IOBigMemoryCursor * | |
259 | IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, | |
0a7de745 A |
260 | IOPhysicalLength inMaxTransferSize, |
261 | IOPhysicalLength inAlignment) | |
1c79356b | 262 | { |
0a7de745 | 263 | IOBigMemoryCursor * me = new IOBigMemoryCursor; |
1c79356b | 264 | |
0a7de745 A |
265 | if (me && !me->initWithSpecification(inMaxSegmentSize, |
266 | inMaxTransferSize, | |
267 | inAlignment)) { | |
268 | me->release(); | |
cb323159 | 269 | return NULL; |
0a7de745 | 270 | } |
1c79356b | 271 | |
0a7de745 | 272 | return me; |
1c79356b A |
273 | } |
274 | ||
0a7de745 | 275 | bool |
1c79356b | 276 | IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, |
0a7de745 A |
277 | IOPhysicalLength inMaxTransferSize, |
278 | IOPhysicalLength inAlignment) | |
1c79356b | 279 | { |
0a7de745 A |
280 | return super::initWithSpecification(&IOBigMemoryCursor::outputSegment, |
281 | inMaxSegmentSize, | |
282 | inMaxTransferSize, | |
283 | inAlignment); | |
1c79356b A |
284 | } |
285 | ||
286 | /************************* class IOLittleMemoryCursor ************************/ | |
287 | ||
288 | #undef super | |
289 | #define super IOMemoryCursor | |
290 | OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor) | |
291 | ||
0a7de745 | 292 | void |
1c79356b | 293 | IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment, |
0a7de745 A |
294 | void * inSegments, |
295 | UInt32 inSegmentIndex) | |
1c79356b | 296 | { |
0a7de745 | 297 | IOPhysicalAddress * segment; |
1c79356b | 298 | |
0a7de745 | 299 | segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location; |
d9a64523 | 300 | #if IOPhysSize == 64 |
0a7de745 A |
301 | OSWriteLittleInt64(segment, 0, inSegment.location); |
302 | OSWriteLittleInt64(segment, sizeof(IOPhysicalAddress), inSegment.length); | |
d9a64523 | 303 | #else |
0a7de745 A |
304 | OSWriteLittleInt(segment, 0, inSegment.location); |
305 | OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length); | |
d9a64523 | 306 | #endif |
1c79356b A |
307 | } |
308 | ||
309 | IOLittleMemoryCursor * | |
310 | IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize, | |
0a7de745 A |
311 | IOPhysicalLength inMaxTransferSize, |
312 | IOPhysicalLength inAlignment) | |
1c79356b | 313 | { |
0a7de745 | 314 | IOLittleMemoryCursor * me = new IOLittleMemoryCursor; |
1c79356b | 315 | |
0a7de745 A |
316 | if (me && !me->initWithSpecification(inMaxSegmentSize, |
317 | inMaxTransferSize, | |
318 | inAlignment)) { | |
319 | me->release(); | |
cb323159 | 320 | return NULL; |
0a7de745 | 321 | } |
1c79356b | 322 | |
0a7de745 | 323 | return me; |
1c79356b A |
324 | } |
325 | ||
326 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
327 | ||
0a7de745 | 328 | bool |
1c79356b | 329 | IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize, |
0a7de745 A |
330 | IOPhysicalLength inMaxTransferSize, |
331 | IOPhysicalLength inAlignment) | |
1c79356b | 332 | { |
0a7de745 A |
333 | return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment, |
334 | inMaxSegmentSize, | |
335 | inMaxTransferSize, | |
336 | inAlignment); | |
1c79356b | 337 | } |