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