|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24: *
25: * HISTORY
26: *
27: */
28:
29: #include <IOKit/assert.h>
30: #include <IOKit/system.h>
31: #include <IOKit/IOLib.h>
32: #include <IOKit/IOMemoryDescriptor.h>
33:
34: #include <IOKit/IOKitDebug.h>
35:
36: #include <libkern/c++/OSContainers.h>
37:
38: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39:
40: OSDefineMetaClass( IOMemoryDescriptor, OSObject )
41: OSDefineAbstractStructors( IOMemoryDescriptor, OSObject )
42:
43: #define super IOMemoryDescriptor
44:
45: OSDefineMetaClassAndStructors(IOGeneralMemoryDescriptor, IOMemoryDescriptor)
46:
47: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48:
49: /*
50: * withAddress:
51: *
52: * Create a new IOMemoryDescriptor. The buffer is a virtual address
53: * relative to the specified task. If no task is supplied, the kernel
54: * task is implied.
55: */
56: IOMemoryDescriptor *
57: IOMemoryDescriptor::withAddress(void * address,
58: IOByteCount withLength,
59: IODirection withDirection)
60: {
61: IOGeneralMemoryDescriptor * that = new IOGeneralMemoryDescriptor;
62: if (that)
63: {
64: if (that->initWithAddress(address, withLength, withDirection))
65: return that;
66:
67: that->release();
68: }
69: return 0;
70: }
71:
72: IOMemoryDescriptor *
73: IOMemoryDescriptor::withAddress(vm_address_t address,
74: IOByteCount withLength,
75: IODirection withDirection,
76: task_t withTask)
77: {
78: IOGeneralMemoryDescriptor * that = new IOGeneralMemoryDescriptor;
79: if (that)
80: {
81: if (that->initWithAddress(address, withLength, withDirection, withTask))
82: return that;
83:
84: that->release();
85: }
86: return 0;
87: }
88:
89: IOMemoryDescriptor *
90: IOMemoryDescriptor::withPhysicalAddress(
91: IOPhysicalAddress address,
92: IOByteCount withLength,
93: IODirection withDirection )
94: {
95: return( IOMemoryDescriptor::withAddress( address, withLength,
96: withDirection, (task_t) 0 ));
97: }
98:
99:
100: /*
101: * withRanges:
102: *
103: * Create a new IOMemoryDescriptor. The buffer is made up of several
104: * virtual address ranges, from a given task.
105: *
106: * Passing the ranges as a reference will avoid an extra allocation.
107: */
108: IOMemoryDescriptor *
109: IOMemoryDescriptor::withRanges( IOVirtualRange * ranges,
110: UInt32 withCount,
111: IODirection withDirection,
112: task_t withTask,
113: bool asReference = false)
114: {
115: IOGeneralMemoryDescriptor * that = new IOGeneralMemoryDescriptor;
116: if (that)
117: {
118: if (that->initWithRanges(ranges, withCount, withDirection, withTask, asReference))
119: return that;
120:
121: that->release();
122: }
123: return 0;
124: }
125:
126: IOMemoryDescriptor *
127: IOMemoryDescriptor::withPhysicalRanges( IOPhysicalRange * ranges,
128: UInt32 withCount,
129: IODirection withDirection,
130: bool asReference = false)
131: {
132: IOGeneralMemoryDescriptor * that = new IOGeneralMemoryDescriptor;
133: if (that)
134: {
135: if (that->initWithPhysicalRanges(ranges, withCount, withDirection, asReference))
136: return that;
137:
138: that->release();
139: }
140: return 0;
141: }
142:
143: IOMemoryDescriptor *
144: IOMemoryDescriptor::withSubRange(IOMemoryDescriptor * of,
145: IOByteCount offset,
146: IOByteCount length,
147: IODirection withDirection)
148: {
149: IOSubMemoryDescriptor * that = new IOSubMemoryDescriptor;
150:
151: if (that && !that->initSubRange(of, offset, length, withDirection)) {
152: that->release();
153: that = 0;
154: }
155: return that;
156: }
157:
158: /*
159: * initWithAddress:
160: *
161: * Initialize an IOMemoryDescriptor. The buffer is a virtual address
162: * relative to the specified task. If no task is supplied, the kernel
163: * task is implied.
164: *
165: * An IOMemoryDescriptor can be re-used by calling initWithAddress or
166: * initWithRanges again on an existing instance -- note this behavior
167: * is not commonly supported in other I/O Kit classes, although it is
168: * supported here.
169: */
170: bool
171: IOGeneralMemoryDescriptor::initWithAddress(void * address,
172: IOByteCount withLength,
173: IODirection withDirection)
174: {
175: _singleRange.v.address = (vm_address_t) address;
176: _singleRange.v.length = withLength;
177:
178: return initWithRanges(&_singleRange.v, 1, withDirection, kernel_task, true);
179: }
180:
181: bool
182: IOGeneralMemoryDescriptor::initWithAddress(vm_address_t address,
183: IOByteCount withLength,
184: IODirection withDirection,
185: task_t withTask)
186: {
187: _singleRange.v.address = address;
188: _singleRange.v.length = withLength;
189:
190: return initWithRanges(&_singleRange.v, 1, withDirection, withTask, true);
191: }
192:
193: bool
194: IOGeneralMemoryDescriptor::initWithPhysicalAddress(
195: IOPhysicalAddress address,
196: IOByteCount withLength,
197: IODirection withDirection )
198: {
199: _singleRange.p.address = address;
200: _singleRange.p.length = withLength;
201:
202: return initWithPhysicalRanges( &_singleRange.p, 1, withDirection, true);
203: }
204:
205: /*
206: * initWithRanges:
207: *
208: * Initialize an IOMemoryDescriptor. The buffer is made up of several
209: * virtual address ranges, from a given task
210: *
211: * Passing the ranges as a reference will avoid an extra allocation.
212: *
213: * An IOMemoryDescriptor can be re-used by calling initWithAddress or
214: * initWithRanges again on an existing instance -- note this behavior
215: * is not commonly supported in other I/O Kit classes, although it is
216: * supported here.
217: */
218: bool
219: IOGeneralMemoryDescriptor::initWithRanges(
220: IOVirtualRange * ranges,
221: UInt32 withCount,
222: IODirection withDirection,
223: task_t withTask,
224: bool asReference = false)
225: {
226: assert(ranges);
227: assert(withCount);
228:
229: /*
230: * We can check the _initialized instance variable before having ever set
231: * it to an initial value because I/O Kit guarantees that all our instance
232: * variables are zeroed on an object's allocation.
233: */
234:
235: if (_initialized == false)
236: {
237: if (super::init() == false) return false;
238: _initialized = true;
239: }
240: else
241: {
242: /*
243: * An existing memory descriptor is being retargeted to point to
244: * somewhere else. Clean up our present state.
245: */
246:
247: assert(_wireCount == 0);
248:
249: while (_wireCount)
250: complete();
251: if (_kernPtr)
252: unmapFromKernel();
253: if (_ranges.v && _rangesIsAllocated)
254: IODelete(_ranges.v, IOVirtualRange, _rangesCount);
255: }
256:
257: /*
258: * Initialize the memory descriptor.
259: */
260:
261: _ranges.v = 0;
262: _rangesCount = withCount;
263: _rangesIsAllocated = asReference ? false : true;
264: _direction = withDirection;
265: _length = 0;
266: _task = withTask;
267: _position = 0;
268: _positionAtIndex = 0;
269: _positionAtOffset = 0;
270: _kernPtr = 0;
271: _cachedPhysicalAddress = 0;
272: _cachedVirtualAddress = 0;
273:
274: if (asReference)
275: _ranges.v = ranges;
276: else
277: {
278: _ranges.v = IONew(IOVirtualRange, withCount);
279: if (_ranges.v == 0) return false;
280: bcopy(/* from */ ranges, _ranges.v, withCount * sizeof(IOVirtualRange));
281: }
282:
283: for (unsigned index = 0; index < _rangesCount; index++)
284: {
285: _length += _ranges.v[index].length;
286: }
287:
288: return true;
289: }
290:
291: bool
292: IOGeneralMemoryDescriptor::initWithPhysicalRanges( IOPhysicalRange * ranges,
293: UInt32 withCount,
294: IODirection withDirection,
295: bool asReference = false)
296: {
297: #warning assuming virtual, physical addresses same size
298: return( initWithRanges( (IOVirtualRange *) ranges,
299: withCount, withDirection, (task_t) 0, asReference ));
300: }
301:
302: /*
303: * free
304: *
305: * Free resources.
306: */
307: void IOGeneralMemoryDescriptor::free()
308: {
309: while (_wireCount)
310: complete();
311: if (_kernPtr)
312: unmapFromKernel();
313: if (_ranges.v && _rangesIsAllocated)
314: IODelete(_ranges.v, IOVirtualRange, _rangesCount);
315: super::free();
316: }
317:
318: void IOGeneralMemoryDescriptor::unmapFromKernel()
319: {
320: kern_return_t krtn;
321: vm_offset_t off;
322: // Pull the shared pages out of the task map
323: // Do we need to unwire it first?
324: for ( off = 0; off < _kernSize; off += page_size )
325: {
326: pmap_change_wiring(
327: kernel_pmap,
328: _kernPtrAligned + off,
329: FALSE);
330:
331: pmap_remove(
332: kernel_pmap,
333: _kernPtrAligned + off,
334: _kernPtrAligned + off + page_size);
335: }
336: // Free the former shmem area in the task
337: krtn = vm_deallocate(kernel_map,
338: _kernPtrAligned,
339: _kernSize );
340: assert(krtn == KERN_SUCCESS);
341: _kernPtr = 0;
342: }
343:
344: void IOGeneralMemoryDescriptor::mapIntoKernel(unsigned rangeIndex)
345: {
346: kern_return_t krtn;
347: vm_offset_t off;
348:
349: if (_kernPtr)
350: {
351: if (_kernPtrAtIndex == rangeIndex) return;
352: unmapFromKernel();
353: assert(_kernPtr == 0);
354: }
355:
356: vm_offset_t srcAlign = trunc_page(_ranges.v[rangeIndex].address);
357:
358: _kernSize = trunc_page(_ranges.v[rangeIndex].address +
359: _ranges.v[rangeIndex].length +
360: page_size - 1) - srcAlign;
361:
362: /* Find some memory of the same size in kernel task. We use vm_allocate()
363: to do this. vm_allocate inserts the found memory object in the
364: target task's map as a side effect. */
365: krtn = vm_allocate( kernel_map,
366: &_kernPtrAligned,
367: _kernSize,
368: TRUE ); // Find first fit
369: assert(krtn == KERN_SUCCESS);
370: if(krtn) return;
371:
372: /* For each page in the area allocated from the kernel map,
373: find the physical address of the page.
374: Enter the page in the target task's pmap, at the
375: appropriate target task virtual address. */
376: for ( off = 0; off < _kernSize; off += page_size )
377: {
378: vm_offset_t kern_phys_addr, phys_addr;
379: if( _task)
380: phys_addr = pmap_extract( get_task_pmap(_task), srcAlign + off );
381: else
382: phys_addr = srcAlign + off;
383: assert(phys_addr);
384: if(phys_addr == 0) return;
385:
386: // Check original state.
387: kern_phys_addr = pmap_extract( kernel_pmap, _kernPtrAligned + off );
388: // Set virtual page to point to the right physical one
389: pmap_enter(
390: kernel_pmap,
391: _kernPtrAligned + off,
392: phys_addr,
393: VM_PROT_READ|VM_PROT_WRITE,
394: TRUE);
395: }
396: _kernPtr = _kernPtrAligned + (_ranges.v[rangeIndex].address - srcAlign);
397: _kernPtrAtIndex = rangeIndex;
398: }
399:
400: /*
401: * getDirection:
402: *
403: * Get the direction of the transfer.
404: */
405: IODirection IOMemoryDescriptor::getDirection() const
406: {
407: return _direction;
408: }
409:
410: /*
411: * getLength:
412: *
413: * Get the length of the transfer (over all ranges).
414: */
415: IOByteCount IOMemoryDescriptor::getLength() const
416: {
417: return _length;
418: }
419:
420: void IOMemoryDescriptor::setTag(
421: IOOptionBits tag )
422: {
423: _tag = tag;
424: }
425:
426: IOOptionBits IOMemoryDescriptor::getTag( void )
427: {
428: return( _tag);
429: }
430:
431: /*
432: * setPosition
433: *
434: * Set the logical start position inside the client buffer.
435: *
436: * It is convention that the position reflect the actual byte count that
437: * is successfully transferred into or out of the buffer, before the I/O
438: * request is "completed" (ie. sent back to its originator).
439: */
440:
441: void IOGeneralMemoryDescriptor::setPosition(IOByteCount position)
442: {
443: assert(position <= _length);
444:
445: if (position >= _length)
446: {
447: _position = _length;
448: _positionAtIndex = _rangesCount; /* careful: out-of-bounds */
449: _positionAtOffset = 0;
450: return;
451: }
452:
453: if (position < _position)
454: {
455: _positionAtOffset = position;
456: _positionAtIndex = 0;
457: }
458: else
459: {
460: _positionAtOffset += (position - _position);
461: }
462: _position = position;
463:
464: while (_positionAtOffset >= _ranges.v[_positionAtIndex].length)
465: {
466: _positionAtOffset -= _ranges.v[_positionAtIndex].length;
467: _positionAtIndex++;
468: }
469: }
470:
471: /*
472: * readBytes:
473: *
474: * Copy data from the memory descriptor's buffer into the specified buffer,
475: * relative to the current position. The memory descriptor's position is
476: * advanced based on the number of bytes copied.
477: */
478:
479: IOByteCount IOGeneralMemoryDescriptor::readBytes(IOByteCount offset,
480: void * bytes, IOByteCount withLength)
481: {
482: IOByteCount bytesLeft;
483: void * segment;
484: IOByteCount segmentLength;
485:
486: if( offset != _position)
487: setPosition( offset );
488:
489: withLength = min(withLength, _length - _position);
490: bytesLeft = withLength;
491:
492: #if 0
493: while (bytesLeft && (_position < _length))
494: {
495: /* Compute the relative length to the end of this virtual segment. */
496: segmentLength = min(_ranges.v[_positionAtIndex].length - _positionAtOffset, bytesLeft);
497:
498: /* Compute the relative address of this virtual segment. */
499: segment = (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset);
500:
501: if (KERN_SUCCESS != vm_map_read_user(get_task_map(_task),
502: /* from */ (vm_offset_t) segment, /* to */ (vm_offset_t) bytes,
503: /* size */ segmentLength))
504: {
505: assert( false );
506: bytesLeft = withLength;
507: break;
508: }
509: bytesLeft -= segmentLength;
510: offset += segmentLength;
511: setPosition(offset);
512: }
513: #else
514: while (bytesLeft && (segment = getVirtualSegment(offset, &segmentLength)))
515: {
516: segmentLength = min(segmentLength, bytesLeft);
517: bcopy(/* from */ segment, /* to */ bytes, /* size */ segmentLength);
518: bytesLeft -= segmentLength;
519: offset += segmentLength;
520: }
521: #endif
522:
523: return withLength - bytesLeft;
524: }
525:
526: /*
527: * writeBytes:
528: *
529: * Copy data to the memory descriptor's buffer from the specified buffer,
530: * relative to the current position. The memory descriptor's position is
531: * advanced based on the number of bytes copied.
532: */
533: IOByteCount IOGeneralMemoryDescriptor::writeBytes(IOByteCount offset,
534: const void* bytes,IOByteCount withLength)
535: {
536: IOByteCount bytesLeft;
537: void * segment;
538: IOByteCount segmentLength;
539:
540: if( offset != _position)
541: setPosition( offset );
542:
543: withLength = min(withLength, _length - _position);
544: bytesLeft = withLength;
545:
546: #if 0
547: while (bytesLeft && (_position < _length))
548: {
549: assert(_position <= _length);
550:
551: /* Compute the relative length to the end of this virtual segment. */
552: segmentLength = min(_ranges.v[_positionAtIndex].length - _positionAtOffset, bytesLeft);
553:
554: /* Compute the relative address of this virtual segment. */
555: segment = (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset);
556:
557: if (KERN_SUCCESS != vm_map_write_user(get_task_map(_task),
558: /* from */ (vm_offset_t) bytes,
559: /* to */ (vm_offset_t) segment,
560: /* size */ segmentLength))
561: {
562: assert( false );
563: bytesLeft = withLength;
564: break;
565: }
566: bytesLeft -= segmentLength;
567: offset += segmentLength;
568: setPosition(offset);
569: }
570: #else
571: while (bytesLeft && (segment = getVirtualSegment(offset, &segmentLength)))
572: {
573: segmentLength = min(segmentLength, bytesLeft);
574: bcopy(/* from */ bytes, /* to */ segment, /* size */ segmentLength);
575: bytesLeft -= segmentLength;
576: offset += segmentLength;
577: }
578: #endif
579:
580: return withLength - bytesLeft;
581: }
582:
583: /*
584: * getPhysicalSegment:
585: *
586: * Get the physical address of the buffer, relative to the current position.
587: * If the current position is at the end of the buffer, a zero is returned.
588: */
589: IOPhysicalAddress
590: IOGeneralMemoryDescriptor::getPhysicalSegment(IOByteCount offset,
591: IOByteCount * lengthOfSegment)
592: {
593: vm_address_t virtualAddress;
594: IOByteCount virtualLength;
595: pmap_t virtualPMap;
596: IOPhysicalAddress physicalAddress;
597: IOPhysicalLength physicalLength;
598:
599: if ((0 == _task) && (1 == _rangesCount))
600: {
601: assert(offset <= _length);
602: if (offset >= _length)
603: {
604: physicalAddress = 0;
605: physicalLength = 0;
606: }
607: else
608: {
609: physicalLength = _length - offset;
610: physicalAddress = offset + _ranges.v[0].address;
611: }
612:
613: if (lengthOfSegment)
614: *lengthOfSegment = physicalLength;
615: return physicalAddress;
616: }
617:
618: if( offset != _position)
619: setPosition( offset );
620:
621: assert(_position <= _length);
622:
623: /* Fail gracefully if the position is at (or past) the end-of-buffer. */
624: if (_position >= _length)
625: {
626: *lengthOfSegment = 0;
627: return 0;
628: }
629:
630: /* Prepare to compute the largest contiguous physical length possible. */
631:
632: virtualAddress = _ranges.v[_positionAtIndex].address + _positionAtOffset;
633: virtualLength = _ranges.v[_positionAtIndex].length - _positionAtOffset;
634: if( _task)
635: virtualPMap = get_task_pmap(_task);
636: else
637: virtualPMap = 0;
638:
639: physicalAddress = (virtualAddress == _cachedVirtualAddress) ?
640: _cachedPhysicalAddress : /* optimization */
641: virtualPMap ?
642: pmap_extract(virtualPMap, virtualAddress) :
643: virtualAddress;
644: physicalLength = trunc_page(physicalAddress) + page_size - physicalAddress;
645:
646: if (physicalAddress == 0) /* memory must be wired in order to proceed */
647: {
648: assert(physicalAddress);
649: *lengthOfSegment = 0;
650: return 0;
651: }
652:
653: /* Compute the largest contiguous physical length possible, within range. */
654: vm_address_t virtualPage = trunc_page(virtualAddress);
655: IOPhysicalAddress physicalPage = trunc_page(physicalAddress);
656:
657: while (physicalLength < virtualLength)
658: {
659: physicalPage += page_size;
660: virtualPage += page_size;
661: _cachedVirtualAddress = virtualPage;
662: _cachedPhysicalAddress = virtualPMap ?
663: pmap_extract(virtualPMap, virtualPage) :
664: virtualPage;
665:
666: if (_cachedPhysicalAddress != physicalPage) break;
667:
668: physicalLength += page_size;
669: }
670:
671: /* Clip contiguous physical length at the end of this range. */
672: if (physicalLength > virtualLength)
673: physicalLength = virtualLength;
674:
675: if( lengthOfSegment)
676: *lengthOfSegment = physicalLength;
677:
678: return physicalAddress;
679: }
680:
681:
682: /*
683: * getVirtualSegment:
684: *
685: * Get the virtual address of the buffer, relative to the current position.
686: * If the memory wasn't mapped into the caller's address space, it will be
687: * mapped in now. If the current position is at the end of the buffer, a
688: * null is returned.
689: */
690: void * IOGeneralMemoryDescriptor::getVirtualSegment(IOByteCount offset,
691: IOByteCount * lengthOfSegment)
692: {
693: if( offset != _position)
694: setPosition( offset );
695:
696: assert(_position <= _length);
697:
698: /* Fail gracefully if the position is at (or past) the end-of-buffer. */
699: if (_position >= _length)
700: {
701: *lengthOfSegment = 0;
702: return 0;
703: }
704:
705: /* Compute the relative length to the end of this virtual segment. */
706: *lengthOfSegment = _ranges.v[_positionAtIndex].length - _positionAtOffset;
707:
708: /* Compute the relative address of this virtual segment. */
709: if (_task == kernel_task)
710: return (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset);
711: else
712: {
713: mapIntoKernel(_positionAtIndex);
714: return (void *)(_kernPtr + _positionAtOffset);
715: }
716: }
717:
718: /*
719: * prepare
720: *
721: * Prepare the memory for an I/O transfer. This involves paging in
722: * the memory, if necessary, and wiring it down for the duration of
723: * the transfer. The complete() method completes the processing of
724: * the memory after the I/O transfer finishes. This method needn't
725: * called for non-pageable memory.
726: */
727: IOReturn IOGeneralMemoryDescriptor::prepare(
728: IODirection forDirection = kIODirectionNone)
729: {
730: IOReturn rc = kIOReturnSuccess;
731:
732: _wireCount++;
733: if(_task && (_task != kernel_task) && (_wireCount == 1)) {
734: UInt rangeIndex;
735: kern_return_t rc;
736: vm_prot_t access = VM_PROT_DEFAULT; // Could be cleverer using _direction
737:
738: //
739: // Check user read/write access to the data buffer.
740: //
741:
742: for (rangeIndex = 0; rangeIndex < _rangesCount; rangeIndex++)
743: {
744: vm_offset_t checkBase = trunc_page(_ranges.v[rangeIndex].address);
745: vm_size_t checkSize = round_page(_ranges.v[rangeIndex].length );
746:
747: while (checkSize)
748: {
749: vm_region_basic_info_data_t regionInfo;
750: mach_msg_type_number_t regionInfoSize = sizeof(regionInfo);
751: vm_size_t regionSize;
752:
753: if ( (vm_region(
754: /* map */ get_task_map(_task),
755: /* address */ &checkBase,
756: /* size */ ®ionSize,
757: /* flavor */ VM_REGION_BASIC_INFO,
758: /* info */ (vm_region_info_t) ®ionInfo,
759: /* info size */ ®ionInfoSize,
760: /* object name */ 0 ) != KERN_SUCCESS ) ||
761: ( (_direction & kIODirectionIn ) &&
762: !(regionInfo.protection & VM_PROT_WRITE) ) ||
763: ( (_direction & kIODirectionOut) &&
764: !(regionInfo.protection & VM_PROT_READ ) ) )
765: {
766: return kIOReturnVMError;
767: }
768:
769: assert((regionSize & PAGE_MASK) == 0);
770:
771: regionSize = min(regionSize, checkSize);
772: checkSize -= regionSize;
773: checkBase += regionSize;
774: } // (for each vm region)
775: } // (for each io range)
776:
777: for(rangeIndex = 0; rangeIndex < _rangesCount; rangeIndex++) {
778:
779: vm_offset_t srcAlign = trunc_page(_ranges.v[rangeIndex].address);
780: IOByteCount srcAlignEnd = trunc_page(_ranges.v[rangeIndex].address +
781: _ranges.v[rangeIndex].length +
782: page_size - 1);
783: rc = vm_map_wire(get_task_map(_task), srcAlign,
784: srcAlignEnd, access, FALSE);
785: if(rc != KERN_SUCCESS) {
786: UInt doneIndex;
787: IOLog("IOMemoryDescriptor::prepare: vm_map_wire failed: %d\n", rc);
788: for(doneIndex = 0; doneIndex < rangeIndex; doneIndex++) {
789: vm_offset_t srcAlign = trunc_page(_ranges.v[doneIndex].address);
790: IOByteCount srcAlignEnd = trunc_page(_ranges.v[doneIndex].address +
791: _ranges.v[doneIndex].length +
792: page_size - 1);
793: vm_map_unwire(get_task_map(_task), srcAlign,
794: srcAlignEnd, FALSE);
795: }
796: _wireCount = 0; // Back to unwired state now.
797: }
798: }
799: }
800: return rc;
801: }
802:
803: /*
804: * complete
805: *
806: * Complete processing of the memory after an I/O transfer finishes.
807: * This method should not be called unless a prepare was previously
808: * issued; the prepare() and complete() must occur in pairs, before
809: * before and after an I/O transfer involving pageable memory.
810: */
811: IOReturn IOGeneralMemoryDescriptor::complete(
812: IODirection forDirection = kIODirectionNone)
813: {
814: assert(_wireCount);
815: _wireCount--;
816: if(_task && (_task != kernel_task) && (_wireCount == 0)) {
817: UInt rangeIndex;
818: kern_return_t rc;
819: for(rangeIndex = 0; rangeIndex < _rangesCount; rangeIndex++) {
820:
821: vm_offset_t srcAlign = trunc_page(_ranges.v[rangeIndex].address);
822: IOByteCount srcAlignEnd = trunc_page(_ranges.v[rangeIndex].address +
823: _ranges.v[rangeIndex].length +
824: page_size - 1);
825: rc = vm_map_unwire(get_task_map(_task), srcAlign,
826: srcAlignEnd, FALSE);
827: if(rc != KERN_SUCCESS)
828: IOLog("IOMemoryDescriptor::complete: vm_map_unwire failed: %d\n", rc);
829: }
830: }
831: return kIOReturnSuccess;
832: }
833:
834: IOReturn IOGeneralMemoryDescriptor::doMap(
835: task_t addressTask,
836: IOVirtualAddress * atAddress,
837: IOOptionBits options,
838: IOByteCount sourceOffset = 0,
839: IOByteCount length = 0 )
840: {
841: // could be much better
842: if( (addressTask == _task) && (options & kIOMapAnywhere)
843: && (1 == _rangesCount) && (0 == sourceOffset)
844: && (length <= _ranges.v[0].length) ) {
845: *atAddress = _ranges.v[0].address;
846: return( kIOReturnSuccess );
847: }
848:
849: return( super::doMap( addressTask, atAddress,
850: options, sourceOffset, length ));
851: }
852:
853: IOReturn IOGeneralMemoryDescriptor::doUnmap(
854: task_t addressTask,
855: IOVirtualAddress logical,
856: IOByteCount length )
857: {
858: // could be much better
859: if( (addressTask == _task) && (1 == _rangesCount)
860: && (logical == _ranges.v[0].address)
861: && (length <= _ranges.v[0].length) )
862: return( kIOReturnSuccess );
863:
864: return( super::doUnmap( addressTask, logical, length ));
865: }
866:
867: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
868:
869: extern "C" {
870: // osfmk/device/iokit_rpc.c
871: extern kern_return_t IOMapPages(vm_map_t map, vm_offset_t va, vm_offset_t pa,
872: vm_size_t length, unsigned int mapFlags);
873: };
874:
875: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
876:
877: static IOLock * gIOMemoryLock;
878:
879: #define LOCK IOTakeLock( gIOMemoryLock)
880: #define UNLOCK IOUnlock( gIOMemoryLock)
881:
882: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
883:
884: OSDefineMetaClass( IOMemoryMap, OSObject )
885: OSDefineAbstractStructors( IOMemoryMap, OSObject )
886:
887: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
888:
889: class _IOMemoryMap : public IOMemoryMap
890: {
891: OSDeclareDefaultStructors(_IOMemoryMap)
892:
893: IOMemoryDescriptor * memory;
894: IOMemoryMap * superMap;
895: IOByteCount offset;
896: IOByteCount length;
897: IOVirtualAddress logical;
898: task_t addressTask;
899: IOOptionBits options;
900:
901: public:
902: virtual void free();
903:
904: // IOMemoryMap methods
905: virtual IOVirtualAddress getVirtualAddress();
906: virtual IOByteCount getLength();
907: virtual task_t getAddressTask();
908: virtual IOMemoryDescriptor * getMemoryDescriptor();
909: virtual IOOptionBits getMapOptions();
910:
911: virtual IOReturn unmap();
912:
913: virtual IOPhysicalAddress getPhysicalSegment(IOByteCount offset,
914: IOByteCount * length);
915:
916: // for IOMemoryDescriptor use
917: _IOMemoryMap * isCompatible(
918: IOMemoryDescriptor * owner,
919: task_t task,
920: IOVirtualAddress toAddress,
921: IOOptionBits options,
922: IOByteCount offset,
923: IOByteCount length );
924:
925: bool _IOMemoryMap::init(
926: IOMemoryDescriptor * memory,
927: IOMemoryMap * superMap,
928: IOByteCount offset,
929: IOByteCount length );
930:
931: bool _IOMemoryMap::init(
932: IOMemoryDescriptor * memory,
933: task_t intoTask,
934: IOVirtualAddress toAddress,
935: IOOptionBits options,
936: IOByteCount offset,
937: IOByteCount length );
938: };
939:
940: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
941:
942: #undef super
943: #define super IOMemoryMap
944:
945: OSDefineMetaClassAndStructors(_IOMemoryMap, IOMemoryMap)
946:
947: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
948:
949: bool _IOMemoryMap::init(
950: IOMemoryDescriptor * _memory,
951: IOMemoryMap * _superMap,
952: IOByteCount _offset,
953: IOByteCount _length )
954: {
955:
956: if( !super::init())
957: return( false);
958:
959: if( (_offset + _length) > _superMap->getLength())
960: return( false);
961:
962: _memory->retain();
963: memory = _memory;
964: _superMap->retain();
965: superMap = _superMap;
966:
967: offset = _offset;
968: if( _length)
969: length = _length;
970: else
971: length = _memory->getLength();
972:
973: options = superMap->getMapOptions();
974: addressTask = superMap->getAddressTask();
975: logical = superMap->getVirtualAddress() + offset;
976:
977: return( true );
978: }
979:
980: bool _IOMemoryMap::init(
981: IOMemoryDescriptor * _memory,
982: task_t intoTask,
983: IOVirtualAddress toAddress,
984: IOOptionBits _options,
985: IOByteCount _offset,
986: IOByteCount _length )
987: {
988: bool ok;
989:
990: if( (!_memory) || !super::init())
991: return( false);
992:
993: if( (_offset + _length) > _memory->getLength())
994: return( false);
995:
996: _memory->retain();
997: memory = _memory;
998:
999: offset = _offset;
1000: if( _length)
1001: length = _length;
1002: else
1003: length = _memory->getLength();
1004:
1005: addressTask = intoTask;
1006: logical = toAddress;
1007: options = _options;
1008:
1009: if( options & kIOMapStatic)
1010: ok = true;
1011: else
1012: ok = (kIOReturnSuccess == memory->doMap( addressTask, &logical,
1013: options, offset, length ));
1014: if( !ok)
1015: logical = 0;
1016:
1017: return( ok );
1018: }
1019:
1020: // documentation lies
1021: #define VM_ALLOCATE_ANYWHERE TRUE
1022: #define VM_ALLOCATE_RESERVED FALSE
1023:
1024: IOReturn IOMemoryDescriptor::doMap(
1025: task_t addressTask,
1026: IOVirtualAddress * atAddress,
1027: IOOptionBits options,
1028: IOByteCount sourceOffset = 0,
1029: IOByteCount length = 0 )
1030: {
1031: IOReturn err = kIOReturnSuccess;
1032: vm_size_t ourSize;
1033: vm_size_t bytes;
1034: vm_offset_t mapped;
1035: vm_address_t logical;
1036: IOByteCount pageOffset;
1037: IOPhysicalLength segLen;
1038: IOPhysicalAddress physAddr;
1039:
1040: if( 0 == length)
1041: length = getLength();
1042:
1043: physAddr = getPhysicalSegment( sourceOffset, &segLen );
1044: assert( physAddr );
1045:
1046: pageOffset = physAddr - trunc_page( physAddr );
1047: ourSize = length + pageOffset;
1048: physAddr -= pageOffset;
1049:
1050: logical = *atAddress;
1051: if( 0 == (options & kIOMapAnywhere)) {
1052: mapped = trunc_page( logical );
1053: if( (logical - mapped) != pageOffset)
1054: err = kIOReturnVMError;
1055: }
1056: if( kIOReturnSuccess == err)
1057: err = vm_allocate( get_task_map(addressTask), &mapped, ourSize,
1058: (options & kIOMapAnywhere)
1059: ? VM_ALLOCATE_ANYWHERE : VM_ALLOCATE_RESERVED);
1060:
1061: if( err) {
1062: kprintf("IOMemoryDescriptor::doMap: vm_allocate()"
1063: " returned %08x\n", err);
1064: return( err);
1065: }
1066: logical = mapped;
1067: *atAddress = mapped + pageOffset;
1068:
1069: segLen += pageOffset;
1070: bytes = ourSize;
1071: do {
1072: // in the middle of the loop only map whole pages
1073: if( segLen >= bytes)
1074: segLen = bytes;
1075: else if( segLen != trunc_page( segLen))
1076: err = kIOReturnVMError;
1077: if( physAddr != trunc_page( physAddr))
1078: err = kIOReturnBadArgument;
1079:
1080: #ifdef DEBUG
1081: if( kIOLogMapping & gIOKitDebug)
1082: kprintf("_IOMemoryMap::map(%x) %08x->%08x:%08x\n",
1083: addressTask, mapped + pageOffset, physAddr + pageOffset,
1084: segLen - pageOffset);
1085: #endif
1086:
1087: if( kIOReturnSuccess == err)
1088: err = IOMapPages( get_task_map(addressTask), mapped, physAddr, segLen, options );
1089: if( err)
1090: break;
1091:
1092: sourceOffset += segLen - pageOffset;
1093: mapped += segLen;
1094: bytes -= segLen;
1095: pageOffset = 0;
1096:
1097: } while( bytes
1098: && (physAddr = getPhysicalSegment( sourceOffset, &segLen )));
1099:
1100: if( bytes)
1101: err = kIOReturnBadArgument;
1102: if( err)
1103: doUnmap( addressTask, logical, ourSize );
1104: else
1105: mapped = true;
1106:
1107: return( err );
1108: }
1109:
1110: IOReturn IOMemoryDescriptor::doUnmap(
1111: task_t addressTask,
1112: IOVirtualAddress logical,
1113: IOByteCount length )
1114: {
1115: IOReturn err;
1116:
1117: #ifdef DEBUG
1118: if( kIOLogMapping & gIOKitDebug)
1119: kprintf("IOMemoryDescriptor::doUnmap(%x) %08x:%08x\n",
1120: addressTask, logical, length );
1121: #endif
1122: err = vm_deallocate( get_task_map(addressTask), logical, length );
1123: assert( err == kIOReturnSuccess );
1124:
1125: return( err );
1126: }
1127:
1128: IOReturn _IOMemoryMap::unmap( void )
1129: {
1130: IOReturn err;
1131:
1132: if( logical && (0 == superMap)
1133: && (0 == (options & kIOMapStatic))) {
1134:
1135: err = memory->doUnmap( addressTask, logical, length );
1136: logical = 0;
1137:
1138: } else
1139: err = kIOReturnSuccess;
1140:
1141: return( err );
1142: }
1143:
1144: void _IOMemoryMap::free()
1145: {
1146: unmap();
1147:
1148: if( memory) {
1149: LOCK;
1150: memory->removeMapping( this);
1151: UNLOCK;
1152: memory->release();
1153: }
1154:
1155: if( superMap)
1156: superMap->release();
1157:
1158: super::free();
1159: }
1160:
1161: IOByteCount _IOMemoryMap::getLength()
1162: {
1163: return( length );
1164: }
1165:
1166: IOVirtualAddress _IOMemoryMap::getVirtualAddress()
1167: {
1168: return( logical);
1169: }
1170:
1171: task_t _IOMemoryMap::getAddressTask()
1172: {
1173: return( addressTask);
1174: }
1175:
1176: IOOptionBits _IOMemoryMap::getMapOptions()
1177: {
1178: return( options);
1179: }
1180:
1181: IOMemoryDescriptor * _IOMemoryMap::getMemoryDescriptor()
1182: {
1183: return( memory );
1184: }
1185:
1186: _IOMemoryMap * _IOMemoryMap::isCompatible(
1187: IOMemoryDescriptor * owner,
1188: task_t task,
1189: IOVirtualAddress toAddress,
1190: IOOptionBits _options,
1191: IOByteCount _offset,
1192: IOByteCount _length )
1193: {
1194: _IOMemoryMap * mapping;
1195:
1196: if( addressTask != task)
1197: return( 0 );
1198: if( (options ^ _options) & (kIOMapCacheMask | kIOMapReadOnly))
1199: return( 0 );
1200:
1201: if( (0 == (_options & kIOMapAnywhere)) && (logical != toAddress))
1202: return( 0 );
1203:
1204: if( _offset < offset)
1205: return( 0 );
1206:
1207: _offset -= offset;
1208:
1209: if( (_offset + _length) > length)
1210: return( 0 );
1211:
1212: if( (length == _length) && (!_offset)) {
1213: retain();
1214: mapping = this;
1215:
1216: } else {
1217: mapping = new _IOMemoryMap;
1218: if( mapping
1219: && !mapping->init( owner, this, _offset, _length )) {
1220: mapping->release();
1221: mapping = 0;
1222: }
1223: }
1224:
1225: return( mapping );
1226: }
1227:
1228: IOPhysicalAddress _IOMemoryMap::getPhysicalSegment( IOByteCount _offset,
1229: IOPhysicalLength * length)
1230: {
1231: IOPhysicalAddress address;
1232:
1233: LOCK;
1234: address = memory->getPhysicalSegment( offset + _offset, length );
1235: UNLOCK;
1236:
1237: return( address );
1238: }
1239:
1240: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1241:
1242: #undef super
1243: #define super OSObject
1244:
1245: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1246:
1247: void IOMemoryDescriptor::initialize( void )
1248: {
1249: if( 0 == gIOMemoryLock)
1250: gIOMemoryLock = IOLockAlloc();
1251: }
1252:
1253: void IOMemoryDescriptor::free( void )
1254: {
1255: if( _mappings)
1256: _mappings->release();
1257:
1258: super::free();
1259: }
1260:
1261: IOMemoryMap * IOMemoryDescriptor::setMapping(
1262: task_t intoTask,
1263: IOVirtualAddress mapAddress,
1264: IOOptionBits options = 0 )
1265: {
1266: _IOMemoryMap * map;
1267:
1268: map = new _IOMemoryMap;
1269:
1270: LOCK;
1271:
1272: if( map
1273: && !map->init( this, intoTask, mapAddress,
1274: options | kIOMapStatic, 0, getLength() )) {
1275: map->release();
1276: map = 0;
1277: }
1278:
1279: addMapping( map);
1280:
1281: UNLOCK;
1282:
1283: return( map);
1284: }
1285:
1286: IOMemoryMap * IOMemoryDescriptor::map(
1287: IOOptionBits options = 0 )
1288: {
1289:
1290: return( makeMapping( this, kernel_task, 0,
1291: options | kIOMapAnywhere,
1292: 0, getLength() ));
1293: }
1294:
1295: IOMemoryMap * IOMemoryDescriptor::map(
1296: task_t intoTask,
1297: IOVirtualAddress toAddress,
1298: IOOptionBits options,
1299: IOByteCount offset = 0,
1300: IOByteCount length = 0 )
1301: {
1302: if( 0 == length)
1303: length = getLength();
1304:
1305: return( makeMapping( this, intoTask, toAddress, options, offset, length ));
1306: }
1307:
1308: IOMemoryMap * IOMemoryDescriptor::makeMapping(
1309: IOMemoryDescriptor * owner,
1310: task_t intoTask,
1311: IOVirtualAddress toAddress,
1312: IOOptionBits options,
1313: IOByteCount offset,
1314: IOByteCount length )
1315: {
1316: _IOMemoryMap * mapping = 0;
1317: OSIterator * iter;
1318:
1319: LOCK;
1320:
1321: do {
1322: // look for an existing mapping
1323: if( (iter = OSCollectionIterator::withCollection( _mappings))) {
1324:
1325: while( (mapping = (_IOMemoryMap *) iter->getNextObject())) {
1326:
1327: if( (mapping = mapping->isCompatible(
1328: owner, intoTask, toAddress,
1329: options | kIOMapReference,
1330: offset, length )))
1331: break;
1332: }
1333: iter->release();
1334: if( mapping)
1335: continue;
1336: }
1337:
1338:
1339: if( mapping || (options & kIOMapReference))
1340: continue;
1341:
1342: owner = this;
1343:
1344: mapping = new _IOMemoryMap;
1345: if( mapping
1346: && !mapping->init( owner, intoTask, toAddress, options,
1347: offset, length )) {
1348:
1349: IOLog("Didn't make map %08lx : %08lx\n", offset, length );
1350: mapping->release();
1351: mapping = 0;
1352: }
1353:
1354: } while( false );
1355:
1356: owner->addMapping( mapping);
1357:
1358: UNLOCK;
1359:
1360: return( mapping);
1361: }
1362:
1363: void IOMemoryDescriptor::addMapping(
1364: IOMemoryMap * mapping )
1365: {
1366: if( mapping) {
1367: if( 0 == _mappings)
1368: _mappings = OSSet::withCapacity(1);
1369: if( _mappings && _mappings->setObject( mapping ))
1370: mapping->release(); /* really */
1371: }
1372: }
1373:
1374: void IOMemoryDescriptor::removeMapping(
1375: IOMemoryMap * mapping )
1376: {
1377:
1378: assert( _mappings );
1379: assert( _mappings->containsObject( mapping ) );
1380:
1381: mapping->retain();
1382: mapping->retain();
1383: if( _mappings)
1384: _mappings->removeObject( mapping);
1385: }
1386:
1387: // a minimalist serializer
1388: bool IOMemoryDescriptor::serialize(OSSerialize *s) const
1389: {
1390: IOMemoryDescriptor * self = (IOMemoryDescriptor *) this;
1391: OSNumber * off;
1392: bool ok = false;
1393:
1394: if( s->previouslySerialized(this)) return true;
1395:
1396: off = OSNumber::withNumber(self->getPhysicalAddress(), IOPhysSize);
1397: if( off)
1398: ok = off->serialize(s);
1399: if (off)
1400: off->release();
1401:
1402: return ok;
1403: }
1404:
1405: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1406:
1407: #undef super
1408: #define super IOMemoryDescriptor
1409:
1410: OSDefineMetaClassAndStructors(IOSubMemoryDescriptor, IOMemoryDescriptor)
1411:
1412: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1413:
1414: bool IOSubMemoryDescriptor::initSubRange( IOMemoryDescriptor * parent,
1415: IOByteCount offset, IOByteCount length,
1416: IODirection withDirection )
1417: {
1418: if( !super::init())
1419: return( false );
1420:
1421: if( !parent)
1422: return( false);
1423:
1424: if( (offset + length) > parent->getLength())
1425: return( false);
1426:
1427: parent->retain();
1428: _parent = parent;
1429: _start = offset;
1430: _length = length;
1431: _direction = withDirection;
1432: _tag = parent->getTag();
1433:
1434: return( true );
1435: }
1436:
1437: void IOSubMemoryDescriptor::free( void )
1438: {
1439: if( _parent)
1440: _parent->release();
1441:
1442: super::free();
1443: }
1444:
1445:
1446: IOPhysicalAddress IOSubMemoryDescriptor::getPhysicalSegment( IOByteCount offset,
1447: IOByteCount * length )
1448: {
1449: IOPhysicalAddress address;
1450: IOByteCount actualLength;
1451:
1452: assert(offset <= _length);
1453:
1454: if( length)
1455: *length = 0;
1456:
1457: if( offset >= _length)
1458: return( 0 );
1459:
1460: address = _parent->getPhysicalSegment( offset + _start, &actualLength );
1461:
1462: if( address && length)
1463: *length = min( _length - offset, actualLength );
1464:
1465: return( address );
1466: }
1467:
1468: void * IOSubMemoryDescriptor::getVirtualSegment(IOByteCount offset,
1469: IOByteCount * lengthOfSegment)
1470: {
1471: return( 0 );
1472: }
1473:
1474: IOByteCount IOSubMemoryDescriptor::readBytes(IOByteCount offset,
1475: void * bytes, IOByteCount withLength)
1476: {
1477: IOByteCount byteCount;
1478:
1479: assert(offset <= _length);
1480:
1481: if( offset >= _length)
1482: return( 0 );
1483:
1484: LOCK;
1485: byteCount = _parent->readBytes( _start + offset, bytes,
1486: min(withLength, _length - offset) );
1487: UNLOCK;
1488:
1489: return( byteCount );
1490: }
1491:
1492: IOByteCount IOSubMemoryDescriptor::writeBytes(IOByteCount offset,
1493: const void* bytes, IOByteCount withLength)
1494: {
1495: IOByteCount byteCount;
1496:
1497: assert(offset <= _length);
1498:
1499: if( offset >= _length)
1500: return( 0 );
1501:
1502: LOCK;
1503: byteCount = _parent->writeBytes( _start + offset, bytes,
1504: min(withLength, _length - offset) );
1505: UNLOCK;
1506:
1507: return( byteCount );
1508: }
1509:
1510: IOReturn IOSubMemoryDescriptor::prepare(
1511: IODirection forDirection = kIODirectionNone)
1512: {
1513: IOReturn err;
1514:
1515: LOCK;
1516: err = _parent->prepare( forDirection);
1517: UNLOCK;
1518:
1519: return( err );
1520: }
1521:
1522: IOReturn IOSubMemoryDescriptor::complete(
1523: IODirection forDirection = kIODirectionNone)
1524: {
1525: IOReturn err;
1526:
1527: LOCK;
1528: err = _parent->complete( forDirection);
1529: UNLOCK;
1530:
1531: return( err );
1532: }
1533:
1534: IOMemoryMap * IOSubMemoryDescriptor::makeMapping(
1535: IOMemoryDescriptor * owner,
1536: task_t intoTask,
1537: IOVirtualAddress toAddress,
1538: IOOptionBits options,
1539: IOByteCount offset,
1540: IOByteCount length )
1541: {
1542: IOMemoryMap * mapping;
1543:
1544: mapping = (IOMemoryMap *) _parent->makeMapping(
1545: _parent, intoTask,
1546: toAddress - (_start + offset),
1547: options | kIOMapReference,
1548: _start + offset, length );
1549:
1550: if( !mapping)
1551: mapping = super::makeMapping( owner, intoTask, toAddress, options,
1552: offset, length );
1553:
1554: return( mapping );
1555: }
1556:
1557: /* ick */
1558:
1559: bool
1560: IOSubMemoryDescriptor::initWithAddress(void * address,
1561: IOByteCount withLength,
1562: IODirection withDirection)
1563: {
1564: return( false );
1565: }
1566:
1567: bool
1568: IOSubMemoryDescriptor::initWithAddress(vm_address_t address,
1569: IOByteCount withLength,
1570: IODirection withDirection,
1571: task_t withTask)
1572: {
1573: return( false );
1574: }
1575:
1576: bool
1577: IOSubMemoryDescriptor::initWithPhysicalAddress(
1578: IOPhysicalAddress address,
1579: IOByteCount withLength,
1580: IODirection withDirection )
1581: {
1582: return( false );
1583: }
1584:
1585: bool
1586: IOSubMemoryDescriptor::initWithRanges(
1587: IOVirtualRange * ranges,
1588: UInt32 withCount,
1589: IODirection withDirection,
1590: task_t withTask,
1591: bool asReference = false)
1592: {
1593: return( false );
1594: }
1595:
1596: bool
1597: IOSubMemoryDescriptor::initWithPhysicalRanges( IOPhysicalRange * ranges,
1598: UInt32 withCount,
1599: IODirection withDirection,
1600: bool asReference = false)
1601: {
1602: return( false );
1603: }
1604:
1605: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.