mirror of
https://github.com/RGBCube/serenity
synced 2025-05-24 05:45:07 +00:00

It is starting to get a little messy with how each device can try to add or remove itself to either /sys/dev/block or /sys/dev/char directories. To better do this, we introduce 4 virtual methods to take care of that, so until we ensure all nodes in /sys/dev/block and /sys/dev/char are actual symlinks, we allow the Device base class to call virtual methods upon insertion or before being destroying, so it add itself elegantly to either of these directories or remove itself when needed. For special cases where we need to create symlinks, we have two virtual methods to be called otherwise to do almost the same thing mentioned before, but to use symlinks instead.
95 lines
2.9 KiB
C++
95 lines
2.9 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/IntegralMath.h>
|
|
#include <AK/Weakable.h>
|
|
#include <Kernel/Devices/Device.h>
|
|
|
|
namespace Kernel {
|
|
|
|
class AsyncBlockDeviceRequest;
|
|
|
|
class BlockDevice : public Device {
|
|
public:
|
|
virtual ~BlockDevice() override;
|
|
|
|
size_t block_size() const { return m_block_size; }
|
|
u8 block_size_log() const { return m_block_size_log; }
|
|
virtual bool is_seekable() const override { return true; }
|
|
|
|
bool read_block(u64 index, UserOrKernelBuffer&);
|
|
bool write_block(u64 index, UserOrKernelBuffer const&);
|
|
|
|
virtual void start_request(AsyncBlockDeviceRequest&) = 0;
|
|
|
|
protected:
|
|
BlockDevice(MajorNumber major, MinorNumber minor, size_t block_size = PAGE_SIZE)
|
|
: Device(major, minor)
|
|
, m_block_size(block_size)
|
|
{
|
|
// 512 is the minimum sector size in most block devices
|
|
VERIFY(m_block_size >= 512);
|
|
VERIFY(is_power_of_two(m_block_size));
|
|
m_block_size_log = AK::log2(m_block_size);
|
|
}
|
|
|
|
protected:
|
|
virtual bool is_block_device() const final { return true; }
|
|
|
|
virtual void after_inserting_add_symlink_to_device_identifier_directory() override final;
|
|
virtual void before_will_be_destroyed_remove_symlink_from_device_identifier_directory() override final;
|
|
|
|
private:
|
|
// FIXME: These methods will be eventually removed after all nodes in /sys/dev/block/ are symlinks
|
|
virtual void after_inserting_add_to_device_identifier_directory() override final;
|
|
virtual void before_will_be_destroyed_remove_from_device_identifier_directory() override final;
|
|
|
|
size_t m_block_size { 0 };
|
|
u8 m_block_size_log { 0 };
|
|
};
|
|
|
|
class AsyncBlockDeviceRequest final : public AsyncDeviceRequest {
|
|
public:
|
|
enum RequestType {
|
|
Read,
|
|
Write
|
|
};
|
|
AsyncBlockDeviceRequest(Device& block_device, RequestType request_type,
|
|
u64 block_index, u32 block_count, UserOrKernelBuffer const& 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; }
|
|
size_t block_size() const { return m_block_device.block_size(); }
|
|
UserOrKernelBuffer& buffer() { return m_buffer; }
|
|
UserOrKernelBuffer const& 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;
|
|
};
|
|
|
|
}
|