Annotation of XNU/iokit/Kernel/IOMemoryDescriptor.cpp, revision 1.1

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        */ &regionSize,
        !           757:                           /* flavor      */ VM_REGION_BASIC_INFO,
        !           758:                           /* info        */ (vm_region_info_t) &regionInfo,
        !           759:                           /* info size   */ &regionInfoSize,
        !           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: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.