ladybird/Kernel/Devices/BlockDevice.h
Liav A fb7b4caa57 Kernel/Storage: Implement basic AHCI hotplug support
This is really a basic support for AHCI hotplug events, so we know how
to add a node representing the device in /sys/dev/block and removing it
according to the event type (insertion/removal).

This change doesn't take into account what happens if the device was
mounted or a read/write operation is being handled.

For this to work correctly, StorageManagement now uses the Singleton
container, as it might be accessed simultaneously from many CPUs
for hotplug events. DiskPartition holds a WeakPtr instead of a RefPtr,
to allow removal of a StorageDevice object from the heap.
StorageDevices are now stored and being referenced to via an
IntrusiveList to make it easier to remove them on hotplug event.

In future changes, all of the stated above might change, but for now,
this commit represents the least amount of changes to make everything
to work correctly.
2021-09-08 00:42:20 +02:00

80 lines
2.0 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Weakable.h>
#include <Kernel/Devices/Device.h>
namespace Kernel {
class BlockDevice;
class AsyncBlockDeviceRequest final : public AsyncDeviceRequest {
public:
enum RequestType {
Read,
Write
};
AsyncBlockDeviceRequest(Device& block_device, RequestType request_type,
u64 block_index, u32 block_count, const UserOrKernelBuffer& buffer, size_t buffer_size);
RequestType request_type() const { return m_request_type; }
u64 block_index() const { return m_block_index; }
u32 block_count() const { return m_block_count; }
UserOrKernelBuffer& buffer() { return m_buffer; }
const UserOrKernelBuffer& buffer() const { return m_buffer; }
size_t buffer_size() const { return m_buffer_size; }
virtual void start() override;
virtual StringView name() const override
{
switch (m_request_type) {
case Read:
return "BlockDeviceRequest (read)"sv;
case Write:
return "BlockDeviceRequest (write)"sv;
default:
VERIFY_NOT_REACHED();
}
}
private:
BlockDevice& m_block_device;
const RequestType m_request_type;
const u64 m_block_index;
const u32 m_block_count;
UserOrKernelBuffer m_buffer;
const size_t m_buffer_size;
};
class BlockDevice : public Device {
public:
virtual ~BlockDevice() override;
size_t block_size() const { return m_block_size; }
virtual bool is_seekable() const override { return true; }
bool read_block(u64 index, UserOrKernelBuffer&);
bool write_block(u64 index, const UserOrKernelBuffer&);
virtual void start_request(AsyncBlockDeviceRequest&) = 0;
protected:
BlockDevice(unsigned major, unsigned minor, size_t block_size = PAGE_SIZE)
: Device(major, minor)
, m_block_size(block_size)
{
}
private:
virtual bool is_block_device() const final { return true; }
size_t m_block_size { 0 };
};
}