1 # bend-osdev-acpi, gas.bend: the Generic Address Structure (ACPI 6.5, 2 # section 5.2.3.2), 12 bytes: 3 # 4 # offset size field 5 # 0 1 Address Space ID (0 system memory, 1 system I/O, 2 PCI 6 # configuration space, 3 embedded controller, 4 SMBus, 7 # 5 CMOS, 6 PCI BAR target, 7 IPMI, 8 GPIO, 9 generic 8 # serial bus, 10 PCC, 11 PRM, 0x7F functional fixed hardware) 9 # 1 1 Register Bit Width 10 # 2 1 Register Bit Offset 11 # 3 1 Access Size (0 undefined, 1 byte, 2 word, 3 dword, 4 qword) 12 # 4 8 Address 13 import Base 14 import bend-osdev-word64@0.1.1.1/word64.bend as W 15 import bend-osdev-bytes@0.1.1.1/bytes.bend as B 16 import ./fields.bend as F 17 18 type AcpiGas is Data: 19 AcpiGas{space: U32, bit_width: U32, bit_offset: U32, access_size: U32, address: W.W64} 20 21 def AcpiGas.space_memory() -> U32: 22 0 23 24 def AcpiGas.space_io() -> U32: 25 1 26 27 def AcpiGas.space_pci_config() -> U32: 28 2 29 30 def AcpiGas.space_ec() -> U32: 31 3 32 33 def AcpiGas.space_ffixedhw() -> U32: 34 127 35 36 def AcpiGas.size() -> Nat: 37 12n 38 39 # the structure at offset i of o 40 def AcpiGas.at(+o: B.Octets, +i: Nat) -> AcpiGas: 41 AcpiGas{F.AcpiF.u8(o, i), F.AcpiF.u8(o, Nat.add(i, 1n)), F.AcpiF.u8(o, Nat.add(i, 2n)), F.AcpiF.u8(o, Nat.add(i, 3n)), F.AcpiF.u64(o, Nat.add(i, 4n))} 42 43 def AcpiGas.encode(g: AcpiGas) -> B.Octets: 44 match g: 45 case AcpiGas{s, w, off, a, addr}: 46 B.Octets.append(B.Octets.of_list([s, w, off, a]), B.Octets.le64(addr)) 47 48 def AcpiGas.zero() -> AcpiGas: 49 AcpiGas{0, 0, 0, 0, W.W64.zero()} 50 51 def AcpiGas.address(g: AcpiGas) -> W.W64: 52 match g: 53 case AcpiGas{s, w, off, a, addr}: 54 addr 55 56 def AcpiGas.space(g: AcpiGas) -> U32: 57 match g: 58 case AcpiGas{s, w, off, a, addr}: 59 s 60 61 # no register: the address is zero 62 def AcpiGas.is_null(g: AcpiGas) -> Bool: 63 W.W64.is_zero(AcpiGas.address(g)) 64 65 # a system I/O register block at a 32-bit port address, n bytes long (how 66 # the FADT's ACPI 1.0 block fields are read as Generic Addresses) 67 def AcpiGas.io_block(port: U32, n: U32) -> AcpiGas: 68 AcpiGas{1, U32.and(255, U32.mul(n, 8)), 0, 0, W.W64.from_u32(port)} 69 70 def AcpiGas.show(g: AcpiGas) -> String: 71 match g: 72 case AcpiGas{s, w, off, a, addr}: 73 "{" ++ U32.show(s) ++ " " ++ U32.show(w) ++ " " ++ U32.show(off) ++ " " ++ U32.show(a) ++ " " ++ W.W64.show_hex(addr) ++ "}"