aboutsummaryrefslogtreecommitdiff
path: root/src/lib/pci.zig
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-05-23 13:48:01 +0200
committerHimbeer <himbeer@disroot.org>2024-05-23 13:48:01 +0200
commit3274a700daff545437f919041cbdce6938eede06 (patch)
tree60a4ec5ebb1406af20733027a2bb4a5d54e54908 /src/lib/pci.zig
parent0f61d3bed969fecb35e438bfac2fe34f588834c6 (diff)
Drop FDT support in favor of custom HWI format
Fixes numerous parsing bugs and increases efficiency. The kernel now runs successfully on the Lichee Pi 4A.
Diffstat (limited to 'src/lib/pci.zig')
-rw-r--r--src/lib/pci.zig761
1 files changed, 761 insertions, 0 deletions
diff --git a/src/lib/pci.zig b/src/lib/pci.zig
new file mode 100644
index 0000000..7b862ee
--- /dev/null
+++ b/src/lib/pci.zig
@@ -0,0 +1,761 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const std = @import("std");
+
+const hwinfo = @import("hwinfo.zig");
+
+pub const Error = error{
+ NoRootNode,
+ NoSoCnode,
+ NoAddrCells,
+ NoSizeCells,
+ NoPcinode,
+ NoUnitAddr,
+ NoReg,
+ NoCompatInfo,
+ Incompatible,
+};
+
+pub const CamType = enum {
+ conventional,
+ enhanced,
+};
+
+pub const Controller = union(CamType) {
+ conventional: CamController,
+ enhanced: EcamController,
+
+ pub fn cfgSpace(self: Controller, bus: u8, device: u5, function: u3) *volatile CfgSpace {
+ return switch (self) {
+ .conventional => |controller| controller.cfgSpace(bus, device, function),
+ .enhanced => |controller| controller.cfgSpace(bus, device, function),
+ };
+ }
+};
+
+pub const CamController = struct {
+ reg: []volatile u8,
+
+ pub fn cfgSpace(self: CamController, bus: u8, device: u5, function: u3) *volatile CfgSpace {
+ const mmio_base = @intFromPtr(self.reg.ptr);
+ const addr = mmio_base + ((@as(usize, bus) * 0x100) + (@as(usize, device) * 0x08) + function) * 0x1000;
+ return @ptrFromInt(addr);
+ }
+};
+
+pub const EcamController = struct {
+ reg: []volatile u8,
+
+ pub fn cfgSpace(self: EcamController, bus: u8, device: u5, function: u3) *volatile CfgSpace {
+ const mmio_base = @intFromPtr(self.reg.ptr);
+ const addr = mmio_base + ((@as(usize, bus) * 0x100) + (@as(usize, device) * 0x08) + function) * 0x1000;
+ return @ptrFromInt(addr);
+ }
+};
+
+pub const HeaderType = enum(u8) {
+ general = 0x0,
+ pci2pci = 0x1,
+ pci2cardbus = 0x2,
+};
+
+pub const Header = packed union {
+ general: GeneralHeader,
+ pci2pci: Pci2Pciheader,
+ pci2cardbus: Pci2CardBusHeader,
+};
+
+pub const GeneralHeader = packed struct(u384) {
+ base_addr0: u32,
+ base_addr1: u32,
+ base_addr2: u32,
+ base_addr3: u32,
+ base_addr4: u32,
+ base_addr5: u32,
+ cardbus_cis_pointer: u32,
+ subsystem_vendor_id: u16,
+ subsystem_id: u16,
+ expansion_rom_base_addr: u32,
+ capabilities_pointer: u8,
+ reserved0: u24,
+ reserved1: u32,
+ interrupt_line: u8,
+ interrupt_pin: u8,
+ min_grant: u8,
+ max_latency: u8,
+
+ pub fn getBaseAddr0(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr0);
+ }
+
+ pub fn getBaseAddr1(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr1);
+ }
+
+ pub fn getBaseAddr2(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr2);
+ }
+
+ pub fn getBaseAddr3(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr3);
+ }
+
+ pub fn getBaseAddr4(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr4);
+ }
+
+ pub fn getBaseAddr5(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr5);
+ }
+
+ pub fn getCardBusCisPointer(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.cardbus_cis_pointer);
+ }
+
+ pub fn getSubsystemVendorId(self: *const volatile GeneralHeader) u16 {
+ return std.mem.littleToNative(u16, self.subsystem_vendor_id);
+ }
+
+ pub fn getSubsystemId(self: *const volatile GeneralHeader) u16 {
+ return std.mem.littleToNative(u16, self.subsystem_id);
+ }
+
+ pub fn getExpansionRomBaseAddr(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.expansion_rom_base_addr);
+ }
+
+ pub fn getCapabilitiesPointer(self: *const volatile GeneralHeader) u8 {
+ return std.mem.littleToNative(u8, self.capabilities_pointer);
+ }
+
+ pub fn getReserved0(self: *const volatile GeneralHeader) u24 {
+ return std.mem.littleToNative(u24, self.reserved0);
+ }
+
+ pub fn getReserved1(self: *const volatile GeneralHeader) u32 {
+ return std.mem.littleToNative(u32, self.reserved1);
+ }
+
+ pub fn getInterruptLine(self: *const volatile GeneralHeader) u8 {
+ return std.mem.littleToNative(u8, self.interrupt_line);
+ }
+
+ pub fn getInterruptPin(self: *const volatile GeneralHeader) u8 {
+ return std.mem.littleToNative(u8, self.interrupt_pin);
+ }
+
+ pub fn getMinGrant(self: *const volatile GeneralHeader) u8 {
+ return std.mem.littleToNative(u8, self.min_grant);
+ }
+
+ pub fn getMaxLatency(self: *const volatile GeneralHeader) u8 {
+ return std.mem.littleToNative(u8, self.max_latency);
+ }
+
+ pub fn setBaseAddr0(self: *const volatile GeneralHeader, new_base_addr0: u32) void {
+ self.base_addr0 = std.mem.nativeToLittle(u32, new_base_addr0);
+ }
+
+ pub fn setBaseAddr1(self: *const volatile GeneralHeader, new_base_addr1: u32) void {
+ self.base_addr1 = std.mem.nativeToLittle(u32, new_base_addr1);
+ }
+
+ pub fn setBaseAddr2(self: *const volatile GeneralHeader, new_base_addr2: u32) void {
+ self.base_addr2 = std.mem.nativeToLittle(u32, new_base_addr2);
+ }
+
+ pub fn setBaseAddr3(self: *const volatile GeneralHeader, new_base_addr3: u32) void {
+ self.base_addr3 = std.mem.nativeToLittle(u32, new_base_addr3);
+ }
+
+ pub fn setBaseAddr4(self: *const volatile GeneralHeader, new_base_addr4: u32) void {
+ self.base_addr4 = std.mem.nativeToLittle(u32, new_base_addr4);
+ }
+
+ pub fn setBaseAddr5(self: *const volatile GeneralHeader, new_base_addr5: u32) void {
+ self.base_addr5 = std.mem.nativeToLittle(u32, new_base_addr5);
+ }
+
+ pub fn setCardBusCisPointer(self: *const volatile GeneralHeader, new_cardbus_cis_pointer: u32) void {
+ self.cardbus_cis_pointer = std.mem.nativeToLittle(u32, new_cardbus_cis_pointer);
+ }
+
+ pub fn setSubsystemVendorId(self: *const volatile GeneralHeader, new_subsystem_vendor_id: u16) void {
+ self.subsystem_vendor_id = std.mem.nativeToLittle(u16, new_subsystem_vendor_id);
+ }
+
+ pub fn setSubsystemId(self: *const volatile GeneralHeader, new_subsystem_id: u16) void {
+ self.subsystem_id = std.mem.nativeToLittle(u16, new_subsystem_id);
+ }
+
+ pub fn setExpansionRomBaseAddr(self: *const volatile GeneralHeader, new_expansion_rom_base_addr: u32) void {
+ self.expansion_rom_base_addr = std.mem.nativeToLittle(u32, new_expansion_rom_base_addr);
+ }
+
+ pub fn setCapabilitiesPointer(self: *const volatile GeneralHeader, new_capabilities_pointer: u8) void {
+ self.capabilities_pointer = std.mem.nativeToLittle(u8, new_capabilities_pointer);
+ }
+
+ pub fn setReserved0(self: *const volatile GeneralHeader, new_reserved0: u24) void {
+ self.reserved0 = std.mem.nativeToLittle(u24, new_reserved0);
+ }
+
+ pub fn setReserved1(self: *const volatile GeneralHeader, new_reserved1: u32) void {
+ self.reserved1 = std.mem.nativeToLittle(u32, new_reserved1);
+ }
+
+ pub fn setInterruptLine(self: *const volatile GeneralHeader, new_interrupt_line: u8) void {
+ self.interrupt_line = std.mem.nativeToLittle(u8, new_interrupt_line);
+ }
+
+ pub fn setInterruptPin(self: *const volatile GeneralHeader, new_interrupt_pin: u8) void {
+ self.interrupt_pin = std.mem.nativeToLittle(u8, new_interrupt_pin);
+ }
+
+ pub fn setMinGrant(self: *const volatile GeneralHeader, new_min_grant: u8) void {
+ self.min_grant = std.mem.nativeToLittle(u8, new_min_grant);
+ }
+
+ pub fn setMaxLatency(self: *const volatile GeneralHeader, new_max_latency: u8) void {
+ self.max_latency = std.mem.nativeToLittle(u8, new_max_latency);
+ }
+};
+
+pub const Pci2Pciheader = packed struct(u384) {
+ base_addr0: u32,
+ base_addr1: u32,
+ primary_bus_number: u8,
+ secondary_bus_number: u8,
+ subordinate_bus_number: u8,
+ secondary_latency_timer: u8,
+ io_base: u8,
+ io_limit: u8,
+ secondary_status: u16,
+ memory_base: u16,
+ memory_limit: u16,
+ prefetchable_memory_base: u16,
+ prefetchable_memory_limit: u16,
+ prefetchable_base_upper_32_bits: u32,
+ prefetchable_limit_upper_32_bits: u32,
+ io_base_upper_16_bits: u16,
+ io_limit_upper_16_bits: u16,
+ capability_pointer: u8,
+ reserved0: u24,
+ expansion_rom_base_addr: u32,
+ interrupt_line: u8,
+ interrupt_pin: u8,
+ bridge_control: u16,
+
+ pub fn getBaseAddr0(self: *const volatile Pci2Pciheader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr0);
+ }
+
+ pub fn getBaseAddr1(self: *const volatile Pci2Pciheader) u32 {
+ return std.mem.littleToNative(u32, self.base_addr1);
+ }
+
+ pub fn getPrimaryBusNumber(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.primary_bus_number);
+ }
+
+ pub fn getSecondaryBusNumber(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.secondary_bus_number);
+ }
+
+ pub fn getSubordinateBusNumber(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.subordinate_bus_number);
+ }
+
+ pub fn getSecondaryLatencyTimer(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.secondary_latency_timer);
+ }
+
+ pub fn getIoBase(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.io_base);
+ }
+
+ pub fn getIoLimit(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.io_limit);
+ }
+
+ pub fn getSecondaryStatus(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.secondary_status);
+ }
+
+ pub fn getMemoryBase(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.memory_base);
+ }
+
+ pub fn getMemoryLimit(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.memory_limit);
+ }
+
+ pub fn getPrefetchableMemoryBase(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.prefetchable_memory_base);
+ }
+
+ pub fn getPrefetchableMemoryLimit(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.prefetchable_memory_limit);
+ }
+
+ pub fn getPrefetchableBaseUpper32Bits(self: *const volatile Pci2Pciheader) u32 {
+ return std.mem.littleToNative(u32, self.prefetchable_base_upper_32_bits);
+ }
+
+ pub fn getPrefetchableLimitUpper32Bits(self: *const volatile Pci2Pciheader) u32 {
+ return std.mem.littleToNative(u32, self.prefetchable_limit_upper_32_bits);
+ }
+
+ pub fn getIoBaseUpper16Bits(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.io_base_upper_16_bits);
+ }
+
+ pub fn getIoLimitUpper16Bits(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.io_limit_upper_16_bits);
+ }
+
+ pub fn getCapabilityPointer(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.capability_pointer);
+ }
+
+ pub fn getReserved0(self: *const volatile Pci2Pciheader) u24 {
+ return std.mem.littleToNative(u24, self.reserved0);
+ }
+
+ pub fn getExpansionRomBaseAddr(self: *const volatile Pci2Pciheader) u32 {
+ return std.mem.littleToNative(u32, self.expansion_rom_base_addr);
+ }
+
+ pub fn getInterruptLine(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.interrupt_line);
+ }
+
+ pub fn getInterruptPin(self: *const volatile Pci2Pciheader) u8 {
+ return std.mem.littleToNative(u8, self.interrupt_pin);
+ }
+
+ pub fn getBridgeControl(self: *const volatile Pci2Pciheader) u16 {
+ return std.mem.littleToNative(u16, self.bridge_control);
+ }
+
+ pub fn setBaseAddr0(self: *volatile Pci2Pciheader, new_base_addr0: u32) void {
+ self.base_addr0 = std.mem.nativeToLittle(u32, new_base_addr0);
+ }
+
+ pub fn setBaseAddr1(self: *volatile Pci2Pciheader, new_base_addr1: u32) void {
+ self.base_addr1 = std.mem.nativeToLittle(u32, new_base_addr1);
+ }
+
+ pub fn setPrimaryBusNumber(self: *volatile Pci2Pciheader, new_primary_bus_number: u8) void {
+ self.primary_bus_number = std.mem.nativeToLittle(u8, new_primary_bus_number);
+ }
+
+ pub fn setSecondaryBusNumber(self: *volatile Pci2Pciheader, new_secondary_bus_number: u8) void {
+ self.secondary_bus_number = std.mem.nativeToLittle(u8, new_secondary_bus_number);
+ }
+
+ pub fn setSubordinateBusNumber(self: *volatile Pci2Pciheader, new_subordinate_bus_number: u8) void {
+ self.subordinate_bus_number = std.mem.nativeToLittle(u8, new_subordinate_bus_number);
+ }
+
+ pub fn setSecondaryLatencyTimer(self: *volatile Pci2Pciheader, new_secondary_latency_timer: u8) void {
+ self.secondary_latency_timer = std.mem.nativeToLittle(u8, new_secondary_latency_timer);
+ }
+
+ pub fn setIoBase(self: *volatile Pci2Pciheader, new_io_base: u8) void {
+ self.io_base = std.mem.nativeToLittle(u8, new_io_base);
+ }
+
+ pub fn setIoLimit(self: *volatile Pci2Pciheader, new_io_limit: u8) void {
+ self.io_limit = std.mem.nativeToLittle(u8, new_io_limit);
+ }
+
+ pub fn setSecondaryStatus(self: *volatile Pci2Pciheader, new_secondary_status: u16) void {
+ self.secondary_status = std.mem.nativeToLittle(u16, new_secondary_status);
+ }
+
+ pub fn setMemoryBase(self: *volatile Pci2Pciheader, new_memory_base: u16) void {
+ self.memory_base = std.mem.nativeToLittle(u16, new_memory_base);
+ }
+
+ pub fn setMemoryLimit(self: *volatile Pci2Pciheader, new_memory_limit: u16) void {
+ self.memory_limit = std.mem.nativeToLittle(u16, new_memory_limit);
+ }
+
+ pub fn setPrefetchableMemoryBase(self: *volatile Pci2Pciheader, new_prefetchable_memory_base: u16) void {
+ self.prefetchable_memory_base = std.mem.nativeToLittle(u16, new_prefetchable_memory_base);
+ }
+
+ pub fn setPrefetchableMemoryLimit(self: *volatile Pci2Pciheader, new_prefetchable_memory_limit: u16) void {
+ self.prefetchable_memory_limit = std.mem.nativeToLittle(u16, new_prefetchable_memory_limit);
+ }
+
+ pub fn setPrefetchableBaseUpper32Bits(self: *volatile Pci2Pciheader, new_prefetchable_base_upper_32_bits: u32) void {
+ self.prefetchable_base_upper_32_bits = std.mem.nativeToLittle(u32, new_prefetchable_base_upper_32_bits);
+ }
+
+ pub fn setPrefetchableLimitUpper32Bits(self: *volatile Pci2Pciheader, new_prefetchable_limit_upper_32_bits: u32) void {
+ self.prefetchable_limit_upper_32_bits = std.mem.nativeToLittle(u32, new_prefetchable_limit_upper_32_bits);
+ }
+
+ pub fn setIoBaseUpper16Bits(self: *volatile Pci2Pciheader, new_io_base_upper_16_bits: u16) void {
+ self.io_base_upper_16_bits = std.mem.nativeToLittle(u16, new_io_base_upper_16_bits);
+ }
+
+ pub fn setIoLimitUpper16Bits(self: *volatile Pci2Pciheader, new_io_limit_upper_16_bits: u16) void {
+ self.io_limit_upper_16_bits = std.mem.nativeToLittle(u16, new_io_limit_upper_16_bits);
+ }
+
+ pub fn setCapabilityPointer(self: *volatile Pci2Pciheader, new_capability_pointer: u8) void {
+ self.capability_pointer = std.mem.nativeToLittle(u8, new_capability_pointer);
+ }
+
+ pub fn setReserved0(self: *volatile Pci2Pciheader, new_reserved0: u24) void {
+ self.reserved0 = std.mem.nativeToLittle(u24, new_reserved0);
+ }
+
+ pub fn setExpansionRomBaseAddr(self: *volatile Pci2Pciheader, new_expansion_rom_base_addr: u32) void {
+ self.expansion_rom_base_addr = std.mem.nativeToLittle(u32, new_expansion_rom_base_addr);
+ }
+
+ pub fn setInterruptLine(self: *volatile Pci2Pciheader, new_interrupt_line: u8) void {
+ self.interrupt_line = std.mem.nativeToLittle(u8, new_interrupt_line);
+ }
+
+ pub fn setInterruptPin(self: *volatile Pci2Pciheader, new_interrupt_pin: u8) void {
+ self.interrupt_pin = std.mem.nativeToLittle(u8, new_interrupt_pin);
+ }
+
+ pub fn setBridgeControl(self: *volatile Pci2Pciheader, new_bridge_control: u16) void {
+ self.bridge_control = std.mem.nativeToLittle(u16, new_bridge_control);
+ }
+};
+
+pub const Pci2CardBusHeader = packed struct(u448) {
+ cardbus_socket_exca_base_addr: u32,
+ capabilities_list_offset: u8,
+ reserved0: u8,
+ secondary_status: u16,
+ pci_bus_number: u8,
+ cardbus_bus_number: u8,
+ subordinate_bus_number: u8,
+ cardbus_latency_timer: u8,
+ memory_base_addr0: u32,
+ memory_limit0: u32,
+ memory_base_addr1: u32,
+ memory_limit1: u32,
+ io_base_addr0: u32,
+ io_limit0: u32,
+ io_base_addr1: u32,
+ io_limit1: u32,
+ interrupt_line: u8,
+ interrupt_pin: u8,
+ bridge_control: u16,
+ subsystem_device_id: u16,
+ subsystem_vendor_id: u16,
+ pc_card_legacy_mode_16_bit_base_addr: u32,
+
+ pub fn getCardBusSocketExCaBaseAddr(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.cardbus_socket_exca_base_addr);
+ }
+
+ pub fn getCapabilitiesListOffset(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.capabilities_list_offset);
+ }
+
+ pub fn getReserved0(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.reserved0);
+ }
+
+ pub fn getSecondaryStatus(self: *const volatile Pci2CardBusHeader) u16 {
+ return std.mem.littleToNative(u16, self.secondary_status);
+ }
+
+ pub fn getPciBusNumber(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.pci_bus_number);
+ }
+
+ pub fn getCardBusBusNumber(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.cardbus_bus_number);
+ }
+
+ pub fn getSubordinateBusNumber(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.subordinate_bus_number);
+ }
+
+ pub fn getCardBusLatencyTimer(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.cardbus_latency_timer);
+ }
+
+ pub fn getMemoryBaseAddr0(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.memory_base_addr0);
+ }
+
+ pub fn getMemoryLimit0(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.memory_limit0);
+ }
+
+ pub fn getMemoryBaseAddr1(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.memory_base_addr1);
+ }
+
+ pub fn getMemoryLimit1(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.memory_limit1);
+ }
+
+ pub fn getIoBaseAddr0(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.io_base_addr0);
+ }
+
+ pub fn getIoLimit0(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.io_limit0);
+ }
+
+ pub fn getIoBaseAddr1(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.io_base_addr1);
+ }
+
+ pub fn getIoLimit1(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.io_limit1);
+ }
+
+ pub fn getInterruptLine(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.interrupt_line);
+ }
+
+ pub fn getInterruptPin(self: *const volatile Pci2CardBusHeader) u8 {
+ return std.mem.littleToNative(u8, self.interrupt_pin);
+ }
+
+ pub fn getBridgeControl(self: *const volatile Pci2CardBusHeader) u16 {
+ return std.mem.littleToNative(u16, self.bridge_control);
+ }
+
+ pub fn getSubsystemDeviceId(self: *const volatile Pci2CardBusHeader) u16 {
+ return std.mem.littleToNative(u16, self.subsystem_device_id);
+ }
+
+ pub fn getSubsystemVendorId(self: *const volatile Pci2CardBusHeader) u16 {
+ return std.mem.littleToNative(u16, self.subsystem_vendor_id);
+ }
+
+ pub fn getPcCardLegacyMode16BitBaseAddr(self: *const volatile Pci2CardBusHeader) u32 {
+ return std.mem.littleToNative(u32, self.pc_card_legacy_mode_16_bit_base_addr);
+ }
+
+ pub fn setCardBusSocketExCaBaseAddr(self: *volatile Pci2CardBusHeader, new_cardbus_socket_exca_base_addr: u32) void {
+ self.cardbus_socket_exca_base_addr = std.mem.nativeToLittle(u32, new_cardbus_socket_exca_base_addr);
+ }
+
+ pub fn setCapabilitiesListOffset(self: *volatile Pci2CardBusHeader, new_capabilities_list_offset: u8) void {
+ self.capabilities_list_offset = std.mem.nativeToLittle(u8, new_capabilities_list_offset);
+ }
+
+ pub fn setReserved0(self: *volatile Pci2CardBusHeader, new_reserved0: u8) void {
+ self.reserved0 = std.mem.nativeToLittle(u8, new_reserved0);
+ }
+
+ pub fn setSecondaryStatus(self: *volatile Pci2CardBusHeader, new_secondary_status: u16) void {
+ self.secondary_status = std.mem.nativeToLittle(u16, new_secondary_status);
+ }
+
+ pub fn setPciBusNumber(self: *volatile Pci2CardBusHeader, new_pci_bus_number: u8) void {
+ self.pci_bus_number = std.mem.nativeToLittle(u8, new_pci_bus_number);
+ }
+
+ pub fn setCardBusBusNumber(self: *volatile Pci2CardBusHeader, new_cardbus_bus_number: u8) void {
+ self.cardbus_bus_number = std.mem.nativeToLittle(u8, new_cardbus_bus_number);
+ }
+
+ pub fn setSubordinateBusNumber(self: *volatile Pci2CardBusHeader, new_subordinate_bus_number: u8) void {
+ self.subordinate_bus_number = std.mem.nativeToLittle(u8, new_subordinate_bus_number);
+ }
+
+ pub fn setCardBusLatencyTimer(self: *volatile Pci2CardBusHeader, new_cardbus_latency_timer: u8) void {
+ self.cardbus_latency_timer = std.mem.nativeToLittle(u8, new_cardbus_latency_timer);
+ }
+
+ pub fn setMemoryBaseAddr0(self: *volatile Pci2CardBusHeader, new_memory_base_addr0: u32) void {
+ self.memory_base_addr0 = std.mem.nativeToLittle(u32, new_memory_base_addr0);
+ }
+
+ pub fn setMemoryLimit0(self: *volatile Pci2CardBusHeader, new_memory_limit0: u32) void {
+ self.memory_limit0 = std.mem.nativeToLittle(u32, new_memory_limit0);
+ }
+
+ pub fn setMemoryBaseAddr1(self: *volatile Pci2CardBusHeader, new_memory_base_addr1: u32) void {
+ self.memory_base_addr1 = std.mem.nativeToLittle(u32, new_memory_base_addr1);
+ }
+
+ pub fn setMemoryLimit1(self: *volatile Pci2CardBusHeader, new_memory_limit1: u32) void {
+ self.memory_limit1 = std.mem.nativeToLittle(u32, new_memory_limit1);
+ }
+
+ pub fn setIoBaseAddr0(self: *volatile Pci2CardBusHeader, new_io_base_addr0: u32) void {
+ self.io_base_addr0 = std.mem.nativeToLittle(u32, new_io_base_addr0);
+ }
+
+ pub fn setIoLimit0(self: *volatile Pci2CardBusHeader, new_io_limit0: u32) void {
+ self.io_limit0 = std.mem.nativeToLittle(u32, new_io_limit0);
+ }
+
+ pub fn setIoBaseAddr1(self: *volatile Pci2CardBusHeader, new_io_base_addr1: u32) void {
+ self.io_base_addr1 = std.mem.nativeToLittle(u32, new_io_base_addr1);
+ }
+
+ pub fn setIoLimit1(self: *volatile Pci2CardBusHeader, new_io_limit1: u32) void {
+ self.io_limit1 = std.mem.nativeToLittle(u32, new_io_limit1);
+ }
+
+ pub fn setInterruptLine(self: *volatile Pci2CardBusHeader, new_interrupt_line: u8) void {
+ self.interrupt_line = std.mem.nativeToLittle(u8, new_interrupt_line);
+ }
+
+ pub fn setInterruptPin(self: *volatile Pci2CardBusHeader, new_interrupt_pin: u8) void {
+ self.interrupt_pin = std.mem.nativeToLittle(u8, new_interrupt_pin);
+ }
+
+ pub fn setBridgeControl(self: *volatile Pci2CardBusHeader, new_bridge_control: u16) void {
+ self.bridge_control = std.mem.nativeToLittle(u16, new_bridge_control);
+ }
+
+ pub fn setSubsystemDeviceId(self: *volatile Pci2CardBusHeader, new_subsystem_device_id: u16) void {
+ self.subsystem_device_id = std.mem.nativeToLittle(u16, new_subsystem_device_id);
+ }
+
+ pub fn setSubsystemVendorId(self: *volatile Pci2CardBusHeader, new_subsystem_vendor_id: u16) void {
+ self.subsystem_vendor_id = std.mem.nativeToLittle(u16, new_subsystem_vendor_id);
+ }
+
+ pub fn setPcCardLegacyMode16BitBaseAddr(self: *volatile Pci2CardBusHeader, new_pc_card_legacy_mode_16_bit_base_addr: u32) void {
+ self.pc_card_legacy_mode_16_bit_base_addr = std.mem.nativeToLittle(u32, new_pc_card_legacy_mode_16_bit_base_addr);
+ }
+};
+
+pub const CfgSpace = packed struct(u576) {
+ vendor_id: u16,
+ device_id: u16,
+ command: u16,
+ status: u16,
+ revision_id: u8,
+ prog_if: u8,
+ subclass: u8,
+ class: u8,
+ cache_line_size: u8,
+ latency_timer: u8,
+ header_type: u8,
+ bist: u8, // built-in self test
+
+ header: Header,
+
+ pub fn getDeviceId(self: *const volatile CfgSpace) u16 {
+ return std.mem.littleToNative(u16, self.device_id);
+ }
+
+ pub fn getVendorId(self: *const volatile CfgSpace) u16 {
+ return std.mem.littleToNative(u16, self.vendor_id);
+ }
+
+ pub fn getStatus(self: *const volatile CfgSpace) u16 {
+ return std.mem.littleToNative(u16, self.status);
+ }
+
+ pub fn getCommand(self: *const volatile CfgSpace) u16 {
+ return std.mem.littleToNative(u16, self.command);
+ }
+
+ pub fn getClass(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.class);
+ }
+
+ pub fn getSubclass(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.subclass);
+ }
+
+ pub fn getProgIf(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.prog_if);
+ }
+
+ pub fn getRevisionId(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.revision_id);
+ }
+
+ pub fn getBist(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.bist);
+ }
+
+ pub fn getHeaderType(self: *const volatile CfgSpace) HeaderType {
+ return @enumFromInt(std.mem.littleToNative(u8, self.header_type));
+ }
+
+ pub fn getLatencyTimer(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.latency_timer);
+ }
+
+ pub fn getCacheLineSize(self: *const volatile CfgSpace) u8 {
+ return std.mem.littleToNative(u8, self.cache_line_size);
+ }
+
+ pub fn setDeviceId(self: *volatile CfgSpace, new_device_id: u16) void {
+ self.device_id = std.mem.nativeToLittle(u16, new_device_id);
+ }
+
+ pub fn setVendorId(self: *volatile CfgSpace, new_vendor_id: u16) void {
+ self.vendor_id = std.mem.nativeToLittle(u16, new_vendor_id);
+ }
+
+ pub fn setStatus(self: *volatile CfgSpace, new_status: u16) void {
+ self.status = std.mem.nativeToLittle(u16, new_status);
+ }
+
+ pub fn setCommand(self: *volatile CfgSpace, new_command: u16) void {
+ self.command = std.mem.nativeToLittle(u16, new_command);
+ }
+
+ pub fn setClass(self: *volatile CfgSpace, new_class: u8) void {
+ self.class = std.mem.writeInt(u8, new_class);
+ }
+
+ pub fn setSubclass(self: *volatile CfgSpace, new_subclass: u8) void {
+ self.subclass = std.mem.nativeToLittle(u8, new_subclass);
+ }
+
+ pub fn setProgIf(self: *volatile CfgSpace, new_prog_if: u8) void {
+ self.prog_if = std.mem.nativeToLittle(u8, new_prog_if);
+ }
+
+ pub fn setRevisionId(self: *volatile CfgSpace, new_revision_id: u8) void {
+ self.revision_id = std.mem.nativeToLittle(u8, new_revision_id);
+ }
+
+ pub fn setBist(self: *volatile CfgSpace, new_bist: u8) void {
+ self.bist = std.mem.nativeToLittle(u8, new_bist);
+ }
+
+ pub fn setHeaderType(self: *volatile CfgSpace, new_header_type: HeaderType) void {
+ self.header_type = std.mem.writeInt(u8, @intFromEnum(new_header_type));
+ }
+
+ pub fn setLatencyTimer(self: *volatile CfgSpace, new_latency_timer: u8) void {
+ self.latency_timer = std.mem.nativeToLittle(u8, new_latency_timer);
+ }
+
+ pub fn setCacheLineSize(self: *volatile CfgSpace, new_cache_line_size: u8) void {
+ self.cache_line_size = std.mem.nativeToLittle(u8, new_cache_line_size);
+ }
+};
+
+pub fn controllerFromHwInfo() ?Controller {
+ var pcie = hwinfo.byKind(.pcie);
+ var pci = hwinfo.byKind(.pci);
+
+ if (try pcie.next()) |ecam| {
+ return Controller{ .enhanced = .{ .reg = ecam.reg.slice(u8) } };
+ } else if (try pci.next()) |cam| {
+ return Controller{ .conventional = .{ .reg = cam.reg.slice(u8) } };
+ } else {
+ return null;
+ }
+}