From 1ca0b78f54cb755cec6fe8a23e018bad32a91bf5 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 19 Nov 2009 07:38:33 +0000 Subject: [PATCH] Extended the public I/O request C API. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34121 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/io_requests.h | 10 ++- .../kernel/device_manager/io_requests.cpp | 85 ++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/headers/os/drivers/io_requests.h b/headers/os/drivers/io_requests.h index 9331eea925..b7eb4f7cd5 100644 --- a/headers/os/drivers/io_requests.h +++ b/headers/os/drivers/io_requests.h @@ -19,8 +19,14 @@ typedef struct IORequest io_request; extern "C" { #endif -bool io_request_is_write(const io_request* request); -void notify_io_request(io_request* request, status_t status); +bool io_request_is_write(const io_request* request); +off_t io_request_offset(const io_request* request); +off_t io_request_length(const io_request* request); +status_t read_from_io_request(io_request* request, void* buffer, + size_t size); +status_t write_to_io_request(io_request* request, const void* buffer, + size_t size); +void notify_io_request(io_request* request, status_t status); #ifdef __cplusplus } diff --git a/src/system/kernel/device_manager/io_requests.cpp b/src/system/kernel/device_manager/io_requests.cpp index 7c3c79f679..4f6e121899 100644 --- a/src/system/kernel/device_manager/io_requests.cpp +++ b/src/system/kernel/device_manager/io_requests.cpp @@ -8,6 +8,41 @@ #include "IORequest.h" +// #pragma mark - static helpers + + +status_t +transfer_io_request_data(io_request* request, void* buffer, size_t size, + bool isWrite) +{ + if (isWrite != request->IsWrite() || request->RemainingBytes() < size) + return B_BAD_VALUE; + + // lock the request buffer memory, if it is user memory + IOBuffer* ioBuffer = request->Buffer(); + if (ioBuffer->IsUser() && !ioBuffer->IsMemoryLocked()) { + status_t error = ioBuffer->LockMemory(request->Team(), isWrite); + if (error != B_OK) + return error; + } + + // read/write + off_t offset = request->Offset() + request->TransferredBytes(); + status_t error = isWrite + ? request->CopyData(buffer, offset, size) + : request->CopyData(offset, buffer, size); + if (error != B_OK) + return error; + + request->Advance(size); + return B_OK; +} + + +// #pragma mark - public API + + +/*! Returns whether the given I/O request is a write request. */ bool io_request_is_write(const io_request* request) { @@ -15,9 +50,57 @@ io_request_is_write(const io_request* request) } +/*! Returns the read/write offset of the given I/O request. + This is the immutable offset the request was created with; + read_from_io_request() and write_to_io_request() don't change it. +*/ +off_t +io_request_offset(const io_request* request) +{ + return request->Offset(); +} + + +/*! Returns the read/write length of the given I/O request. + This is the immutable length the request was created with; + read_from_io_request() and write_to_io_request() don't change it. +*/ +off_t +io_request_length(const io_request* request) +{ + return request->Length(); +} + + +/*! Reads data from the given I/O request into the given buffer and advances + the request's transferred data pointer. + Multiple calls to read_from_io_request() are allowed, but the total size + must not exceed io_request_length(request). +*/ +status_t +read_from_io_request(io_request* request, void* buffer, size_t size) +{ + return transfer_io_request_data(request, buffer, size, false); +} + + +/*! Writes data from the given buffer to the given I/O request and advances + the request's transferred data pointer. + Multiple calls to write_to_io_request() are allowed, but the total size + must not exceed io_request_length(request). +*/ +status_t +write_to_io_request(io_request* request, const void* buffer, size_t size) +{ + return transfer_io_request_data(request, (void*)buffer, size, true); +} + + +/*! Sets the given I/O request's status and notifies listeners that the request + is finished. +*/ void notify_io_request(io_request* request, status_t status) { request->SetStatusAndNotify(status); } -