aboutsummaryrefslogtreecommitdiff
path: root/src/lib/pci.zig
diff options
context:
space:
mode:
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;
+ }
+}