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