diff options
Diffstat (limited to 'src/lib/pci.zig')
-rw-r--r-- | src/lib/pci.zig | 761 |
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; + } +} |