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
42OSDefineMetaClassAndStructors(IOMemoryCursor, OSObject)
43
44OSSharedPtr<IOMemoryCursor>
45IOMemoryCursor::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(outSegFunc: inSegFunc,
53 maxSegmentSize: inMaxSegmentSize,
54 maxTransferSize: inMaxTransferSize,
55 alignment: inAlignment)) {
56 return nullptr;
57 }
58
59 return me;
60}
61
62/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63
64bool
65IOMemoryCursor::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(arg_string: "mseg", arg_ptr: &sMaxDBDMASegment, max_arg: sizeof(sMaxDBDMASegment))) {
76 IOLog(format: "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
111UInt32
112IOMemoryCursor::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 = { .location: 0, .length: 0 };
138 UInt curSegIndex = 0;
139 UInt curTransferSize = 0;
140 IOByteCount inDescriptorLength = inDescriptor->getLength();
141 PhysicalSegment seg = { .location: 0, .length: 0 };
142
143 while ((seg.location) || (fromPosition < inDescriptorLength)) {
144 if (!seg.location) {
145 seg.location = inDescriptor->getPhysicalSegment(
146 offset: fromPosition, length: (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
201OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
202
203void
204IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
205 void * outSegments,
206 UInt32 outSegmentIndex)
207{
208 ((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
209}
210
211OSSharedPtr<IONaturalMemoryCursor>
212IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
213 IOPhysicalLength inMaxTransferSize,
214 IOPhysicalLength inAlignment)
215{
216 OSSharedPtr<IONaturalMemoryCursor> me = OSMakeShared<IONaturalMemoryCursor>();
217
218 if (me && !me->initWithSpecification(maxSegmentSize: inMaxSegmentSize,
219 maxTransferSize: inMaxTransferSize,
220 alignment: inAlignment)) {
221 return nullptr;
222 }
223
224 return me;
225}
226
227bool
228IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
229 IOPhysicalLength inMaxTransferSize,
230 IOPhysicalLength inAlignment)
231{
232 return super::initWithSpecification(inSegFunc: &IONaturalMemoryCursor::outputSegment,
233 inMaxSegmentSize,
234 inMaxTransferSize,
235 inAlignment);
236}
237
238/************************** class IOBigMemoryCursor **************************/
239
240#undef super
241#define super IOMemoryCursor
242OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
243
244void
245IOBigMemoryCursor::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
261OSSharedPtr<IOBigMemoryCursor>
262IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
263 IOPhysicalLength inMaxTransferSize,
264 IOPhysicalLength inAlignment)
265{
266 OSSharedPtr<IOBigMemoryCursor> me = OSMakeShared<IOBigMemoryCursor>();
267
268 if (me && !me->initWithSpecification(maxSegmentSize: inMaxSegmentSize,
269 maxTransferSize: inMaxTransferSize,
270 alignment: inAlignment)) {
271 return nullptr;
272 }
273
274 return me;
275}
276
277bool
278IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
279 IOPhysicalLength inMaxTransferSize,
280 IOPhysicalLength inAlignment)
281{
282 return super::initWithSpecification(inSegFunc: &IOBigMemoryCursor::outputSegment,
283 inMaxSegmentSize,
284 inMaxTransferSize,
285 inAlignment);
286}
287
288/************************* class IOLittleMemoryCursor ************************/
289
290#undef super
291#define super IOMemoryCursor
292OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
293
294void
295IOLittleMemoryCursor::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
311OSSharedPtr<IOLittleMemoryCursor>
312IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
313 IOPhysicalLength inMaxTransferSize,
314 IOPhysicalLength inAlignment)
315{
316 OSSharedPtr<IOLittleMemoryCursor> me = OSMakeShared<IOLittleMemoryCursor>();
317
318 if (me && !me->initWithSpecification(maxSegmentSize: inMaxSegmentSize,
319 maxTransferSize: inMaxTransferSize,
320 alignment: inAlignment)) {
321 return nullptr;
322 }
323
324 return me;
325}
326
327/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
328
329bool
330IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
331 IOPhysicalLength inMaxTransferSize,
332 IOPhysicalLength inAlignment)
333{
334 return super::initWithSpecification(inSegFunc: &IOLittleMemoryCursor::outputSegment,
335 inMaxSegmentSize,
336 inMaxTransferSize,
337 inAlignment);
338}
339