|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * Copyright 1994 NeXT Computer, Inc.
26: * All rights reserved.
27: *
28: */
29:
30: #if NOTYET
31:
32: /* Clean this up later. */
33: #define KERNEL_PRIVATE 1
34: #define ARCH_PRIVATE 1
35:
36: #import <driverkit/IOBuffer.h>
37: #import <driverkit/generalFuncs.h>
38: #import <vm/vm_map.h>
39: #import <mach/vm_param.h>
40:
41: #define MIN(a,b) ((a) < (b) ? (a) : (b))
42:
43: /*
44: * Helper functions
45: */
46: static BOOL checkAlignmentFromVirtual(
47: IOVirtualAddress vaddr,
48: IOAddressMap map,
49: int size,
50: IOAlignment align
51: );
52: static BOOL checkAlignmentFromPhysical(
53: IOPhysicalAddress paddr,
54: int size,
55: IOAlignment align
56: );
57: static BOOL checkAlignmentFromSize(
58: int size,
59: IOAlignment align
60: );
61: static unsigned int
62: maskFromAlignment(
63: IOAlignment align
64: );
65: static unsigned int
66: alignmentFromAddress(
67: IOVirtualAddress addr
68: );
69: static void
70: copyData(
71: IOVirtualAddress src,
72: IOAddressMap srcMap,
73: IOVirtualAddress dst,
74: IOAddressMap dstMap,
75: unsigned int totalLength
76: );
77:
78:
79:
80: @implementation IOBuffer
81:
82: -initWithSize:(unsigned int)newSize
83: {
84: return [self initWithSize:newSize attributes:IOBuf_None
85: alignment:IOBufferAlignMin];
86: }
87:
88: -initWithSize:(unsigned int)newSize
89: attributes:(IOBufferAttributes)newAttrs
90: alignment:(IOAlignment)align
91: {
92: if (checkAlignmentFromSize(newSize, align) == NO) {
93: return nil;
94: }
95:
96: size = newSize;
97: alignment = align;
98: if ([[self class] allocMemoryWithSize:newSize
99: attributes:newAttrs
100: alignment:align
101: allocedAddress:&allocedData
102: dataAddress:(IOVirtualAddress *)&data
103: allocedSize:&allocedSize
104: newAttributes:&attributes
105: newMap:&map] == NO) {
106: return nil;
107: }
108:
109: attributes = newAttrs | IOBuf_Wired | IOBuf_Contiguous | IOBuf_WiredStatic;
110:
111: map = (IOAddressMap)IOVmTaskSelf();
112:
113: return self;
114: }
115:
116:
117: -initFromVirtualAddress:(IOVirtualAddress)addr
118: addressMap:(IOAddressMap)newMap
119: size:(unsigned int)newSize
120: {
121: data = (void *)addr;
122: map = newMap;
123:
124: alignment = MIN(alignmentFromAddress(addr),
125: alignmentFromAddress(newSize));
126: size = newSize;
127:
128: return self;
129: }
130:
131:
132: -initFromPhysicalAddress:(IOPhysicalAddress)addr
133: size:(unsigned int)newSize
134: {
135: data = (void *)addr;
136:
137: alignment = MIN(alignmentFromAddress(addr),
138: alignmentFromAddress(newSize));
139: return nil;
140: }
141:
142: -free
143: {
144: (void)[self unwireMemory];
145: if (allocedData) {
146: [[self class] freeMemory:allocedData
147: size:allocedSize
148: map:map
149: attributes:attributes];
150: }
151: return [super free];
152: }
153:
154: -(BOOL)copyFromBuffer:(IOBuffer *)sourceBuffer
155: {
156: int length, sourceSize;
157: BOOL rtn;
158: IORange source, dest;
159:
160: sourceSize = [sourceBuffer size];
161: source.size = dest.size = MIN(sourceSize, size);
162: source.start = dest.start = 0;
163: rtn = [self copyFromBuffer:sourceBuffer
164: source:source
165: destination:dest];
166: if ((rtn == YES) && (sourceSize < source.size)) {
167: bzero((char *)data + sourceSize, source.size - sourceSize);
168: }
169: return rtn;
170: }
171:
172: -(BOOL)copyFromBuffer:(IOBuffer *)sourceBuffer
173: source:(IORange)srcRange
174: destination:(IORange)dstRange
175: {
176: int sourceSize, destSize;
177: IOVirtualRange sourceAddrRange, destAddrRange;
178:
179: if ([self isWired] == NO || [sourceBuffer isWired] == NO)
180: return NO;
181:
182: sourceSize = [sourceBuffer size] - srcRange.start;
183: destSize = [self size] - dstRange.start;
184: if ((srcRange.size > sourceSize) || (srcRange.size > destSize))
185: return NO;
186:
187: if ([sourceBuffer getVirtualAddress:&sourceAddrRange
188: at:srcRange.start] == NO) {
189: return NO;
190: }
191: if ([self getVirtualAddress:&destAddrRange
192: at:dstRange.start] == NO) {
193: return NO;
194: }
195: copyData(sourceAddrRange.start, [sourceBuffer addressMap],
196: destAddrRange.start, map, srcRange.size);
197:
198: return YES;
199: }
200:
201: -(IOAddressMap)addressMap
202: {
203: return map;
204: }
205:
206:
207: -(BOOL)wireMemory
208: {
209: if ([self isWired])
210: return YES;
211:
212: if (vm_map_pageable(map, trunc_page((char *)data),
213: round_page((char *)data + size), FALSE)
214: == KERN_SUCCESS) {
215: attributes |= IOBuf_Wired;
216: return YES;
217: }
218:
219: return NO;
220: }
221:
222: -(BOOL)unwireMemory
223: {
224: if ([self isWired] == NO)
225: return YES;
226: if (!(attributes & IOBuf_WiredStatic) &&
227: (vm_map_pageable(map, trunc_page((char *)data),
228: round_page((char *)data + size), TRUE)
229: == KERN_SUCCESS)) {
230: attributes &= ~IOBuf_Wired;
231: return YES;
232: }
233: return NO;
234: }
235:
236: -(BOOL)getVirtualAddress:(IOVirtualRange *)virtualRangePtr
237: at:(unsigned int)offset
238: {
239: if (offset >= size)
240: return NO;
241: if (virtualRangePtr != NULL) {
242: virtualRangePtr->start = (IOVirtualAddress)((char *)data + offset);
243: virtualRangePtr->size = size - offset;
244: }
245: return YES;
246: }
247:
248: -(BOOL)getPhysicalAddress:(IOPhysicalRange *)physicalRangePtr
249: at:(unsigned int)offset
250: {
251: IOPhysicalAddress paddr;
252: char *vaddr;
253: int cbytes = 0;
254: IOPhysicalAddress nextContPage, nextPhysPage;
255: char *nextVirtPage, *curVirtPage;
256: int bytesLeftInPage, curByteCount;
257:
258: if ((offset >= size) || ![self isWired])
259: return NO;
260:
261: vaddr = (char *)data + offset;
262: paddr = (IOPhysicalAddress) pmap_resident_extract(
263: vm_map_pmap((vm_map_t)map), vaddr);
264:
265: if (physicalRangePtr != NULL) {
266: curByteCount = size - offset;
267: curVirtPage = (char *)trunc_page(vaddr);
268: nextContPage = (IOPhysicalAddress)trunc_page(paddr) + PAGE_SIZE;
269: bytesLeftInPage = nextContPage - paddr;
270:
271: while (curByteCount > 0) {
272: if (bytesLeftInPage >= curByteCount ){
273: cbytes += curByteCount;
274: break;
275: } else {
276: cbytes += bytesLeftInPage;
277:
278: nextPhysPage = (IOPhysicalAddress) pmap_resident_extract(
279: vm_map_pmap((vm_map_t)map),
280: (curVirtPage + PAGE_SIZE));
281:
282: if (nextPhysPage == nextContPage){
283: curByteCount -= bytesLeftInPage;
284: bytesLeftInPage = PAGE_SIZE;
285: curVirtPage += PAGE_SIZE;
286: nextContPage += PAGE_SIZE;
287: } else {
288: break;
289: }
290: }
291: }
292: }
293: if (physicalRangePtr != NULL) {
294: physicalRangePtr->start = paddr;
295: physicalRangePtr->size = cbytes;
296: }
297: return YES;
298: }
299:
300: -(IOBufferAttributes)attributes
301: {
302: return attributes;
303: }
304:
305: -(BOOL)isContiguous
306: {
307: return ((attributes & IOBuf_Contiguous) ? YES : NO);
308: }
309:
310: -(BOOL)isWired
311: {
312: return ((attributes & IOBuf_Wired) ? YES : NO);
313: }
314:
315: -(unsigned int)size
316: {
317: return size;
318: }
319:
320: -(void *)data
321: {
322: return data;
323: }
324:
325: -(IOAlignment)alignment
326: {
327: return alignment;
328: }
329:
330: -(IORange)range
331: {
332: return userRange;
333: }
334:
335:
336: -(void)setRange:(IORange)newRange
337: {
338: userRange = newRange;
339: }
340:
341:
342: +(BOOL)allocMemoryWithSize:(int)memSize
343: attributes:(IOBufferAttributes)attr
344: alignment:(IOAlignment)align
345: allocedAddress:(IOVirtualAddress *)allocPtr
346: dataAddress:(IOVirtualAddress *)dataPtr
347: allocedSize:(int *)sizePtr
348: newAttributes:(IOBufferAttributes *)newAttrPtr
349: newMap:(IOAddressMap *)mapPtr
350: {
351: IOVirtualAddress vaddr;
352: int alignSize, newSize;
353:
354: alignSize = IOAlignmentToSize(align);
355: newSize = memSize + 2 * alignSize;
356:
357: /* an optimization that relies on IOMalloc returning aligned pages. */
358: if (newSize > PAGE_SIZE && memSize <= PAGE_SIZE)
359: newSize = PAGE_SIZE;
360:
361: vaddr = (IOVirtualAddress)IOMalloc(newSize);
362: if (vaddr == 0)
363: return FALSE;
364:
365: *allocPtr = vaddr;
366: if (newSize != memSize)
367: *dataPtr = (vaddr + alignSize - 1) & ~(alignSize - 1);
368: else
369: *dataPtr = vaddr;
370: *sizePtr = newSize;
371: *newAttrPtr = IOBuf_Wired | IOBuf_WiredStatic | IOBuf_Contiguous;
372: *mapPtr = (IOAddressMap)IOVmTaskSelf();
373: return TRUE;
374: }
375:
376:
377: +(BOOL)freeMemory:(IOVirtualAddress)addr
378: size:(int)memsize
379: map:(IOAddressMap)memmap
380: attributes:(IOBufferAttributes)attr
381: {
382: IOFree((void *)addr, memsize);
383: return TRUE;
384: }
385:
386: @end
387:
388: /*
389: * Helper functions
390: */
391:
392: /*
393: * Returns TRUE if the address meets the specified aligment requirement.
394: */
395: static BOOL checkAlignmentFromVirtual(
396: IOVirtualAddress vaddr,
397: IOAddressMap map,
398: int size,
399: IOAlignment align
400: )
401: {
402: IOPhysicalAddress paddr;
403:
404: paddr = (IOPhysicalAddress) pmap_resident_extract(
405: vm_map_pmap((vm_map_t)map), vaddr);
406:
407: return checkAlignmentFromPhysical(paddr, size, align);
408: }
409:
410: static BOOL checkAlignmentFromPhysical(
411: IOPhysicalAddress paddr,
412: int size,
413: IOAlignment align
414: )
415: {
416: unsigned int mask;
417:
418: if (align > IOBufferAlignMax)
419: return NO;
420:
421: mask = maskFromAlignment(align);
422: if ((paddr & mask) || (size & mask))
423: return NO;
424:
425: return YES;
426: }
427:
428: static BOOL checkAlignmentFromSize(
429: int size,
430: IOAlignment align
431: )
432: {
433: unsigned int mask;
434: if (align > IOBufferAlignMax)
435: return NO;
436: mask = maskFromAlignment(align);
437: if (size & mask)
438: return NO;
439: return YES;
440: }
441:
442: static unsigned int
443: maskFromAlignment(
444: IOAlignment align
445: )
446: {
447: unsigned int mask;
448:
449: for (mask = 0; align; align--) {
450: mask = (mask << 1) | 1;
451: }
452: return mask;
453: }
454:
455: static unsigned int
456: alignmentFromAddress(
457: unsigned int addr
458: )
459: {
460: unsigned int alignment;
461:
462: for (alignment=0; alignment < PAGE_SHIFT; alignment++) {
463: if (addr & 0x01)
464: return alignment;
465: addr >>= 1;
466: }
467: return alignment;
468: }
469:
470: static void
471: copyData(
472: IOVirtualAddress src,
473: IOAddressMap srcMap,
474: IOVirtualAddress dst,
475: IOAddressMap dstMap,
476: unsigned int totalLength
477: )
478: {
479: IOPhysicalAddress physSrc, physDst;
480: int currentLength;
481: int leftInSrc, leftInDst;
482: const unsigned int pageMask = PAGE_SIZE - 1;
483:
484: while (totalLength) {
485: physSrc = (IOPhysicalAddress) pmap_resident_extract(
486: vm_map_pmap((vm_map_t)srcMap), src);
487: physDst = (IOPhysicalAddress) pmap_resident_extract(
488: vm_map_pmap((vm_map_t)dstMap), dst);
489: leftInSrc = PAGE_SIZE - (physSrc & pageMask);
490: leftInDst = PAGE_SIZE - (physDst & pageMask);
491: currentLength = MIN(leftInSrc, leftInDst);
492: currentLength = MIN(totalLength, currentLength);
493: bcopy(pmap_phys_to_kern(physSrc),
494: pmap_phys_to_kern(physDst),
495: currentLength);
496: totalLength -= currentLength;
497: src += currentLength;
498: dst += currentLength;
499: }
500: }
501:
502: #endif NOTYET
503:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.