X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4452a7af2eac33dbad800bcc91f2399d62c18f53..3e170ce000f1506b7b5d2c5c7faec85ceabb573d:/iokit/IOKit/IODMACommand.h diff --git a/iokit/IOKit/IODMACommand.h b/iokit/IOKit/IODMACommand.h index 56a36018f..54e0815bb 100644 --- a/iokit/IOKit/IODMACommand.h +++ b/iokit/IOKit/IODMACommand.h @@ -31,6 +31,7 @@ #include #include class IOMapper; +class IOBufferMemoryDescriptor; /**************************** class IODMACommand ***************************/ @@ -46,10 +47,26 @@ class IOMapper; The IODMACommand can be used in a 'weak-linked' manner. To do this you must avoid using any static member functions. Use the, much slower but safe, weakWithSpecification function. On success a dma command instance will be returned. This instance can then be used to clone as many commands as is needed. Remember deriving from this class can not be done weakly, that is no weak subclassing! */ + +enum +{ + kIODMAMapOptionMapped = 0x00000000, + kIODMAMapOptionBypassed = 0x00000001, + kIODMAMapOptionNonCoherent = 0x00000002, + kIODMAMapOptionUnmapped = 0x00000003, + kIODMAMapOptionTypeMask = 0x0000000f, + + kIODMAMapOptionNoCacheStore = 0x00000010, // Memory in descriptor + kIODMAMapOptionOnChip = 0x00000020, // Indicates DMA is on South Bridge + kIODMAMapOptionIterateOnly = 0x00000040 // DMACommand will be used as a cursor only +}; + class IODMACommand : public IOCommand { OSDeclareDefaultStructors(IODMACommand); +friend class IODMAEventSource; + public: /*! @@ -76,14 +93,25 @@ public: @constant kMaxMappingOptions Internal use only */ enum MappingOptions { - kMapped = 0x00000000, - kBypassed = 0x00000001, - kNonCoherent = 0x00000002, - kTypeMask = 0x0000000f, - - kNoCacheStore = 0x00000010, // Memory in descriptor - kOnChip = 0x00000020, // Indicates DMA is on South Bridge - kIterateOnly = 0x00000040 // DMACommand will be used as a cursor only + kMapped = kIODMAMapOptionMapped, + kBypassed = kIODMAMapOptionBypassed, + kNonCoherent = kIODMAMapOptionNonCoherent, + kUnmapped = kIODMAMapOptionUnmapped, + kTypeMask = kIODMAMapOptionTypeMask, + + kNoCacheStore = kIODMAMapOptionNoCacheStore, // Memory in descriptor + kOnChip = kIODMAMapOptionOnChip, // Indicates DMA is on South Bridge + kIterateOnly = kIODMAMapOptionIterateOnly // DMACommand will be used as a cursor only + }; + + struct SegmentOptions { + uint8_t fStructSize; + uint8_t fNumAddressBits; + uint64_t fMaxSegmentSize; + uint64_t fMaxTransferSize; + uint32_t fAlignment; + uint32_t fAlignmentLength; + uint32_t fAlignmentInternalSegments; }; /*! @enum SynchronizeOptions @@ -159,8 +187,8 @@ public: static bool OutputBig64(IODMACommand *target, Segment64 seg, void *segs, UInt32 ind); -/*! @defined kIODMACommandOutputLittle64 - @abstract Output little-endian Segment64 output segment function. +/*! @defined kIODMACommandOutputBig64 + @abstract Output big-endian Segment64 output segment function. */ #define kIODMACommandOutputBig64 (IODMACommand::OutputBig64) @@ -170,8 +198,8 @@ public: static bool OutputLittle64(IODMACommand *target, Segment64 seg, void *segs, UInt32 ind); -/*! @defined kIODMACommandOutputBig64 - @abstract Output big-endian Segment64 output segment function. +/*! @defined kIODMACommandOutputLittle64 + @abstract Output little-endian Segment64 output segment function. */ #define kIODMACommandOutputLittle64 (IODMACommand::OutputLittle64) @@ -185,7 +213,8 @@ public: @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. @param alignment Alignment restriction, in bytes, on I/O bus addresses. Defaults to single byte alignment. @param mapper For mapping types kMapped & kBypassed mapper is used to define the hardware that will perform the mapping, defaults to the system mapper. - @result Returns a new memory cursor if successfully created and initialized, 0 otherwise. + @param refCon Reference Constant + @result Returns a new IODMACommand if successfully created and initialized, 0 otherwise. */ static IODMACommand * withSpecification(SegmentFunction outSegFunc, @@ -208,6 +237,7 @@ public: @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. @param alignment Alignment restriction, in bytes, on I/O bus addresses. Defaults to single byte alignment. @param mapper For mapping types kMapped & kBypassed mapper is used to define the hardware that will perform the mapping, defaults to the system mapper. + @param refCon Reference Constant @result kIOReturnSuccess if everything is OK, otherwise kIOReturnBadArgument if newCommand is NULL, kIOReturnUnsupported if the kernel doesn't export IODMACommand or IOReturnError if the new command fails to init, q.v. initWithSpecification. */ // Note that the function has the attribute always_inline. @@ -226,11 +256,27 @@ public: IOMapper *mapper = 0, void *refCon = 0) __attribute__((always_inline)); + static IODMACommand * + withSpecification(SegmentFunction outSegFunc, + const SegmentOptions * segmentOptions, + uint32_t mappingOptions, + IOMapper * mapper, + void * refCon); + + +/*! @function withRefCon + @abstract Creates and initializes an unspecified IODMACommand. + @discussion Factory function to create and initialize an unspecified IODMACommand. prepareWithSpecification() must be used to prepare the IODMACommand before use. + @param refCon Reference Constant + @result Returns a new IODMACommand if successfully created and initialized, 0 otherwise. +*/ + static IODMACommand * withRefCon(void * refCon); + /*! @function cloneCommand @abstract Creates a new command based on the specification of the current one. @discussion Factory function to create and initialise an IODMACommand in one operation. The current command's specification will be duplicated in the new object, but however none of its state will be duplicated. This means that it is safe to clone a command even if it is currently active and running, however you must be certain that the command to be duplicated does have a valid reference for the duration. - @result Returns a new memory cursor if successfully created and initialised, 0 otherwise. + @result Returns a new IODMACommand if successfully created and initialised, 0 otherwise. */ virtual IODMACommand *cloneCommand(void *refCon = 0); @@ -243,6 +289,7 @@ public: @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. @param alignment Alignment restriction, in bytes, on I/O bus addresses. Defaults to single byte alignment. @param mapper For mapping types kMapped & kBypassed mapper is used to define the hardware that will perform the mapping, defaults to the system mapper. + @param refCon Reference Constant @result Can fail if the mapping type is not recognised, if one of the 3 mandatory parameters are set to 0, if a 32 bit output function is selected when more than 32 bits of address is required or, if kBypassed is requested on a machine that doesn't support bypassing. Returns true otherwise. */ virtual bool initWithSpecification( SegmentFunction outSegFunc, @@ -256,7 +303,7 @@ public: /*! @function setMemoryDescriptor @abstract Sets and resets the DMACommand's current memory descriptor - @discussion The DMA command will configure itself based on the information that it finds in the memory descriptor. It looks for things like the direction of the memory descriptor and whether the current memory descriptor is already mapped into some IOMMU. As a programmer convenience it can also prepare the memory descriptor immediately. See prepare(). Note the IODMACommand is designed to used multiple times with a succession of memory descriptors, making the pooling of commands possible. It is an error though to attempt to reset a currently prepared() DMA command. Warning: This routine may block so never try to autoprepare an IODMACommand while in a gated context, i.e. one of the WorkLoops action call outs. + @discussion The DMA command will configure itself based on the information that it finds in the memory descriptor. It looks for things like the direction of the memory descriptor and whether the current memory descriptor is already mapped into some IOMMU. As a programmer convenience it can also prepare the DMA command immediately. See prepare(). Note the IODMACommand is designed to used multiple times with a succession of memory descriptors, making the pooling of commands possible. It is an error though to attempt to reset a currently prepared() DMA command. Warning: This routine may block so never try to autoprepare an IODMACommand while in a gated context, i.e. one of the WorkLoops action call outs. @param mem A pointer to the current I/Os memory descriptor. @param autoPrepare An optional boolean variable that will call the prepare() function automatically after the memory descriptor is processed. Defaults to true. @result Returns kIOReturnSuccess, kIOReturnBusy if currently prepared, kIOReturnNoSpace if the length(mem) >= Maximum Transfer Size or the error codes returned by prepare() (qv). @@ -276,6 +323,11 @@ public: */ virtual const IOMemoryDescriptor *getMemoryDescriptor() const; +/*! @function getIOMemoryDescriptor + @abstract Get the memory descriptor to be used for DMA +*/ + IOMemoryDescriptor * getIOMemoryDescriptor() const; + /*! @function prepare @abstract Prepare the memory for an I/O transfer. @discussion Allocate the mapping resources neccessary for this transfer, specifying a sub range of the IOMemoryDescriptor that will be the target of the I/O. The complete() method frees these resources. Data may be copied to buffers for kIODirectionOut memory descriptors, depending on hardware mapping resource availabilty or alignment restrictions. It should be noted that the this function may block and should only be called on the clients context, i.e never call this routine while gated; also the call itself is not thread safe though this should be an issue as each IODMACommand is independant. @@ -319,6 +371,31 @@ public: void *segments, UInt32 *numSegments); +private: + virtual UInt64 transfer( IOOptionBits transferOp, UInt64 offset, void * buffer, UInt64 length ); + +public: + +/*! @function writeBytes + @abstract Copy data to the IODMACommand's buffer from the specified buffer. + @discussion This method copies data to the IODMACommand's memory at the given offset, from the caller's buffer. The IODMACommand must be prepared, and the offset is relative to the prepared offset. + @param offset A byte offset into the IODMACommand's memory, relative to the prepared offset. + @param bytes The caller supplied buffer to copy the data from. + @param length The length of the data to copy. + @result The number of bytes copied, zero will be returned if the specified offset is beyond the prepared length of the IODMACommand. */ + + UInt64 writeBytes(UInt64 offset, const void *bytes, UInt64 length); + +/*! @function readBytes + @abstract Copy data from the IODMACommand's buffer to the specified buffer. + @discussion This method copies data from the IODMACommand's memory at the given offset, to the caller's buffer. The IODMACommand must be prepared, and the offset is relative to the prepared offset. + @param offset A byte offset into the IODMACommand's memory, relative to the prepared offset. + @param bytes The caller supplied buffer to copy the data to. + @param length The length of the data to copy. + @result The number of bytes copied, zero will be returned if the specified offset is beyond the prepared length of the IODMACommand. */ + + UInt64 readBytes(UInt64 offset, void *bytes, UInt64 length); + /*! @function gen32IOVMSegments @abstract Helper function for a type checked call to genIOVMSegments(qv), for use with an IODMACommand set up with the output function kIODMACommandOutputHost32, kIODMACommandOutputBig32, or kIODMACommandOutputLittle32. If the output function of the IODMACommand is not a 32 bit function, results will be incorrect. */ @@ -335,9 +412,19 @@ public: UInt32 *numSegments) { return genIOVMSegments(offset, segments, numSegments); }; - virtual void free(); + IOReturn + genIOVMSegments(SegmentFunction segmentFunction, + UInt64 *offsetP, + void *segmentsP, + UInt32 *numSegmentsP); + + virtual void free() APPLE_KEXT_OVERRIDE; private: + IOReturn setSpecification(SegmentFunction outSegFunc, + const SegmentOptions * segmentOptions, + uint32_t mappingOptions, + IOMapper * mapper); typedef IOReturn (*InternalSegmentFunction)( void *reference, @@ -346,7 +433,8 @@ private: void *segments, UInt32 segmentIndex); - IOReturn genIOVMSegments(InternalSegmentFunction outSegFunc, + IOReturn genIOVMSegments(uint32_t op, + InternalSegmentFunction outSegFunc, void *reference, UInt64 *offsetP, void *segmentsP, @@ -355,23 +443,104 @@ private: static IOReturn clientOutputSegment( void *reference, IODMACommand *target, Segment64 segment, void *vSegList, UInt32 outSegIndex); - + static IOReturn segmentOp( void *reference, IODMACommand *target, Segment64 segment, void *segments, UInt32 segmentIndex); - IOReturn IODMACommand::walkAll(UInt8 op); + IOReturn walkAll(UInt8 op); + +public: + +/*! @function prepareWithSpecification + @abstract Prepare the memory for an I/O transfer with a new specification. + @discussion Allocate the mapping resources neccessary for this transfer, specifying a sub range of the IOMemoryDescriptor that will be the target of the I/O. The complete() method frees these resources. Data may be copied to buffers for kIODirectionOut memory descriptors, depending on hardware mapping resource availabilty or alignment restrictions. It should be noted that the this function may block and should only be called on the clients context, i.e never call this routine while gated; also the call itself is not thread safe though this should be an issue as each IODMACommand is independant. + @param outSegFunc SegmentFunction to call to output one physical segment. A set of nine commonly required segment functions are provided. + @param numAddressBits Number of bits that the hardware uses on its internal address bus. Typically 32 but may be more on modern hardware. A 0 implies no-restriction other than that implied by the output segment function. + @param maxSegmentSize Maximum allowable size for one segment. Defaults to 0 which means any size. + @param mappingOptions is the type of mapping that is required to translate an IOMemoryDescriptor into the desired number of bits. For instance if your hardware only supports 32 bits but must run on machines with > 4G of RAM some mapping will be required. Number of bits will be specified in numAddressBits, see below.This parameter can take 3 values:- kNonCoherent - used for non-coherent hardware transfers, Mapped - Validate that all I/O bus generated addresses are within the number of addressing bits specified, Bypassed indicates that bypassed addressing is required, this is used when the hardware transferes are into coherent memory but no mapping is required. See also prepare() for failure cases. + @param maxTransferSize Maximum size of an entire transfer. Defaults to 0 indicating no maximum. + @param alignment Alignment restriction, in bytes, on I/O bus addresses. Defaults to single byte alignment. + @param mapper For mapping types kMapped & kBypassed mapper is used to define the hardware that will perform the mapping, defaults to the system mapper. + @param offset defines the starting offset in the memory descriptor the DMA command will operate on. genIOVMSegments will produce its results based on the offset and length passed to the prepare method. + @param length defines the ending position in the memory descriptor the DMA command will operate on. genIOVMSegments will produce its results based on the offset and length passed to the prepare method. + @param flushCache Flush the caches for the memory descriptor and make certain that the memory cycles are complete. Defaults to true for kNonCoherent and is ignored by the other types. + @param synchronize Copy any buffered data back from the target IOMemoryDescriptor. Defaults to true, if synchronize() is being used to explicitly copy data, passing false may avoid an unneeded copy. + @result An IOReturn code. Can fail if the mapping type is not recognised, if one of the 3 mandatory parameters are set to 0, if a 32 bit output function is selected when more than 32 bits of address is required or, if kBypassed is requested on a machine that doesn't support bypassing. +*/ + + virtual IOReturn prepareWithSpecification(SegmentFunction outSegFunc, + UInt8 numAddressBits, + UInt64 maxSegmentSize, + MappingOptions mappingOptions = kMapped, + UInt64 maxTransferSize = 0, + UInt32 alignment = 1, + IOMapper *mapper = 0, + UInt64 offset = 0, + UInt64 length = 0, + bool flushCache = true, + bool synchronize = true); + + static IOReturn transferSegment(void *reference, + IODMACommand *target, + Segment64 segment, + void *segments, + UInt32 segmentIndex); + +/*! @function getPreparedOffsetAndLength + @abstract Returns the offset and length into the target IOMemoryDescriptor of a prepared IODDMACommand. + @discussion If successfully prepared, returns the offset and length into the IOMemoryDescriptor. Will fail for an unprepared IODMACommand. + @param offset returns the starting offset in the memory descriptor the DMA command was prepared with. Pass NULL for don't care. + @param length returns the length in the memory descriptor the DMA command was prepared with. Pass NULL for don't care. + @result An IOReturn code. kIOReturnNotReady if the IODMACommand is not prepared. */ + + virtual IOReturn getPreparedOffsetAndLength(UInt64 * offset, UInt64 * length); + + UInt8 getNumAddressBits(void); + UInt32 getAlignment(void); + uint32_t getAlignmentLength(void); + uint32_t getAlignmentInternalSegments(void); + + +/*! @function initWithRefCon + @abstract Secondary initializer for the IODMACommand class. + @param refCon Reference Constant + @result Can fail if super init fails. Returns true otherwise. +*/ + virtual + bool initWithRefCon(void * refCon = 0); + + virtual + bool initWithSpecification(SegmentFunction outSegFunc, + const SegmentOptions * segmentOptions, + uint32_t mappingOptions, + IOMapper * mapper, + void * refCon); + + virtual + IOReturn prepareWithSpecification(SegmentFunction outSegFunc, + const SegmentOptions * segmentOptions, + uint32_t mappingOptions, + IOMapper * mapper, + uint64_t offset, + uint64_t length, + bool flushCache = true, + bool synchronize = true); + + virtual + IOBufferMemoryDescriptor * createCopyBuffer(IODirection direction, UInt64 length); + private: - OSMetaClassDeclareReservedUnused(IODMACommand, 0); - OSMetaClassDeclareReservedUnused(IODMACommand, 1); - OSMetaClassDeclareReservedUnused(IODMACommand, 2); - OSMetaClassDeclareReservedUnused(IODMACommand, 3); - OSMetaClassDeclareReservedUnused(IODMACommand, 4); - OSMetaClassDeclareReservedUnused(IODMACommand, 5); - OSMetaClassDeclareReservedUnused(IODMACommand, 6); + OSMetaClassDeclareReservedUsed(IODMACommand, 0); + OSMetaClassDeclareReservedUsed(IODMACommand, 1); + OSMetaClassDeclareReservedUsed(IODMACommand, 2); + OSMetaClassDeclareReservedUsed(IODMACommand, 3); + OSMetaClassDeclareReservedUsed(IODMACommand, 4); + OSMetaClassDeclareReservedUsed(IODMACommand, 5); + OSMetaClassDeclareReservedUsed(IODMACommand, 6); OSMetaClassDeclareReservedUnused(IODMACommand, 7); OSMetaClassDeclareReservedUnused(IODMACommand, 8); OSMetaClassDeclareReservedUnused(IODMACommand, 9); @@ -395,9 +564,8 @@ protected: Maximum size of a transfer that this memory cursor is allowed to generate */ UInt64 fMaxTransferSize; -/*! @var fBypassMask - Mask to be ored into the address to bypass the given iommu's mapping. */ - UInt64 fBypassMask; + UInt32 fAlignMaskLength; + UInt32 fAlignMaskInternalSegments; /*! @var fMapper Client defined mapper. */ @@ -424,7 +592,7 @@ protected: /*! @var fMappingOptions What type of I/O virtual address mapping is required for this command */ - MappingOptions fMappingOptions; + uint32_t fMappingOptions; /*! @var fActive fActive indicates that this DMA command is currently prepared and ready to go */ @@ -432,7 +600,7 @@ protected: /*! @var reserved Reserved for future use. (Internal use only) */ - struct ExpansionData * reserved; + struct IODMACommandInternal * reserved; }; IOReturn IODMACommand::