Annotation of XNU/iokit/Kernel/IOBufferMemoryDescriptor.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: #include <IOKit/assert.h>
                     23: #include <IOKit/system.h>
                     24: 
                     25: #include <IOKit/IOLib.h>
                     26: #include <IOKit/IOBufferMemoryDescriptor.h>
                     27: 
                     28: #define super IOGeneralMemoryDescriptor
                     29: OSDefineMetaClassAndStructors(IOBufferMemoryDescriptor,
                     30:                                IOGeneralMemoryDescriptor);
                     31: 
                     32: /*
                     33:  * initWithCapacity:
                     34:  *
                     35:  * Initialize a new IOBufferMemoryDescriptor with a buffer large enough to
                     36:  * hold capacity bytes.  The descriptor's length is initially set to zero.
                     37:  */
                     38: bool IOBufferMemoryDescriptor::initWithCapacity(vm_size_t   inCapacity,
                     39:                                                 IODirection inDirection,
                     40:                                                 bool        inContiguous)
                     41: {
                     42:     if (!inCapacity)
                     43:         return false;
                     44: 
                     45:     /* Allocate a wired-down buffer inside kernel space. */
                     46:     _buffer       = (inContiguous) ?
                     47:                                IOMallocContiguous(inCapacity, inCapacity, 0) :
                     48:                                 IOMalloc(inCapacity);
                     49:     _contiguous   = inContiguous;
                     50:     _capacity     = inCapacity;
                     51:     _physAddrs    = 0;
                     52:     _physSegCount = 0;
                     53: 
                     54:     if (!_buffer)
                     55:         return false;
                     56: 
                     57:     if (!super::initWithAddress(_buffer, inCapacity, inDirection))
                     58:        return false;
                     59: 
                     60:     /* Precompute virtual-to-physical page mappings. */
                     61:     vm_address_t inBuffer = (vm_address_t) _buffer;
                     62:     _physSegCount = atop(trunc_page(inBuffer + inCapacity - 1) -
                     63:                          trunc_page(inBuffer)) + 1;
                     64:     _physAddrs = IONew(IOPhysicalAddress, _physSegCount);
                     65:     if (!_physAddrs)
                     66:        return false;
                     67: 
                     68:     inBuffer = trunc_page(inBuffer);
                     69:     for (unsigned i = 0; i < _physSegCount; i++) {
                     70:         _physAddrs[i] = pmap_extract(get_task_pmap(kernel_task), inBuffer);
                     71:         assert(_physAddrs[i]); /* supposed to be wired */
                     72:         inBuffer += page_size;
                     73:     }
                     74: 
                     75:     // start out with no data
                     76:     setLength(0);
                     77:     
                     78:     return true;
                     79: }
                     80: 
                     81: /*
                     82:  * withCapacity:
                     83:  *
                     84:  * Returns a new IOBufferMemoryDescriptor with a buffer large enough to
                     85:  * hold capacity bytes.  The descriptor's length is initially set to zero.
                     86:  */
                     87: IOBufferMemoryDescriptor *
                     88: IOBufferMemoryDescriptor::withCapacity(vm_size_t   inCapacity,
                     89:                                        IODirection inDirection,
                     90:                                        bool        inContiguous)
                     91: {
                     92:     IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor;
                     93:     
                     94:     if (me && !me->initWithCapacity(inCapacity, inDirection, inContiguous)) {
                     95:        me->release();
                     96:        me = 0;
                     97:     }
                     98:     return me;
                     99: }
                    100: 
                    101: /*
                    102:  * initWithBytes:
                    103:  *
                    104:  * Initialize a new IOBufferMemoryDescriptor preloaded with bytes (copied).
                    105:  * The descriptor's length and capacity are set to the input buffer's size.
                    106:  */
                    107: bool IOBufferMemoryDescriptor::initWithBytes(const void * inBytes,
                    108:                                              vm_size_t    inLength,
                    109:                                              IODirection  inDirection,
                    110:                                              bool         inContiguous)
                    111: {
                    112:     if (!initWithCapacity(inLength, inDirection, inContiguous))
                    113:         return false;
                    114: 
                    115:     if (!appendBytes(inBytes, inLength))
                    116:         return false;
                    117: 
                    118:     return true;
                    119: }
                    120: 
                    121: /*
                    122:  * withBytes:
                    123:  *
                    124:  * Returns a new IOBufferMemoryDescriptor preloaded with bytes (copied).
                    125:  * The descriptor's length and capacity are set to the input buffer's size.
                    126:  */
                    127: IOBufferMemoryDescriptor *
                    128: IOBufferMemoryDescriptor::withBytes(const void * inBytes,
                    129:                                     vm_size_t    inLength,
                    130:                                     IODirection  inDirection,
                    131:                                     bool         inContiguous)
                    132: {
                    133:     IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor;
                    134: 
                    135:     if (me && !me->initWithBytes(inBytes, inLength, inDirection, inContiguous)){
                    136:         me->release();
                    137:         me = 0;
                    138:     }
                    139:     return me;
                    140: }
                    141: 
                    142: /*
                    143:  * free:
                    144:  *
                    145:  * Free resources
                    146:  */
                    147: void IOBufferMemoryDescriptor::free()
                    148: {
                    149:     if (_physAddrs)
                    150:         IODelete(_physAddrs, IOPhysicalAddress, _physSegCount);
                    151: 
                    152:     super::free();
                    153: 
                    154:     if (_buffer) {
                    155:         if (_contiguous)
                    156:             IOFreeContiguous(_buffer, _capacity);
                    157:         else
                    158:             IOFree(_buffer, _capacity);
                    159:     }
                    160: }
                    161: 
                    162: /*
                    163:  * getCapacity:
                    164:  *
                    165:  * Get the buffer capacity
                    166:  */
                    167: vm_size_t IOBufferMemoryDescriptor::getCapacity() const
                    168: {
                    169:     return _capacity;
                    170: }
                    171: 
                    172: /*
                    173:  * setLength:
                    174:  *
                    175:  * Change the buffer length of the memory descriptor.  When a new buffer is
                    176:  * created with initWithBytes, the descriptor's length is set to capacity,
                    177:  * or its length is initially zero.  This method allows one to resize the
                    178:  * buffer length up to capacity or less.  This eliminates the need to
                    179:  * destroy and create new buffers when different sizes are needed.  The
                    180:  * descriptor position is implicitly reset to zero as a result of this call.
                    181:  */
                    182: void IOBufferMemoryDescriptor::setLength(vm_size_t length)
                    183: {
                    184:     assert(length <= _capacity);
                    185: 
                    186:     _length = length;
                    187:     _singleRange.v.length = length;
                    188: }
                    189: 
                    190: /*
                    191:  * setDirection:
                    192:  *
                    193:  * Change the direction of the transfer.  This method allows one to redirect
                    194:  * the descriptor's transfer direction.  This eliminates the need to destroy
                    195:  * and create new buffers when different transfer directions are needed.
                    196:  */
                    197: void IOBufferMemoryDescriptor::setDirection(IODirection direction)
                    198: {
                    199:     _direction = direction;
                    200: }
                    201: 
                    202: /*
                    203:  * appendBytes:
                    204:  *
                    205:  * Add some data to the end of the buffer.  This method automatically
                    206:  * maintains the memory descriptor buffer length.  Note that appendBytes
                    207:  * will not copy past the end of the memory descriptor's current capacity.
                    208:  */
                    209: bool
                    210: IOBufferMemoryDescriptor::appendBytes(const void * bytes, vm_size_t withLength)
                    211: {
                    212:     vm_size_t actualBytesToCopy = min(withLength, _capacity - _length);
                    213: 
                    214:     assert(_length <= _capacity);
                    215:     bcopy(/* from */ bytes, (void *)(_singleRange.v.address + _length),
                    216:           actualBytesToCopy);
                    217:     _length += actualBytesToCopy;
                    218:     _singleRange.v.length += actualBytesToCopy;
                    219: 
                    220:     return true;
                    221: }
                    222: 
                    223: /*
                    224:  * getBytesNoCopy:
                    225:  *
                    226:  * Return the virtual address of the beginning of the buffer
                    227:  */
                    228: void * IOBufferMemoryDescriptor::getBytesNoCopy()
                    229: {
                    230:     return (void *)_singleRange.v.address;
                    231: }
                    232: 
                    233: /*
                    234:  * getBytesNoCopy:
                    235:  *
                    236:  * Return the virtual address of an offset from the beginning of the buffer
                    237:  */
                    238: void *
                    239: IOBufferMemoryDescriptor::getBytesNoCopy(vm_size_t start, vm_size_t withLength)
                    240: {
                    241:     if (start < _length && (start + withLength) <= _length)
                    242:         return (void *)(_singleRange.v.address + start);
                    243:     return 0;
                    244: }
                    245: 
                    246: /*
                    247:  * getPhysicalSegment:
                    248:  *
                    249:  * Get the physical address of the buffer, relative to the current position.
                    250:  * If the current position is at the end of the buffer, a zero is returned.
                    251:  */
                    252: IOPhysicalAddress
                    253: IOBufferMemoryDescriptor::getPhysicalSegment(IOByteCount offset,
                    254:                                        IOPhysicalLength * lengthOfSegment)
                    255: {
                    256:     if( offset != _position)
                    257:        setPosition( offset );
                    258: 
                    259:     assert(_position <= _length);
                    260: 
                    261:     /* Fail gracefully if the position is at (or past) the end-of-buffer. */
                    262:     if (_position >= _length) {
                    263:         *lengthOfSegment = 0;
                    264:         return 0;
                    265:     }
                    266: 
                    267:     /* Compute the largest contiguous physical length possible. */
                    268:     vm_address_t actualPos  = _singleRange.v.address + _position;
                    269:     vm_address_t actualPage = trunc_page(actualPos);
                    270:     unsigned     physInd    = atop(actualPage-trunc_page(_singleRange.v.address));
                    271: 
                    272:     vm_size_t physicalLength = actualPage + page_size - actualPos;
                    273:     for (unsigned index = physInd + 1; index < _physSegCount &&
                    274:          _physAddrs[index] == _physAddrs[index-1] + page_size; index++) {
                    275:         physicalLength += page_size;
                    276:     }
                    277: 
                    278:     /* Clip contiguous physical length at the end-of-buffer. */
                    279:     if (physicalLength > _length - _position)
                    280:         physicalLength = _length - _position;
                    281: 
                    282:     *lengthOfSegment = physicalLength;
                    283:     return _physAddrs[physInd] + (actualPos - actualPage);
                    284: }

unix.superglobalmegacorp.com

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