16969690aSAxel Dörfler/*
2435c43f5SIngo Weinhold * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
36969690aSAxel Dörfler * Copyright 2008, Axel D��rfler, axeld@pinc-software.de.
46969690aSAxel Dörfler * Distributed under the terms of the MIT License.
56969690aSAxel Dörfler */
66969690aSAxel Dörfler#ifndef DMA_RESOURCES_H
76969690aSAxel Dörfler#define DMA_RESOURCES_H
86969690aSAxel Dörfler
9435c43f5SIngo Weinhold
106969690aSAxel Dörfler#include <sys/uio.h>
116969690aSAxel Dörfler
12435c43f5SIngo Weinhold#include <fs_interface.h>
13435c43f5SIngo Weinhold
146969690aSAxel Dörfler#include <lock.h>
156969690aSAxel Dörfler#include <util/DoublyLinkedList.h>
166969690aSAxel Dörfler
176969690aSAxel Dörfler
1839b5c374SAxel Dörflerstruct device_node;
196969690aSAxel Dörflerstruct IOOperation;
206969690aSAxel Dörflerstruct IORequest;
216969690aSAxel Dörfler
226969690aSAxel Dörfler
23435c43f5SIngo Weinholdtypedef struct generic_io_vec {
24435c43f5SIngo Weinhold	generic_addr_t	base;
25435c43f5SIngo Weinhold	generic_size_t	length;
26435c43f5SIngo Weinhold} generic_io_vec;
27435c43f5SIngo Weinhold
28435c43f5SIngo Weinhold
296969690aSAxel Dörflerstruct dma_restrictions {
30435c43f5SIngo Weinhold	generic_addr_t	low_address;
31435c43f5SIngo Weinhold	generic_addr_t	high_address;
32435c43f5SIngo Weinhold	generic_size_t	alignment;
33435c43f5SIngo Weinhold	generic_size_t	boundary;
34435c43f5SIngo Weinhold	generic_size_t	max_transfer_size;
35435c43f5SIngo Weinhold	uint32			max_segment_count;
36435c43f5SIngo Weinhold	generic_size_t	max_segment_size;
37435c43f5SIngo Weinhold	uint32			flags;
386969690aSAxel Dörfler};
396969690aSAxel Dörfler
406969690aSAxel Dörfler
41025f7c32SIngo Weinholdstruct DMABounceBuffer : public DoublyLinkedListLinkImpl<DMABounceBuffer> {
42435c43f5SIngo Weinhold	void*		address;
43435c43f5SIngo Weinhold	phys_addr_t	physical_address;
44435c43f5SIngo Weinhold	phys_size_t	size;
45025f7c32SIngo Weinhold};
46025f7c32SIngo Weinhold
47025f7c32SIngo Weinholdtypedef DoublyLinkedList<DMABounceBuffer> DMABounceBufferList;
48025f7c32SIngo Weinhold
49025f7c32SIngo Weinhold
506969690aSAxel Dörflerclass DMABuffer : public DoublyLinkedListLinkImpl<DMABuffer> {
516969690aSAxel Dörflerpublic:
52025f7c32SIngo Weinhold	static	DMABuffer*			Create(size_t count);
536969690aSAxel Dörfler
54435c43f5SIngo Weinhold			generic_io_vec*		Vecs() { return fVecs; }
55435c43f5SIngo Weinhold			generic_io_vec&		VecAt(size_t index) { return fVecs[index]; }
566969690aSAxel Dörfler			uint32				VecCount() const { return fVecCount; }
576969690aSAxel Dörfler			void				SetVecCount(uint32 count);
586969690aSAxel Dörfler
59435c43f5SIngo Weinhold			void				AddVec(generic_addr_t base,
60435c43f5SIngo Weinhold									generic_size_t size);
616969690aSAxel Dörfler
62025f7c32SIngo Weinhold			void				SetBounceBuffer(DMABounceBuffer* bounceBuffer)
63025f7c32SIngo Weinhold									{ fBounceBuffer = bounceBuffer; }
64025f7c32SIngo Weinhold			DMABounceBuffer*	BounceBuffer() const { return fBounceBuffer; }
65025f7c32SIngo Weinhold
66025f7c32SIngo Weinhold			void*				BounceBufferAddress() const
67025f7c32SIngo Weinhold									{ return fBounceBuffer
68025f7c32SIngo Weinhold										? fBounceBuffer->address : NULL; }
69435c43f5SIngo Weinhold			phys_addr_t			PhysicalBounceBufferAddress() const
70025f7c32SIngo Weinhold									{ return fBounceBuffer
71025f7c32SIngo Weinhold										? fBounceBuffer->physical_address
72025f7c32SIngo Weinhold										: 0; }
73435c43f5SIngo Weinhold			phys_size_t			BounceBufferSize() const
74025f7c32SIngo Weinhold									{ return fBounceBuffer
75025f7c32SIngo Weinhold										? fBounceBuffer->size : 0; }
766969690aSAxel Dörfler
778faff60cSAxel Dörfler			bool				UsesBounceBufferAt(uint32 index);
786969690aSAxel Dörfler
79f8a59924SAxel Dörfler			void				Dump() const;
80f8a59924SAxel Dörfler
816969690aSAxel Dörflerprivate:
82025f7c32SIngo Weinhold			DMABounceBuffer*	fBounceBuffer;
836969690aSAxel Dörfler			uint32				fVecCount;
84435c43f5SIngo Weinhold			generic_io_vec		fVecs[1];
856969690aSAxel Dörfler};
866969690aSAxel Dörfler
876969690aSAxel Dörfler
886969690aSAxel Dörflertypedef DoublyLinkedList<DMABuffer> DMABufferList;
896969690aSAxel Dörfler
906969690aSAxel Dörfler
916969690aSAxel Dörflerclass DMAResource {
926969690aSAxel Dörflerpublic:
936969690aSAxel Dörfler								DMAResource();
946969690aSAxel Dörfler								~DMAResource();
956969690aSAxel Dörfler
966969690aSAxel Dörfler			status_t			Init(const dma_restrictions& restrictions,
97435c43f5SIngo Weinhold									generic_size_t blockSize,
98435c43f5SIngo Weinhold									uint32 bufferCount,
99025f7c32SIngo Weinhold									uint32 bounceBufferCount);
100435c43f5SIngo Weinhold			status_t			Init(device_node* node,
101435c43f5SIngo Weinhold									generic_size_t blockSize,
102025f7c32SIngo Weinhold									uint32 bufferCount,
103025f7c32SIngo Weinhold									uint32 bounceBufferCount);
1046969690aSAxel Dörfler
105025f7c32SIngo Weinhold			status_t			CreateBuffer(DMABuffer** _buffer);
106025f7c32SIngo Weinhold			status_t			CreateBounceBuffer(DMABounceBuffer** _buffer);
1076969690aSAxel Dörfler
1086969690aSAxel Dörfler			status_t			TranslateNext(IORequest* request,
1090316483fSIngo Weinhold									IOOperation* operation,
110435c43f5SIngo Weinhold									generic_size_t maxOperationLength);
1116969690aSAxel Dörfler			void				RecycleBuffer(DMABuffer* buffer);
1126969690aSAxel Dörfler
113435c43f5SIngo Weinhold			generic_size_t		BlockSize() const	{ return fBlockSize; }
1146969690aSAxel Dörfler			uint32				BufferCount() const { return fBufferCount; }
1156969690aSAxel Dörfler
1166969690aSAxel Dörflerprivate:
1176969690aSAxel Dörfler			bool				_NeedsBoundsBuffers() const;
118435c43f5SIngo Weinhold			void				_RestrictBoundaryAndSegmentSize(
119435c43f5SIngo Weinhold									generic_addr_t base,
120435c43f5SIngo Weinhold									generic_addr_t& length);
1218faff60cSAxel Dörfler			void				_CutBuffer(DMABuffer& buffer,
122435c43f5SIngo Weinhold									phys_addr_t& physicalBounceBuffer,
123435c43f5SIngo Weinhold									phys_size_t& bounceLeft,
124435c43f5SIngo Weinhold									generic_size_t toCut);
125435c43f5SIngo Weinhold			phys_size_t			_AddBounceBuffer(DMABuffer& buffer,
126435c43f5SIngo Weinhold									phys_addr_t& physicalBounceBuffer,
127435c43f5SIngo Weinhold									phys_size_t& bounceLeft,
128435c43f5SIngo Weinhold									generic_size_t length, bool fixedLength);
1296969690aSAxel Dörfler
1306969690aSAxel Dörfler			mutex				fLock;
1316969690aSAxel Dörfler			dma_restrictions	fRestrictions;
132435c43f5SIngo Weinhold			generic_size_t		fBlockSize;
1336969690aSAxel Dörfler			uint32				fBufferCount;
134025f7c32SIngo Weinhold			uint32				fBounceBufferCount;
135435c43f5SIngo Weinhold			phys_size_t			fBounceBufferSize;
1366969690aSAxel Dörfler			DMABufferList		fDMABuffers;
137025f7c32SIngo Weinhold			DMABounceBufferList	fBounceBuffers;
138435c43f5SIngo Weinhold			generic_io_vec*		fScratchVecs;
1396969690aSAxel Dörfler};
1406969690aSAxel Dörfler
1416969690aSAxel Dörfler#endif	// DMA_RESOURCES_H
142