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