The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IOMultiMemoryDescriptor.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 
   29 #include <IOKit/IOLib.h>
   30 #include <IOKit/IOMultiMemoryDescriptor.h>
   31 
   32 #define super IOMemoryDescriptor
   33 OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor, IOMemoryDescriptor)
   34 
   35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   36 
   37 bool IOMultiMemoryDescriptor::initWithAddress(
   38                                   void *      /* address       */ ,
   39                                   IOByteCount /* withLength    */ ,
   40                                   IODirection /* withDirection */ )
   41 {
   42     return false;
   43 }
   44 
   45 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   46 
   47 bool IOMultiMemoryDescriptor::initWithAddress(
   48                                   vm_address_t /* address       */ ,
   49                                   IOByteCount  /* withLength    */ ,
   50                                   IODirection  /* withDirection */ ,
   51                                   task_t       /* withTask      */ )
   52 {
   53     return false;
   54 }
   55 
   56 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   57 
   58 bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
   59                                   IOPhysicalAddress /* address       */ ,
   60                                   IOByteCount       /* withLength    */ ,
   61                                   IODirection       /* withDirection */ )
   62 {
   63     return false;
   64 }
   65 
   66 
   67 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   68 
   69 bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
   70                                   IOPhysicalRange * /* ranges        */ ,
   71                                   UInt32            /* withCount     */ ,
   72                                   IODirection       /* withDirection */ ,
   73                                   bool              /* asReference   */ )
   74 {
   75     return false;
   76 }
   77 
   78 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   79 
   80 bool IOMultiMemoryDescriptor::initWithRanges(
   81                                   IOVirtualRange * /* ranges        */ ,
   82                                   UInt32           /* withCount     */ ,
   83                                   IODirection      /* withDirection */ ,
   84                                   task_t           /* withTask      */ ,
   85                                   bool             /* asReference   */ )
   86 {
   87     return false;
   88 }
   89 
   90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   91 
   92 IOMultiMemoryDescriptor * IOMultiMemoryDescriptor::withDescriptors(
   93                                   IOMemoryDescriptor ** descriptors,
   94                                   UInt32                withCount,
   95                                   IODirection           withDirection,
   96                                   bool                  asReference )
   97 {
   98     //
   99     // Create a new IOMultiMemoryDescriptor.  The "buffer" is made up of several
  100     // memory descriptors, that are to be chained end-to-end to make up a single
  101     // memory descriptor.
  102     //
  103     // Passing the ranges as a reference will avoid an extra allocation.
  104     //
  105 
  106     IOMultiMemoryDescriptor * me = new IOMultiMemoryDescriptor;
  107     
  108     if ( me && me->initWithDescriptors(
  109                                   /* descriptors   */ descriptors,
  110                                   /* withCount     */ withCount,
  111                                   /* withDirection */ withDirection,
  112                                   /* asReference   */ asReference ) == false )
  113     {
  114             me->release();
  115             me = 0;
  116     }
  117 
  118     return me;
  119 }
  120 
  121 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  122 
  123 bool IOMultiMemoryDescriptor::initWithDescriptors(
  124                                   IOMemoryDescriptor ** descriptors,
  125                                   UInt32                withCount,
  126                                   IODirection           withDirection,
  127                                   bool                  asReference )
  128 {
  129     //
  130     // Initialize an IOMultiMemoryDescriptor. The "buffer" is made up of several
  131     // memory descriptors, that are to be chained end-to-end to make up a single
  132     // memory descriptor.
  133     //
  134     // Passing the ranges as a reference will avoid an extra allocation.
  135     //
  136 
  137     assert(descriptors);
  138     assert(withCount);
  139 
  140     // Release existing descriptors, if any
  141     if ( _descriptors )
  142     {
  143         for ( unsigned index = 0; index < _descriptorsCount; index++ ) 
  144             _descriptors[index]->release();
  145 
  146         if ( _descriptorsIsAllocated )
  147             IODelete(_descriptors, IOMemoryDescriptor *, _descriptorsCount);
  148     } else {
  149         // Ask our superclass' opinion.
  150         if ( super::init() == false )  return false;
  151     }
  152     
  153     // Initialize our minimal state.
  154 
  155     _descriptors            = 0;
  156     _descriptorsCount       = withCount;
  157     _descriptorsIsAllocated = asReference ? false : true;
  158     _direction              = withDirection;
  159     _length                 = 0;
  160     _mappings               = 0;
  161     _tag                    = 0;
  162 
  163     if ( asReference )
  164     {
  165         _descriptors = descriptors;
  166     }
  167     else
  168     {
  169         _descriptors = IONew(IOMemoryDescriptor *, withCount);
  170         if ( _descriptors == 0 )  return false;
  171 
  172         bcopy( /* from  */ descriptors,
  173                /* to    */ _descriptors,
  174                /* bytes */ withCount * sizeof(IOMemoryDescriptor *) );
  175     }
  176 
  177     for ( unsigned index = 0; index < withCount; index++ ) 
  178     {
  179         descriptors[index]->retain();
  180         _length += descriptors[index]->getLength();
  181         if ( _tag == 0 )  _tag = descriptors[index]->getTag();
  182         assert(descriptors[index]->getDirection() == withDirection);
  183     }
  184 
  185     return true;
  186 }
  187 
  188 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  189 
  190 void IOMultiMemoryDescriptor::free()
  191 {
  192     //
  193     // Free all of this object's outstanding resources.
  194     //
  195 
  196     if ( _descriptors )
  197     {
  198         for ( unsigned index = 0; index < _descriptorsCount; index++ ) 
  199             _descriptors[index]->release();
  200 
  201         if ( _descriptorsIsAllocated )
  202             IODelete(_descriptors, IOMemoryDescriptor *, _descriptorsCount);
  203     }
  204 
  205     super::free();
  206 }
  207 
  208 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  209 
  210 IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection)
  211 {
  212     //
  213     // Prepare the memory for an I/O transfer.
  214     //
  215     // This involves paging in the memory and wiring it down for the duration
  216     // of the transfer.  The complete() method finishes the processing of the
  217     // memory after the I/O transfer finishes.
  218     //
  219 
  220     unsigned index;
  221     IOReturn status = kIOReturnInternalError;
  222     IOReturn statusUndo;
  223 
  224     if ( forDirection == kIODirectionNone )
  225     {
  226         forDirection = _direction;
  227     }
  228 
  229     for ( index = 0; index < _descriptorsCount; index++ ) 
  230     {
  231         status = _descriptors[index]->prepare(forDirection);
  232         if ( status != kIOReturnSuccess )  break;
  233     }
  234 
  235     if ( status != kIOReturnSuccess )
  236     {
  237         for ( unsigned indexUndo = 0; indexUndo <= index; indexUndo++ )
  238         {
  239             statusUndo = _descriptors[index]->complete(forDirection);
  240             assert(statusUndo == kIOReturnSuccess);
  241         }
  242     }
  243 
  244     return status;
  245 }
  246 
  247 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  248 
  249 IOReturn IOMultiMemoryDescriptor::complete(IODirection forDirection)
  250 {
  251     //
  252     // Complete processing of the memory after an I/O transfer finishes.
  253     //
  254     // This method shouldn't be called unless a prepare() was previously issued;
  255     // the prepare() and complete() must occur in pairs, before and after an I/O
  256     // transfer.
  257     //
  258 
  259     IOReturn status;
  260     IOReturn statusFinal = kIOReturnSuccess;
  261 
  262     if ( forDirection == kIODirectionNone )
  263     {
  264         forDirection = _direction;
  265     }
  266 
  267     for ( unsigned index = 0; index < _descriptorsCount; index++ ) 
  268     {
  269         status = _descriptors[index]->complete(forDirection);
  270         if ( status != kIOReturnSuccess )  statusFinal = status;
  271         assert(status == kIOReturnSuccess);
  272     }
  273 
  274     return statusFinal;
  275 }
  276 
  277 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  278 
  279 addr64_t IOMultiMemoryDescriptor::getPhysicalSegment64( 
  280                                     IOByteCount   offset, IOByteCount * length )
  281 {
  282     //
  283     // This method returns the physical address of the byte at the given offset
  284     // into the memory,  and optionally the length of the physically contiguous
  285     // segment from that offset.
  286     //
  287 
  288     assert(offset <= _length);
  289 
  290     for ( unsigned index = 0; index < _descriptorsCount; index++ ) 
  291     {
  292         if ( offset < _descriptors[index]->getLength() )
  293         {
  294             return _descriptors[index]->getPhysicalSegment64(offset, length);
  295         }
  296         offset -= _descriptors[index]->getLength();
  297     }
  298 
  299     if ( length )  *length = 0;
  300 
  301     return 0;
  302 }
  303 
  304 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  305 
  306 IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment( 
  307                                     IOByteCount   offset, IOByteCount * length )
  308 {
  309     //
  310     // This method returns the physical address of the byte at the given offset
  311     // into the memory,  and optionally the length of the physically contiguous
  312     // segment from that offset.
  313     //
  314 
  315     assert(offset <= _length);
  316 
  317     for ( unsigned index = 0; index < _descriptorsCount; index++ ) 
  318     {
  319         if ( offset < _descriptors[index]->getLength() )
  320         {
  321             return _descriptors[index]->getPhysicalSegment(offset, length);
  322         }
  323         offset -= _descriptors[index]->getLength();
  324     }
  325 
  326     if ( length )  *length = 0;
  327 
  328     return 0;
  329 }
  330 
  331 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  332 
  333 IOPhysicalAddress IOMultiMemoryDescriptor::getSourceSegment(
  334                                                        IOByteCount   offset,
  335                                                        IOByteCount * length )
  336 {
  337     //
  338     // This method returns the physical address of the byte at the given offset
  339     // into the memory,  and optionally the length of the physically contiguous
  340     // segment from that offset.
  341     //
  342 
  343     assert(offset <= _length);
  344 
  345     for ( unsigned index = 0; index < _descriptorsCount; index++ ) 
  346     {
  347         if ( offset < _descriptors[index]->getLength() )
  348         {
  349             return _descriptors[index]->getSourceSegment(offset, length);
  350         }
  351         offset -= _descriptors[index]->getLength();
  352     }
  353 
  354     if ( length )  *length = 0;
  355 
  356     return 0;
  357 }
  358 
  359 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  360 
  361 void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount   /* offset */ ,
  362                                                    IOByteCount * /* length */ )
  363 {
  364     return 0;
  365 }
  366 
  367 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  368 
  369 IOByteCount IOMultiMemoryDescriptor::readBytes( IOByteCount offset,
  370                                                 void *      bytes,
  371                                                 IOByteCount withLength )
  372 {
  373     //
  374     // Copies data from the memory descriptor's buffer at the given offset, to
  375     // the specified buffer.  Returns the number of bytes copied.
  376     //
  377 
  378     IOByteCount bytesCopied = 0;
  379     unsigned    index;
  380 
  381     for ( index = 0; index < _descriptorsCount; index++ ) 
  382     {
  383         if ( offset < _descriptors[index]->getLength() )  break;
  384         offset -= _descriptors[index]->getLength();
  385     }
  386 
  387     for ( ; index < _descriptorsCount && withLength; index++)
  388     {
  389         IOByteCount copy   = min(_descriptors[index]->getLength(), withLength);
  390         IOByteCount copied = _descriptors[index]->readBytes(offset,bytes,copy);
  391 
  392         bytesCopied += copied;
  393         if ( copied != copy )  break;
  394 
  395         bytes = ((UInt8 *) bytes) + copied;
  396         withLength -= copied;
  397         offset = 0;
  398     }
  399 
  400     return bytesCopied;
  401 }
  402 
  403 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  404 
  405 IOByteCount IOMultiMemoryDescriptor::writeBytes( IOByteCount  offset,
  406                                                  const void * bytes,
  407                                                  IOByteCount  withLength )
  408 {
  409     //
  410     // Copies data to the memory descriptor's buffer at the given offset, from
  411     // the specified buffer.  Returns the number of bytes copied.
  412     //
  413 
  414     IOByteCount bytesCopied = 0;
  415     unsigned    index;
  416 
  417     for ( index = 0; index < _descriptorsCount; index++ ) 
  418     {
  419         if ( offset < _descriptors[index]->getLength() )  break;
  420         offset -= _descriptors[index]->getLength();
  421     }
  422 
  423     for ( ; index < _descriptorsCount && withLength; index++)
  424     {
  425         IOByteCount copy   = min(_descriptors[index]->getLength(), withLength);
  426         IOByteCount copied = _descriptors[index]->writeBytes(offset,bytes,copy);
  427 
  428         bytesCopied += copied;
  429         if ( copied != copy )  break;
  430 
  431         bytes = ((UInt8 *) bytes) + copied;
  432         withLength -= copied;
  433         offset = 0;
  434     }
  435 
  436     return bytesCopied;
  437 }

Cache object: eaf01b7a6b544f484dbcc8f0b1d9356a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.