Serenity Operating System
1/*
2 * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/Bus/PCI/API.h>
8#include <Kernel/Bus/PCI/Access.h>
9#include <Kernel/FileSystem/SysFS/Subsystems/Bus/PCI/DeviceAttribute.h>
10#include <Kernel/Sections.h>
11
12namespace Kernel {
13
14StringView PCIDeviceAttributeSysFSComponent::name() const
15{
16 switch (m_offset) {
17 case PCI::RegisterOffset::VENDOR_ID:
18 return "vendor"sv;
19 case PCI::RegisterOffset::DEVICE_ID:
20 return "device_id"sv;
21 case PCI::RegisterOffset::CLASS:
22 return "class"sv;
23 case PCI::RegisterOffset::SUBCLASS:
24 return "subclass"sv;
25 case PCI::RegisterOffset::REVISION_ID:
26 return "revision"sv;
27 case PCI::RegisterOffset::PROG_IF:
28 return "progif"sv;
29 case PCI::RegisterOffset::SUBSYSTEM_VENDOR_ID:
30 return "subsystem_vendor"sv;
31 case PCI::RegisterOffset::SUBSYSTEM_ID:
32 return "subsystem_id"sv;
33 case PCI::RegisterOffset::BAR0:
34 return "bar0"sv;
35 case PCI::RegisterOffset::BAR1:
36 return "bar1"sv;
37 case PCI::RegisterOffset::BAR2:
38 return "bar2"sv;
39 case PCI::RegisterOffset::BAR3:
40 return "bar3"sv;
41 case PCI::RegisterOffset::BAR4:
42 return "bar4"sv;
43 case PCI::RegisterOffset::BAR5:
44 return "bar5"sv;
45 default:
46 VERIFY_NOT_REACHED();
47 }
48}
49
50NonnullLockRefPtr<PCIDeviceAttributeSysFSComponent> PCIDeviceAttributeSysFSComponent::create(PCIDeviceSysFSDirectory const& device, PCI::RegisterOffset offset, size_t field_bytes_width)
51{
52 return adopt_lock_ref(*new (nothrow) PCIDeviceAttributeSysFSComponent(device, offset, field_bytes_width));
53}
54
55PCIDeviceAttributeSysFSComponent::PCIDeviceAttributeSysFSComponent(PCIDeviceSysFSDirectory const& device, PCI::RegisterOffset offset, size_t field_bytes_width)
56 : SysFSComponent()
57 , m_device(device)
58 , m_offset(offset)
59 , m_field_bytes_width(field_bytes_width)
60{
61}
62
63ErrorOr<size_t> PCIDeviceAttributeSysFSComponent::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription*) const
64{
65 auto blob = TRY(try_to_generate_buffer());
66
67 if ((size_t)offset >= blob->size())
68 return 0;
69
70 ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count));
71 TRY(buffer.write(blob->data() + offset, nread));
72 return nread;
73}
74
75ErrorOr<NonnullOwnPtr<KBuffer>> PCIDeviceAttributeSysFSComponent::try_to_generate_buffer() const
76{
77 OwnPtr<KString> value;
78 SpinlockLocker locker(m_device->device_identifier().operation_lock());
79 switch (m_field_bytes_width) {
80 case 1:
81 value = TRY(KString::formatted("{:#x}", PCI::read8_locked(m_device->device_identifier(), m_offset)));
82 break;
83 case 2:
84 value = TRY(KString::formatted("{:#x}", PCI::read16_locked(m_device->device_identifier(), m_offset)));
85 break;
86 case 4:
87 value = TRY(KString::formatted("{:#x}", PCI::read32_locked(m_device->device_identifier(), m_offset)));
88 break;
89 default:
90 VERIFY_NOT_REACHED();
91 }
92
93 return KBuffer::try_create_with_bytes("PCIDeviceAttributeSysFSComponent: Device address"sv, value->view().bytes());
94}
95}