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
19struct device_node;
20struct IOOperation;
21struct IORequest;
22
23
24struct 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
36struct DMABounceBuffer : public DoublyLinkedListLinkImpl<DMABounceBuffer> {
37	void*		address;
38	phys_addr_t	physical_address;
39	phys_size_t	size;
40};
41
42typedef DoublyLinkedList<DMABounceBuffer> DMABounceBufferList;
43
44
45class DMABuffer : public DoublyLinkedListLinkImpl<DMABuffer> {
46public:
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
76private:
77			DMABounceBuffer*	fBounceBuffer;
78			uint32				fVecCount;
79			generic_io_vec		fVecs[1];
80};
81
82
83typedef DoublyLinkedList<DMABuffer> DMABufferList;
84
85
86class DMAResource {
87public:
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
111private:
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