xref: /haiku/src/system/kernel/device_manager/io_requests.cpp (revision e0ef64750f3169cd634bb2f7a001e22488b05231)
1 /*
2  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <io_requests.h>
7 
8 #include "IORequest.h"
9 
10 
11 // #pragma mark - static helpers
12 
13 
14 static status_t
15 transfer_io_request_data(io_request* request, void* buffer, size_t size,
16 	bool writeToRequest)
17 {
18 	if (writeToRequest == request->IsWrite()
19 		|| request->RemainingBytes() < size) {
20 		return B_BAD_VALUE;
21 	}
22 
23 	// lock the request buffer memory, if it is user memory
24 	IOBuffer* ioBuffer = request->Buffer();
25 	if (ioBuffer->IsUser() && !ioBuffer->IsMemoryLocked()) {
26 		status_t error = ioBuffer->LockMemory(request->Team(), !writeToRequest);
27 		if (error != B_OK)
28 			return error;
29 	}
30 
31 	// read/write
32 	off_t offset = request->Offset() + request->TransferredBytes();
33 	status_t error = writeToRequest
34 		? request->CopyData(buffer, offset, size)
35 		: request->CopyData(offset, buffer, size);
36 	if (error != B_OK)
37 		return error;
38 
39 	request->Advance(size);
40 	return B_OK;
41 }
42 
43 
44 // #pragma mark - public API
45 
46 
47 /*!	Returns whether the given I/O request is a write request. */
48 bool
49 io_request_is_write(const io_request* request)
50 {
51 	return request->IsWrite();
52 }
53 
54 
55 /*!	Returns whether the I/O request has VIP status. */
56 bool
57 io_request_is_vip(const io_request* request)
58 {
59 	return (request->Flags() & B_VIP_IO_REQUEST) != 0;
60 }
61 
62 
63 /*!	Returns the read/write offset of the given I/O request.
64 	This is the immutable offset the request was created with;
65 	read_from_io_request() and write_to_io_request() don't change it.
66 */
67 off_t
68 io_request_offset(const io_request* request)
69 {
70 	return request->Offset();
71 }
72 
73 
74 /*!	Returns the read/write length of the given I/O request.
75 	This is the immutable length the request was created with;
76 	read_from_io_request() and write_to_io_request() don't change it.
77 */
78 off_t
79 io_request_length(const io_request* request)
80 {
81 	return request->Length();
82 }
83 
84 
85 /*!	Reads data from the given I/O request into the given buffer and advances
86 	the request's transferred data pointer.
87 	Multiple calls to read_from_io_request() are allowed, but the total size
88 	must not exceed io_request_length(request).
89 */
90 status_t
91 read_from_io_request(io_request* request, void* buffer, size_t size)
92 {
93 	return transfer_io_request_data(request, buffer, size, false);
94 }
95 
96 
97 /*!	Writes data from the given buffer to the given I/O request and advances
98 	the request's transferred data pointer.
99 	Multiple calls to write_to_io_request() are allowed, but the total size
100 	must not exceed io_request_length(request).
101 */
102 status_t
103 write_to_io_request(io_request* request, const void* buffer, size_t size)
104 {
105 	return transfer_io_request_data(request, (void*)buffer, size, true);
106 }
107 
108 
109 /*!	Sets the given I/O request's status and notifies listeners that the request
110 	is finished.
111 */
112 void
113 notify_io_request(io_request* request, status_t status)
114 {
115 	request->SetStatusAndNotify(status);
116 }
117