mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 10:55:06 +00:00
Kernel: Implement an asynchronous device request stack
This allows issuing asynchronous requests for devices and waiting on the completion of the request. The requests can cascade into multiple sub-requests. Since IRQs may complete at any time, if the current process is no longer the same that started the process, we need to swich the paging context before accessing user buffers. Change the PATA driver to use this model.
This commit is contained in:
parent
96081010dc
commit
2fd5ce1eb0
17 changed files with 804 additions and 246 deletions
|
@ -28,18 +28,66 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
AsyncBlockDeviceRequest::AsyncBlockDeviceRequest(Device& block_device, RequestType request_type, u32 block_index, u32 block_count, const UserOrKernelBuffer& buffer, size_t buffer_size)
|
||||
: AsyncDeviceRequest(block_device)
|
||||
, m_block_device(static_cast<BlockDevice&>(block_device))
|
||||
, m_request_type(request_type)
|
||||
, m_block_index(block_index)
|
||||
, m_block_count(block_count)
|
||||
, m_buffer(buffer)
|
||||
, m_buffer_size(buffer_size)
|
||||
{
|
||||
}
|
||||
|
||||
void AsyncBlockDeviceRequest::start()
|
||||
{
|
||||
m_block_device.start_request(*this);
|
||||
}
|
||||
|
||||
BlockDevice::~BlockDevice()
|
||||
{
|
||||
}
|
||||
|
||||
bool BlockDevice::read_block(unsigned index, UserOrKernelBuffer& buffer) const
|
||||
bool BlockDevice::read_block(unsigned index, UserOrKernelBuffer& buffer)
|
||||
{
|
||||
return const_cast<BlockDevice*>(this)->read_blocks(index, 1, buffer);
|
||||
auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, 1, buffer, 512);
|
||||
switch (read_request->wait().request_result()) {
|
||||
case AsyncDeviceRequest::Success:
|
||||
return true;
|
||||
case AsyncDeviceRequest::Failure:
|
||||
dbg() << "BlockDevice::read_block(" << index << ") IO error";
|
||||
break;
|
||||
case AsyncDeviceRequest::MemoryFault:
|
||||
dbg() << "BlockDevice::read_block(" << index << ") EFAULT";
|
||||
break;
|
||||
case AsyncDeviceRequest::Cancelled:
|
||||
dbg() << "BlockDevice::read_block(" << index << ") cancelled";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BlockDevice::write_block(unsigned index, const UserOrKernelBuffer& data)
|
||||
bool BlockDevice::write_block(unsigned index, const UserOrKernelBuffer& buffer)
|
||||
{
|
||||
return write_blocks(index, 1, data);
|
||||
auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, 1, buffer, 512);
|
||||
switch (write_request->wait().request_result()) {
|
||||
case AsyncDeviceRequest::Success:
|
||||
return true;
|
||||
case AsyncDeviceRequest::Failure:
|
||||
dbg() << "BlockDevice::write_block(" << index << ") IO error";
|
||||
break;
|
||||
case AsyncDeviceRequest::MemoryFault:
|
||||
dbg() << "BlockDevice::write_block(" << index << ") EFAULT";
|
||||
break;
|
||||
case AsyncDeviceRequest::Cancelled:
|
||||
dbg() << "BlockDevice::write_block(" << index << ") cancelled";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue