1 /* 2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef DMA_RESOURCES_H 7 #define DMA_RESOURCES_H 8 9 10 #include <sys/uio.h> 11 12 #include <fs_interface.h> 13 14 #include <lock.h> 15 #include <util/DoublyLinkedList.h> 16 #include <util/iovec_support.h> 17 18 19 struct device_node; 20 struct IOOperation; 21 struct IORequest; 22 23 24 struct dma_restrictions { 25 generic_addr_t low_address; 26 generic_addr_t high_address; 27 generic_size_t alignment; 28 generic_size_t boundary; 29 generic_size_t max_transfer_size; 30 uint32 max_segment_count; 31 generic_size_t max_segment_size; 32 uint32 flags; 33 }; 34 35 36 struct DMABounceBuffer : public DoublyLinkedListLinkImpl<DMABounceBuffer> { 37 void* address; 38 phys_addr_t physical_address; 39 phys_size_t size; 40 }; 41 42 typedef DoublyLinkedList<DMABounceBuffer> DMABounceBufferList; 43 44 45 class DMABuffer : public DoublyLinkedListLinkImpl<DMABuffer> { 46 public: 47 static DMABuffer* Create(size_t count); 48 49 generic_io_vec* Vecs() { return fVecs; } 50 generic_io_vec& VecAt(size_t index) { return fVecs[index]; } 51 uint32 VecCount() const { return fVecCount; } 52 void SetVecCount(uint32 count); 53 54 void AddVec(generic_addr_t base, 55 generic_size_t size); 56 57 void SetBounceBuffer(DMABounceBuffer* bounceBuffer) 58 { fBounceBuffer = bounceBuffer; } 59 DMABounceBuffer* BounceBuffer() const { return fBounceBuffer; } 60 61 void* BounceBufferAddress() const 62 { return fBounceBuffer 63 ? fBounceBuffer->address : NULL; } 64 phys_addr_t PhysicalBounceBufferAddress() const 65 { return fBounceBuffer 66 ? fBounceBuffer->physical_address 67 : 0; } 68 phys_size_t BounceBufferSize() const 69 { return fBounceBuffer 70 ? fBounceBuffer->size : 0; } 71 72 bool UsesBounceBufferAt(uint32 index); 73 74 void Dump() const; 75 76 private: 77 DMABounceBuffer* fBounceBuffer; 78 uint32 fVecCount; 79 generic_io_vec fVecs[1]; 80 }; 81 82 83 typedef DoublyLinkedList<DMABuffer> DMABufferList; 84 85 86 class DMAResource { 87 public: 88 DMAResource(); 89 ~DMAResource(); 90 91 status_t Init(const dma_restrictions& restrictions, 92 generic_size_t blockSize, 93 uint32 bufferCount, 94 uint32 bounceBufferCount); 95 status_t Init(device_node* node, 96 generic_size_t blockSize, 97 uint32 bufferCount, 98 uint32 bounceBufferCount); 99 100 status_t CreateBuffer(DMABuffer** _buffer); 101 status_t CreateBounceBuffer(DMABounceBuffer** _buffer); 102 103 status_t TranslateNext(IORequest* request, 104 IOOperation* operation, 105 generic_size_t maxOperationLength); 106 void RecycleBuffer(DMABuffer* buffer); 107 108 generic_size_t BlockSize() const { return fBlockSize; } 109 uint32 BufferCount() const { return fBufferCount; } 110 111 private: 112 bool _NeedsBoundsBuffers() const; 113 void _RestrictBoundaryAndSegmentSize( 114 generic_addr_t base, 115 generic_addr_t& length); 116 void _CutBuffer(DMABuffer& buffer, 117 phys_addr_t& physicalBounceBuffer, 118 phys_size_t& bounceLeft, 119 generic_size_t toCut); 120 phys_size_t _AddBounceBuffer(DMABuffer& buffer, 121 phys_addr_t& physicalBounceBuffer, 122 phys_size_t& bounceLeft, 123 generic_size_t length, bool fixedLength); 124 125 mutex fLock; 126 dma_restrictions fRestrictions; 127 generic_size_t fBlockSize; 128 uint32 fBufferCount; 129 uint32 fBounceBufferCount; 130 phys_size_t fBounceBufferSize; 131 DMABufferList fDMABuffers; 132 DMABounceBufferList fBounceBuffers; 133 generic_io_vec* fScratchVecs; 134 }; 135 136 #endif // DMA_RESOURCES_H 137