// SPDX-FileCopyrightText: 2024 Himbeer // // SPDX-License-Identifier: AGPL-3.0-or-later const std = @import("std"); const fdt = @import("fdt.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 { register: []u8, fn init(register: []u8) CamController { return .{ .register = register }; } pub fn cfgSpace(self: CamController, bus: u8, device: u5, function: u3) *volatile CfgSpace { const mmio_base = @intFromPtr(self.register.ptr); const addr = mmio_base + ((@as(usize, bus) * 0x100) + (@as(usize, device) * 0x08) + function) * 0x1000; return @ptrFromInt(addr); } }; pub const EcamController = struct { register: []u8, fn init(register: []u8) EcamController { return .{ .register = register, }; } pub fn cfgSpace(self: EcamController, bus: u8, device: u5, function: u3) *volatile CfgSpace { const mmio_base = @intFromPtr(self.register.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 controllerFromFdt(dt: *const fdt.Tree) !Controller { if (dt.nodes.items.len < 1) return Error.NoRootNode; const root = dt.nodes.items[0]; const soc = fdt.findNodeExact(root.subnodes.items, "soc") orelse return Error.NoSoCnode; const address_cells_bytes = soc[1].props.get("#address-cells") orelse return Error.NoAddrCells; const size_cells_bytes = soc[1].props.get("#size-cells") orelse return Error.NoSizeCells; const address_cells = 16 * std.mem.readInt(u32, address_cells_bytes[0..4], .big); const size_cells = 16 * std.mem.readInt(u32, size_cells_bytes[0..4], .big); var results = fdt.findNode(soc[1].subnodes.items, "pci"); const node = results.next() orelse return Error.NoPcinode; const unitAddr = try node.unitAddr() orelse return Error.NoUnitAddr; const reg = node.props.get("reg") orelse return Error.NoReg; const regSize = ((address_cells / 8) + (size_cells / 8)); const n = reg.len / regSize; if (n < 1) return Error.NoReg; const ptr: [*]u8 = @ptrFromInt(unitAddr + std.mem.readVarInt(usize, reg[0..(address_cells / 8)], .big)); const len = std.mem.readVarInt(usize, reg[(address_cells / 8) .. (size_cells / 8) + (address_cells / 8)], .big); const slice = ptr[0..len]; const compatible = node.props.get("compatible") orelse return Error.NoCompatInfo; if (std.mem.eql(u8, compatible, "pci-host-cam-generic\x00")) { return Controller{ .conventional = CamController.init(slice) }; } else if (std.mem.eql(u8, compatible, "pci-host-ecam-generic\x00")) { return Controller{ .enhanced = EcamController.init(slice) }; } else { return Error.Incompatible; } }