hpet.bend

bend-osdev-acpi@0.1.2.0 · 75 lines · 0 definitions

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
15import Base
16import bend-osdev-word64@0.1.1.1/word64.bend as W
17import bend-osdev-bytes@0.1.1.1/bytes.bend as B
18import bend-osdev-acpi@0.1.2.0/error.bend as E
19import bend-osdev-acpi@0.1.2.0/header.bend as H
20import bend-osdev-acpi@0.1.2.0/fields.bend as F
21import bend-osdev-acpi@0.1.2.0/gas.bend as G
22
23type AcpiHpet is Data:
24  AcpiHpet{header: H.AcpiHeader, block_id: U32, base: G.AcpiGas, number: U32, min_tick: U32, page_protection: U32}
25
26def 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
33def 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
39def 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
46def 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
49def AcpiHpet.block_id(t: AcpiHpet) -> U32:
50  match t:
51    case AcpiHpet{h, id, g, n, m, p}:
52      id
53
54def 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
60def AcpiHpet.vendor_id(t: AcpiHpet) -> U32:
61  F.AcpiF.bits(AcpiHpet.block_id(t), 16n, 16n)
62
63def AcpiHpet.comparators(t: AcpiHpet) -> U32:
64  U32.add(F.AcpiF.bits(AcpiHpet.block_id(t), 8n, 5n), 1)
65
66def AcpiHpet.counter_64(t: AcpiHpet) -> Bool:
67  F.AcpiF.bit(AcpiHpet.block_id(t), 13n)
68
69def AcpiHpet.legacy_capable(t: AcpiHpet) -> Bool:
70  F.AcpiF.bit(AcpiHpet.block_id(t), 15n)
71
72def 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])]))