|
5 | 5 | */
|
6 | 6 |
|
7 | 7 | #include <AK/Singleton.h>
|
| 8 | +#include <Kernel/Devices/BaseDevices.h> |
| 9 | +#include <Kernel/Devices/BlockDevice.h> |
| 10 | +#include <Kernel/Devices/CharacterDevice.h> |
8 | 11 | #include <Kernel/Devices/Device.h>
|
9 |
| -#include <Kernel/Devices/DeviceManagement.h> |
10 | 12 | #include <Kernel/FileSystem/InodeMetadata.h>
|
11 | 13 | #include <Kernel/FileSystem/SysFS/Component.h>
|
12 | 14 | #include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/BlockDevicesDirectory.h>
|
|
15 | 17 |
|
16 | 18 | namespace Kernel {
|
17 | 19 |
|
18 |
| -Device::Device(MajorNumber major, MinorNumber minor) |
19 |
| - : m_major(major) |
20 |
| - , m_minor(minor) |
| 20 | +struct AllDevicesDetails { |
| 21 | + SpinlockProtected<HashMap<u64, BlockDevice*>, LockRank::None> block_devices {}; |
| 22 | + SpinlockProtected<HashMap<u64, CharacterDevice*>, LockRank::None> char_devices {}; |
| 23 | + SpinlockProtected<CircularQueue<DeviceEvent, 100>, LockRank::None> event_queue {}; |
| 24 | + // NOTE: There's no locking on this pointer because we expect to initialize it once |
| 25 | + // and never touch it again. |
| 26 | + OwnPtr<BaseDevices> base_devices; |
| 27 | +}; |
| 28 | + |
| 29 | +static Singleton<AllDevicesDetails> s_all_details; |
| 30 | + |
| 31 | +SpinlockProtected<CircularQueue<DeviceEvent, 100>, LockRank::None>& Device::event_queue() |
21 | 32 | {
|
| 33 | + return s_all_details->event_queue; |
| 34 | +} |
| 35 | + |
| 36 | +BaseDevices* Device::base_devices() |
| 37 | +{ |
| 38 | + return s_all_details->base_devices.ptr(); |
| 39 | +} |
| 40 | + |
| 41 | +UNMAP_AFTER_INIT void Device::initialize_base_devices() |
| 42 | +{ |
| 43 | + auto base_devices = MUST(adopt_nonnull_own_or_enomem(new (nothrow) BaseDevices(*NullDevice::must_initialize(), *ConsoleDevice::must_create(), *DeviceControlDevice::must_create()))); |
| 44 | + s_all_details->base_devices = move(base_devices); |
| 45 | +} |
| 46 | + |
| 47 | +RefPtr<Device> Device::acquire_by_type_and_major_minor_numbers(DeviceNodeType type, MajorNumber major, MinorNumber minor) |
| 48 | +{ |
| 49 | + VERIFY(type == DeviceNodeType::Block || type == DeviceNodeType::Character); |
| 50 | + |
| 51 | + auto find_device_in_map = [major, minor](auto& map) -> RefPtr<Device> { |
| 52 | + auto it = map.find(encoded_device(major.value(), minor.value())); |
| 53 | + if (it == map.end()) |
| 54 | + return nullptr; |
| 55 | + return *it->value; |
| 56 | + }; |
| 57 | + |
| 58 | + if (type == DeviceNodeType::Block) { |
| 59 | + return s_all_details->block_devices.with([&](auto& map) -> RefPtr<Device> { |
| 60 | + return find_device_in_map(map); |
| 61 | + }); |
| 62 | + } |
| 63 | + |
| 64 | + return s_all_details->char_devices.with([&](auto& map) -> RefPtr<Device> { |
| 65 | + return find_device_in_map(map); |
| 66 | + }); |
22 | 67 | }
|
23 | 68 |
|
24 | 69 | void Device::before_will_be_destroyed_remove_from_device_management()
|
25 | 70 | {
|
26 |
| - DeviceManagement::the().before_device_removal({}, *this); |
| 71 | + before_device_removal({}, *this); |
27 | 72 | m_state = State::BeingRemoved;
|
28 | 73 | }
|
29 | 74 |
|
30 | 75 | void Device::after_inserting_add_to_device_management()
|
31 | 76 | {
|
32 |
| - DeviceManagement::the().after_inserting_device({}, *this); |
| 77 | + after_inserting_device({}, *this); |
| 78 | +} |
| 79 | + |
| 80 | +Device::Device(MajorNumber major, MinorNumber minor) |
| 81 | + : m_major(major) |
| 82 | + , m_minor(minor) |
| 83 | +{ |
33 | 84 | }
|
34 | 85 |
|
35 | 86 | ErrorOr<void> Device::after_inserting()
|
@@ -80,4 +131,52 @@ void Device::process_next_queued_request(Badge<AsyncDeviceRequest>, AsyncDeviceR
|
80 | 131 | evaluate_block_conditions();
|
81 | 132 | }
|
82 | 133 |
|
| 134 | +void Device::after_inserting_device(Badge<Device>, Device& device) |
| 135 | +{ |
| 136 | + if (device.is_block_device()) { |
| 137 | + s_all_details->block_devices.with([&](auto& map) -> void { |
| 138 | + add_device_to_map<BlockDevice>(map, device); |
| 139 | + }); |
| 140 | + } else { |
| 141 | + VERIFY(device.is_character_device()); |
| 142 | + s_all_details->char_devices.with([&](auto& map) -> void { |
| 143 | + add_device_to_map<CharacterDevice>(map, device); |
| 144 | + }); |
| 145 | + } |
| 146 | + |
| 147 | + s_all_details->event_queue.with([&](auto& queue) { |
| 148 | + DeviceEvent event { DeviceEvent::State::Inserted, device.is_block_device(), device.major().value(), device.minor().value() }; |
| 149 | + queue.enqueue(event); |
| 150 | + }); |
| 151 | + |
| 152 | + if (s_all_details->base_devices) |
| 153 | + s_all_details->base_devices->device_control_device->evaluate_block_conditions(); |
| 154 | +} |
| 155 | + |
| 156 | +void Device::before_device_removal(Badge<Device>, Device& device) |
| 157 | +{ |
| 158 | + u64 device_id = encoded_device(device.major(), device.minor()); |
| 159 | + |
| 160 | + if (device.is_block_device()) { |
| 161 | + s_all_details->block_devices.with([&](auto& map) -> void { |
| 162 | + VERIFY(map.contains(device_id)); |
| 163 | + map.remove(encoded_device(device.major(), device.minor())); |
| 164 | + }); |
| 165 | + } else { |
| 166 | + VERIFY(device.is_character_device()); |
| 167 | + s_all_details->char_devices.with([&](auto& map) -> void { |
| 168 | + VERIFY(map.contains(device_id)); |
| 169 | + map.remove(encoded_device(device.major(), device.minor())); |
| 170 | + }); |
| 171 | + } |
| 172 | + |
| 173 | + s_all_details->event_queue.with([&](auto& queue) { |
| 174 | + DeviceEvent event { DeviceEvent::State::Removed, device.is_block_device(), device.major().value(), device.minor().value() }; |
| 175 | + queue.enqueue(event); |
| 176 | + }); |
| 177 | + |
| 178 | + if (s_all_details->base_devices) |
| 179 | + s_all_details->base_devices->device_control_device->evaluate_block_conditions(); |
| 180 | +} |
| 181 | + |
83 | 182 | }
|
0 commit comments