Annotation of XNU/iokit/Kernel/IOMemoryDescriptor.cpp, revision 1.1.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.