1 # bend-osdev-acpi, hpet.bend: the HPET Description Table, "HPET" (IA-PC HPET 2 # (High Precision Event Timers) Specification, revision 1.0a, Intel, 2004, 3 # section 3.2.4; its signature is reserved by ACPI 6.5, section 5.2.6), 4 # 56 bytes: 5 # 6 # offset size field 7 # 36 4 Event Timer Block ID: bits 0-7 hardware revision, 8-12 8 # number of comparators in the first block minus one, 13 9 # COUNT_SIZE_CAP (64-bit counter), 15 legacy replacement 10 # IRQ routing capable, 16-31 PCI vendor ID 11 # 40 12 Base Address (a Generic Address Structure, gas.bend) 12 # 52 1 HPET Number 13 # 53 2 Main Counter Minimum Clock Tick in Periodic Mode 14 # 55 1 Page Protection and OEM Attribute 15 import Base 16 import bend-osdev-word64@0.1.1.1/word64.bend as W 17 import bend-osdev-bytes@0.1.1.1/bytes.bend as B 18 import ./error.bend as E 19 import ./header.bend as H 20 import ./fields.bend as F 21 import ./gas.bend as G 22 23 type AcpiHpet is Data: 24 AcpiHpet{header: H.AcpiHeader, block_id: U32, base: G.AcpiGas, number: U32, min_tick: U32, page_protection: U32} 25 26 def hpet.read(ok: Bool, +h: H.AcpiHeader, +o: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiHpet>: 27 match ok: 28 case False{}: 29 Fail{E.AcpiTooShort{56n, B.Octets.len(o)}} 30 case True{}: 31 Done{AcpiHpet{h, F.AcpiF.u32(o, 36n), G.AcpiGas.at(o, 40n), F.AcpiF.u8(o, 52n), F.AcpiF.u16(o, 53n), F.AcpiF.u8(o, 55n)}} 32 33 def AcpiHpet.of_sdt(t: H.AcpiSdt) -> Result<&2, &2, E.AcpiError, AcpiHpet>: 34 match t: 35 case H.AcpiSdt{+h, body}: 36 +o = B.Octets.append(H.AcpiHeader.encode(h), body) 37 hpet.read(Nat.is_le(56n, B.Octets.len(o)), h, o) 38 39 def hpet.parse(r: Result<&2, &2, E.AcpiError, H.AcpiSdt>) -> Result<&2, &2, E.AcpiError, AcpiHpet>: 40 match r: 41 case Fail{e}: 42 Fail{e} 43 case Done{t}: 44 AcpiHpet.of_sdt(t) 45 46 def AcpiHpet.parse(+o: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiHpet>: 47 hpet.parse(H.AcpiSdt.parse_sig(B.Octets.of_string("HPET"), o)) 48 49 def AcpiHpet.block_id(t: AcpiHpet) -> U32: 50 match t: 51 case AcpiHpet{h, id, g, n, m, p}: 52 id 53 54 def AcpiHpet.base(t: AcpiHpet) -> G.AcpiGas: 55 match t: 56 case AcpiHpet{h, id, g, n, m, p}: 57 g 58 59 # the fields of the Event Timer Block ID 60 def AcpiHpet.vendor_id(t: AcpiHpet) -> U32: 61 F.AcpiF.bits(AcpiHpet.block_id(t), 16n, 16n) 62 63 def AcpiHpet.comparators(t: AcpiHpet) -> U32: 64 U32.add(F.AcpiF.bits(AcpiHpet.block_id(t), 8n, 5n), 1) 65 66 def AcpiHpet.counter_64(t: AcpiHpet) -> Bool: 67 F.AcpiF.bit(AcpiHpet.block_id(t), 13n) 68 69 def AcpiHpet.legacy_capable(t: AcpiHpet) -> Bool: 70 F.AcpiF.bit(AcpiHpet.block_id(t), 15n) 71 72 def AcpiHpet.build(t: AcpiHpet) -> B.Octets: 73 match t: 74 case AcpiHpet{H.AcpiHeader{s, l, r, c, o, tid, orv, ci, cr}, id, g, n, m, p}: 75 H.AcpiSdt.build(H.AcpiHeader{B.Octets.of_string("HPET"), l, r, c, o, tid, orv, ci, cr}, B.Octets.concat([B.Octets.le32(id), G.AcpiGas.encode(g), B.Octets.of_list([n]), B.Octets.le16(m), B.Octets.of_list([p])]))