2 * Copyright 2008-2011, 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.
14 #include <fs_interface.h>
16 #include <condition_variable.h>
18 #include <util/DoublyLinkedList.h>
20 #include "dma_resources.h"
23 #define B_PHYSICAL_IO_REQUEST 0x01 /* buffer points to physical memory */
24 #define B_VIP_IO_REQUEST 0x02 /* used by the page writer -- make sure
25 allocations won't fail */
26 #define B_DELETE_IO_REQUEST 0x04 /* delete request when finished */
31 typedef struct IOOperation io_operation
;
33 class IOBuffer
: public DoublyLinkedListLinkImpl
<IOBuffer
> {
35 static IOBuffer
* Create(uint32 count
, bool vip
);
38 bool IsVirtual() const { return !fPhysical
; }
39 bool IsPhysical() const { return fPhysical
; }
40 bool IsUser() const { return fUser
; }
42 void SetVecs(generic_size_t firstVecOffset
,
43 const generic_io_vec
* vecs
, uint32 count
,
44 generic_size_t length
, uint32 flags
);
46 void SetPhysical(bool physical
)
47 { fPhysical
= physical
; }
48 void SetUser(bool user
) { fUser
= user
; }
49 void SetLength(generic_size_t length
)
51 void SetVecCount(uint32 count
) { fVecCount
= count
; }
53 generic_size_t
Length() const { return fLength
; }
55 generic_io_vec
* Vecs() { return fVecs
; }
56 generic_io_vec
& VecAt(size_t index
) { return fVecs
[index
]; }
57 size_t VecCount() const { return fVecCount
; }
58 size_t Capacity() const { return fCapacity
; }
60 status_t
GetNextVirtualVec(void*& cookie
, iovec
& vector
);
61 void FreeVirtualVecCookie(void* cookie
);
63 status_t
LockMemory(team_id team
, bool isWrite
);
64 void UnlockMemory(team_id team
, bool isWrite
);
65 bool IsMemoryLocked() const
66 { return fMemoryLocked
; }
74 void _UnlockMemory(team_id team
, size_t count
,
81 generic_size_t fLength
;
84 generic_io_vec fVecs
[1];
89 struct IORequestOwner
;
92 class IORequestChunk
{
95 virtual ~IORequestChunk();
97 IORequest
* Parent() const { return fParent
; }
98 void SetParent(IORequest
* parent
)
101 status_t
Status() const { return fStatus
; }
103 DoublyLinkedListLink
<IORequestChunk
>*
104 ListLink() { return &fListLink
; }
107 void SetStatus(status_t status
)
108 { fStatus
= status
; }
117 DoublyLinkedListLink
<IORequestChunk
> fListLink
;
120 typedef DoublyLinkedList
<IORequestChunk
,
121 DoublyLinkedListMemberGetLink
<IORequestChunk
, &IORequestChunk::fListLink
> >
125 struct IOOperation
: IORequestChunk
, DoublyLinkedListLinkImpl
<IOOperation
> {
128 // returns true, if it can be recycled
130 status_t
Prepare(IORequest
* request
);
131 void SetOriginalRange(off_t offset
,
132 generic_size_t length
);
134 void SetRange(off_t offset
, generic_size_t length
);
136 void SetStatus(status_t status
)
137 { IORequestChunk::SetStatus(status
); }
139 off_t
Offset() const;
140 generic_size_t
Length() const;
141 off_t
OriginalOffset() const
142 { return fOriginalOffset
; }
143 generic_size_t
OriginalLength() const
144 { return fOriginalLength
; }
146 generic_size_t
TransferredBytes() const
147 { return fTransferredBytes
; }
148 void SetTransferredBytes(generic_size_t bytes
)
149 { fTransferredBytes
= bytes
; }
151 generic_io_vec
* Vecs() const;
152 uint32
VecCount() const;
154 void SetPartial(bool partialBegin
, bool partialEnd
);
155 bool HasPartialBegin() const
156 { return fPartialBegin
; }
157 bool HasPartialEnd() const
158 { return fPartialEnd
; }
159 bool IsWrite() const;
162 void SetBlockSize(generic_size_t blockSize
)
163 { fBlockSize
= blockSize
; }
165 bool UsesBounceBuffer() const
166 { return fUsesBounceBuffer
; }
167 void SetUsesBounceBuffer(bool uses
)
168 { fUsesBounceBuffer
= uses
; }
170 DMABuffer
* Buffer() const { return fDMABuffer
; }
171 void SetBuffer(DMABuffer
* buffer
)
172 { fDMABuffer
= buffer
; }
178 status_t
_CopyPartialBegin(bool isWrite
,
179 bool& partialBlockOnly
);
180 status_t
_CopyPartialEnd(bool isWrite
);
182 DMABuffer
* fDMABuffer
;
184 off_t fOriginalOffset
;
185 generic_size_t fLength
;
186 generic_size_t fOriginalLength
;
187 generic_size_t fTransferredBytes
;
188 generic_size_t fBlockSize
;
189 uint16 fSavedVecIndex
;
190 uint16 fSavedVecLength
;
194 bool fUsesBounceBuffer
;
198 typedef IOOperation io_operation
;
199 typedef DoublyLinkedList
<IOOperation
> IOOperationList
;
201 typedef struct IORequest io_request
;
202 typedef status_t (*io_request_finished_callback
)(void* data
,
203 io_request
* request
, status_t status
, bool partialTransfer
,
204 generic_size_t transferEndOffset
);
205 // TODO: Return type: status_t -> void
206 typedef status_t (*io_request_iterate_callback
)(void* data
,
207 io_request
* request
, bool* _partialTransfer
);
210 struct IORequest
: IORequestChunk
, DoublyLinkedListLinkImpl
<IORequest
> {
212 virtual ~IORequest();
214 static IORequest
* Create(bool vip
);
216 status_t
Init(off_t offset
, generic_addr_t buffer
,
217 generic_size_t length
, bool write
,
219 status_t
Init(off_t offset
, const generic_io_vec
* vecs
,
220 size_t count
, generic_size_t length
,
221 bool write
, uint32 flags
)
222 { return Init(offset
, 0, vecs
, count
,
223 length
, write
, flags
); }
224 status_t
Init(off_t offset
,
225 generic_size_t firstVecOffset
,
226 const generic_io_vec
* vecs
, size_t count
,
227 generic_size_t length
, bool write
,
230 void SetOwner(IORequestOwner
* owner
)
232 IORequestOwner
* Owner() const { return fOwner
; }
234 status_t
CreateSubRequest(off_t parentOffset
,
235 off_t offset
, generic_size_t length
,
236 IORequest
*& subRequest
);
237 void DeleteSubRequests();
239 void SetFinishedCallback(
240 io_request_finished_callback callback
,
242 void SetIterationCallback(
243 io_request_iterate_callback callback
,
245 io_request_finished_callback
FinishedCallback(
246 void** _cookie
= NULL
) const;
248 status_t
Wait(uint32 flags
= 0, bigtime_t timeout
= 0);
250 bool IsFinished() const
251 { return fStatus
!= 1
252 && fPendingChildren
== 0; }
253 void NotifyFinished();
254 bool HasCallbacks() const;
255 void SetStatusAndNotify(status_t status
);
257 void OperationFinished(IOOperation
* operation
,
258 status_t status
, bool partialTransfer
,
259 generic_size_t transferEndOffset
);
260 void SubRequestFinished(IORequest
* request
,
261 status_t status
, bool partialTransfer
,
262 generic_size_t transferEndOffset
);
263 void SetUnfinished();
265 generic_size_t
RemainingBytes() const
266 { return fRemainingBytes
; }
267 generic_size_t
TransferredBytes() const
268 { return fTransferSize
; }
269 bool IsPartialTransfer() const
270 { return fPartialTransfer
; }
271 void SetTransferredBytes(bool partialTransfer
,
272 generic_size_t transferredBytes
);
274 void SetSuppressChildNotifications(bool suppress
);
275 bool SuppressChildNotifications() const
276 { return fSuppressChildNotifications
; }
278 bool IsWrite() const { return fIsWrite
; }
279 bool IsRead() const { return !fIsWrite
; }
280 team_id
TeamID() const { return fTeam
; }
281 thread_id
ThreadID() const { return fThread
; }
282 uint32
Flags() const { return fFlags
; }
284 IOBuffer
* Buffer() const { return fBuffer
; }
285 off_t
Offset() const { return fOffset
; }
286 generic_size_t
Length() const { return fLength
; }
288 void SetOffset(off_t offset
) { fOffset
= offset
; }
290 uint32
VecIndex() const { return fVecIndex
; }
291 generic_size_t
VecOffset() const { return fVecOffset
; }
293 void Advance(generic_size_t bySize
);
295 IORequest
* FirstSubRequest();
296 IORequest
* NextSubRequest(IORequest
* previous
);
298 void AddOperation(IOOperation
* operation
);
299 void RemoveOperation(IOOperation
* operation
);
301 status_t
CopyData(off_t offset
, void* buffer
,
303 status_t
CopyData(const void* buffer
, off_t offset
,
305 status_t
ClearData(off_t offset
, generic_size_t size
);
310 status_t
_CopyData(void* buffer
, off_t offset
,
311 size_t size
, bool copyIn
);
312 static status_t
_CopySimple(void* bounceBuffer
,
313 generic_addr_t external
, size_t size
,
314 team_id team
, bool copyIn
);
315 static status_t
_CopyPhysical(void* bounceBuffer
,
316 generic_addr_t external
, size_t size
,
317 team_id team
, bool copyIn
);
318 static status_t
_CopyUser(void* bounceBuffer
,
319 generic_addr_t external
, size_t size
,
320 team_id team
, bool copyIn
);
321 static status_t
_ClearDataSimple(generic_addr_t external
,
322 generic_size_t size
, team_id team
);
323 static status_t
_ClearDataPhysical(generic_addr_t external
,
324 generic_size_t size
, team_id team
);
325 static status_t
_ClearDataUser(generic_addr_t external
,
326 generic_size_t size
, team_id team
);
329 IORequestOwner
* fOwner
;
332 generic_size_t fLength
;
333 generic_size_t fTransferSize
;
334 // After all subrequests/operations have
335 // finished, number of contiguous bytes at
336 // the beginning of the request that have
337 // actually been transferred.
338 generic_size_t fRelativeParentOffset
;
339 // offset of this request relative to its
341 IORequestChunkList fChildren
;
342 int32 fPendingChildren
;
347 bool fPartialTransfer
;
348 bool fSuppressChildNotifications
;
351 io_request_finished_callback fFinishedCallback
;
352 void* fFinishedCookie
;
353 io_request_iterate_callback fIterationCallback
;
354 void* fIterationCookie
;
355 ConditionVariable fFinishedCondition
;
357 // these are for iteration
359 generic_size_t fVecOffset
;
360 generic_size_t fRemainingBytes
;
364 typedef DoublyLinkedList
<IORequest
> IORequestList
;
367 #endif // IO_REQUEST_H