xref: /haiku/src/system/kernel/device_manager/dma_resources.h (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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