Definitions.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Badge.h>
  8. #include <AK/DistinctNumeric.h>
  9. #include <AK/Function.h>
  10. #include <AK/Types.h>
  11. #include <AK/Vector.h>
  12. #include <Kernel/Debug.h>
  13. #include <Kernel/Locking/Spinlock.h>
  14. #include <Kernel/PhysicalAddress.h>
  15. namespace Kernel::PCI {
  16. enum class HeaderType {
  17. Device = 0,
  18. Bridge = 1,
  19. };
  20. enum class HeaderType0BaseRegister {
  21. BAR0 = 0,
  22. BAR1,
  23. BAR2,
  24. BAR3,
  25. BAR4,
  26. BAR5,
  27. };
  28. enum class BARSpaceType {
  29. IOSpace,
  30. Memory16BitSpace,
  31. Memory32BitSpace,
  32. Memory64BitSpace,
  33. };
  34. enum class RegisterOffset {
  35. VENDOR_ID = 0x00, // word
  36. DEVICE_ID = 0x02, // word
  37. COMMAND = 0x04, // word
  38. STATUS = 0x06, // word
  39. REVISION_ID = 0x08, // byte
  40. PROG_IF = 0x09, // byte
  41. SUBCLASS = 0x0a, // byte
  42. CLASS = 0x0b, // byte
  43. CACHE_LINE_SIZE = 0x0c, // byte
  44. LATENCY_TIMER = 0x0d, // byte
  45. HEADER_TYPE = 0x0e, // byte
  46. BIST = 0x0f, // byte
  47. BAR0 = 0x10, // u32
  48. BAR1 = 0x14, // u32
  49. BAR2 = 0x18, // u32
  50. SECONDARY_BUS = 0x19, // byte
  51. BAR3 = 0x1C, // u32
  52. BAR4 = 0x20, // u32
  53. BAR5 = 0x24, // u32
  54. SUBSYSTEM_VENDOR_ID = 0x2C, // u16
  55. SUBSYSTEM_ID = 0x2E, // u16
  56. EXPANSION_ROM_POINTER = 0x30, // u32
  57. CAPABILITIES_POINTER = 0x34, // u8
  58. INTERRUPT_LINE = 0x3C, // byte
  59. INTERRUPT_PIN = 0x3D, // byte
  60. };
  61. enum class Limits {
  62. MaxDevicesPerBus = 32,
  63. MaxBusesPerDomain = 256,
  64. MaxFunctionsPerDevice = 8,
  65. };
  66. static constexpr u16 address_port = 0xcf8;
  67. static constexpr u16 value_port = 0xcfc;
  68. static constexpr size_t mmio_device_space_size = 4096;
  69. static constexpr u16 none_value = 0xffff;
  70. static constexpr size_t memory_range_per_bus = mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice) * to_underlying(Limits::MaxDevicesPerBus);
  71. // Taken from https://pcisig.com/sites/default/files/files/PCI_Code-ID_r_1_11__v24_Jan_2019.pdf
  72. enum class ClassID {
  73. MassStorage = 0x1,
  74. Multimedia = 0x4,
  75. Bridge = 0x6,
  76. };
  77. namespace MassStorage {
  78. enum class SubclassID {
  79. IDEController = 0x1,
  80. SATAController = 0x6,
  81. NVMeController = 0x8,
  82. };
  83. enum class SATAProgIF {
  84. AHCI = 0x1,
  85. };
  86. }
  87. namespace Multimedia {
  88. enum class SubclassID {
  89. AudioController = 0x1,
  90. };
  91. }
  92. namespace Bridge {
  93. enum class SubclassID {
  94. PCI_TO_PCI = 0x4,
  95. };
  96. }
  97. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, CapabilityID);
  98. namespace Capabilities {
  99. enum ID {
  100. Null = 0x0,
  101. MSI = 0x5,
  102. VendorSpecific = 0x9,
  103. MSIX = 0x11,
  104. };
  105. }
  106. struct HardwareID {
  107. u16 vendor_id { 0 };
  108. u16 device_id { 0 };
  109. bool is_null() const { return !vendor_id && !device_id; }
  110. bool operator==(HardwareID const& other) const
  111. {
  112. return vendor_id == other.vendor_id && device_id == other.device_id;
  113. }
  114. bool operator!=(HardwareID const& other) const
  115. {
  116. return vendor_id != other.vendor_id || device_id != other.device_id;
  117. }
  118. };
  119. class Domain {
  120. public:
  121. Domain() = delete;
  122. Domain(u32 domain_number, u8 start_bus, u8 end_bus)
  123. : m_domain_number(domain_number)
  124. , m_start_bus(start_bus)
  125. , m_end_bus(end_bus)
  126. {
  127. }
  128. u8 start_bus() const { return m_start_bus; }
  129. u8 end_bus() const { return m_end_bus; }
  130. u32 domain_number() const { return m_domain_number; }
  131. private:
  132. u32 m_domain_number;
  133. u8 m_start_bus;
  134. u8 m_end_bus;
  135. };
  136. struct Address {
  137. public:
  138. Address() = default;
  139. Address(u32 domain)
  140. : m_domain(domain)
  141. , m_bus(0)
  142. , m_device(0)
  143. , m_function(0)
  144. {
  145. }
  146. Address(u32 domain, u8 bus, u8 device, u8 function)
  147. : m_domain(domain)
  148. , m_bus(bus)
  149. , m_device(device)
  150. , m_function(function)
  151. {
  152. }
  153. Address(Address const& address) = default;
  154. bool is_null() const { return !m_bus && !m_device && !m_function; }
  155. operator bool() const { return !is_null(); }
  156. // Disable default implementations that would use surprising integer promotion.
  157. bool operator<=(Address const&) const = delete;
  158. bool operator>=(Address const&) const = delete;
  159. bool operator<(Address const&) const = delete;
  160. bool operator>(Address const&) const = delete;
  161. bool operator==(Address const& other) const
  162. {
  163. if (this == &other)
  164. return true;
  165. return m_domain == other.m_domain && m_bus == other.m_bus && m_device == other.m_device && m_function == other.m_function;
  166. }
  167. bool operator!=(Address const& other) const
  168. {
  169. return !(*this == other);
  170. }
  171. u32 domain() const { return m_domain; }
  172. u8 bus() const { return m_bus; }
  173. u8 device() const { return m_device; }
  174. u8 function() const { return m_function; }
  175. private:
  176. u32 m_domain { 0 };
  177. u8 m_bus { 0 };
  178. u8 m_device { 0 };
  179. u8 m_function { 0 };
  180. };
  181. class Capability {
  182. public:
  183. Capability(Address address, u8 id, u8 ptr)
  184. : m_address(address)
  185. , m_id(id)
  186. , m_ptr(ptr)
  187. {
  188. }
  189. CapabilityID id() const { return m_id; }
  190. u8 read8(size_t offset) const;
  191. u16 read16(size_t offset) const;
  192. u32 read32(size_t offset) const;
  193. private:
  194. const Address m_address;
  195. const CapabilityID m_id;
  196. const u8 m_ptr;
  197. };
  198. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, ClassCode);
  199. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, SubclassCode);
  200. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, ProgrammingInterface);
  201. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, RevisionID);
  202. AK_TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemID);
  203. AK_TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemVendorID);
  204. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, InterruptLine);
  205. AK_TYPEDEF_DISTINCT_ORDERED_ID(u8, InterruptPin);
  206. class Access;
  207. class EnumerableDeviceIdentifier {
  208. public:
  209. EnumerableDeviceIdentifier(Address address, HardwareID hardware_id, RevisionID revision_id, ClassCode class_code, SubclassCode subclass_code, ProgrammingInterface prog_if, SubsystemID subsystem_id, SubsystemVendorID subsystem_vendor_id, InterruptLine interrupt_line, InterruptPin interrupt_pin, Vector<Capability> const& capabilities)
  210. : m_address(address)
  211. , m_hardware_id(hardware_id)
  212. , m_revision_id(revision_id)
  213. , m_class_code(class_code)
  214. , m_subclass_code(subclass_code)
  215. , m_prog_if(prog_if)
  216. , m_subsystem_id(subsystem_id)
  217. , m_subsystem_vendor_id(subsystem_vendor_id)
  218. , m_interrupt_line(interrupt_line)
  219. , m_interrupt_pin(interrupt_pin)
  220. , m_capabilities(capabilities)
  221. {
  222. if constexpr (PCI_DEBUG) {
  223. for (auto const& capability : capabilities)
  224. dbgln("{} has capability {}", address, capability.id());
  225. }
  226. }
  227. Vector<Capability> const& capabilities() const { return m_capabilities; }
  228. HardwareID const& hardware_id() const { return m_hardware_id; }
  229. Address const& address() const { return m_address; }
  230. RevisionID revision_id() const { return m_revision_id; }
  231. ClassCode class_code() const { return m_class_code; }
  232. SubclassCode subclass_code() const { return m_subclass_code; }
  233. ProgrammingInterface prog_if() const { return m_prog_if; }
  234. SubsystemID subsystem_id() const { return m_subsystem_id; }
  235. SubsystemVendorID subsystem_vendor_id() const { return m_subsystem_vendor_id; }
  236. InterruptLine interrupt_line() const { return m_interrupt_line; }
  237. InterruptPin interrupt_pin() const { return m_interrupt_pin; }
  238. void apply_subclass_code_change(Badge<Access>, SubclassCode new_subclass)
  239. {
  240. m_subclass_code = new_subclass;
  241. }
  242. void apply_prog_if_change(Badge<Access>, ProgrammingInterface new_progif)
  243. {
  244. m_prog_if = new_progif;
  245. }
  246. protected:
  247. Address m_address;
  248. HardwareID m_hardware_id;
  249. RevisionID m_revision_id;
  250. ClassCode m_class_code;
  251. SubclassCode m_subclass_code;
  252. ProgrammingInterface m_prog_if;
  253. SubsystemID m_subsystem_id;
  254. SubsystemVendorID m_subsystem_vendor_id;
  255. InterruptLine m_interrupt_line;
  256. InterruptPin m_interrupt_pin;
  257. Vector<Capability> m_capabilities;
  258. };
  259. class DeviceIdentifier
  260. : public RefCounted<DeviceIdentifier>
  261. , public EnumerableDeviceIdentifier {
  262. AK_MAKE_NONCOPYABLE(DeviceIdentifier);
  263. public:
  264. static ErrorOr<NonnullRefPtr<DeviceIdentifier>> from_enumerable_identifier(EnumerableDeviceIdentifier const& other_identifier);
  265. Spinlock<LockRank::None>& operation_lock() { return m_operation_lock; }
  266. Spinlock<LockRank::None>& operation_lock() const { return m_operation_lock; }
  267. virtual ~DeviceIdentifier() = default;
  268. private:
  269. DeviceIdentifier(EnumerableDeviceIdentifier const& other_identifier)
  270. : EnumerableDeviceIdentifier(other_identifier.address(),
  271. other_identifier.hardware_id(),
  272. other_identifier.revision_id(),
  273. other_identifier.class_code(),
  274. other_identifier.subclass_code(),
  275. other_identifier.prog_if(),
  276. other_identifier.subsystem_id(),
  277. other_identifier.subsystem_vendor_id(),
  278. other_identifier.interrupt_line(),
  279. other_identifier.interrupt_pin(),
  280. other_identifier.capabilities())
  281. {
  282. }
  283. mutable Spinlock<LockRank::None> m_operation_lock;
  284. };
  285. class Domain;
  286. class Device;
  287. }
  288. template<>
  289. struct AK::Formatter<Kernel::PCI::Address> : Formatter<FormatString> {
  290. ErrorOr<void> format(FormatBuilder& builder, Kernel::PCI::Address value)
  291. {
  292. return Formatter<FormatString>::format(
  293. builder,
  294. "PCI [{:04x}:{:02x}:{:02x}:{:02x}]"sv, value.domain(), value.bus(), value.device(), value.function());
  295. }
  296. };
  297. template<>
  298. struct AK::Formatter<Kernel::PCI::HardwareID> : Formatter<FormatString> {
  299. ErrorOr<void> format(FormatBuilder& builder, Kernel::PCI::HardwareID value)
  300. {
  301. return Formatter<FormatString>::format(
  302. builder,
  303. "PCI::HardwareID [{:04x}:{:04x}]"sv, value.vendor_id, value.device_id);
  304. }
  305. };