7 class Acpi_hpet : public Acpi_table_head
10 Unsigned32 event_timer_block_id;
11 Acpi_gas base_address;
12 Unsigned8 hpet_number;
13 Unsigned16 min_clock_ticks_for_irq;
14 Unsigned8 page_prot_and_oem_attr;
15 } __attribute__((packed));
20 Unsigned64 config_and_cap;
27 Tn_INT_TYPE_CNF = 1 << 1,
28 Tn_INT_ENB_CNF = 1 << 2,
30 Tn_PER_INT_CAP = 1 << 4,
32 Tn_VAL_SET_CNF = 1 << 6,
33 Tn_32MODE_CNF = 1 << 8,
34 Tn_FSB_EN_CNF = 1 << 14,
35 Tn_FSB_INT_DEL_CAP = 1 << 15,
36 Tn_INT_ROUTE_CNF_MASK = 31 << 9,
39 void enable_int() { config_and_cap |= Tn_INT_ENB_CNF; }
40 void disable_int() { config_and_cap &= ~Tn_INT_ENB_CNF; }
42 { config_and_cap = (config_and_cap & ~Tn_INT_ROUTE_CNF_MASK) | (irq << 9); }
44 int get_int() const { return (config_and_cap & Tn_INT_ROUTE_CNF_MASK) >> 9; }
46 bool can_periodic() const { return config_and_cap & Tn_PER_INT_CAP; }
47 void set_periodic() { config_and_cap |= Tn_TYPE_CNF; }
49 void set_level_irq() { config_and_cap |= Tn_INT_TYPE_CNF; }
50 void set_edge_irq() { config_and_cap &= ~Tn_INT_TYPE_CNF; }
52 bool can_64bit() const { return config_and_cap & Tn_SIZE_CAP; }
53 void force_32bit() { config_and_cap |= Tn_32MODE_CNF; }
54 void val_set() { config_and_cap |= Tn_VAL_SET_CNF; }
56 Unsigned32 int_route_cap() const { return config_and_cap >> 32; }
57 bool int_avail(int i) const { return int_route_cap() & i; }
61 Unsigned32 cap = int_route_cap();
62 for (int i = 0; i < 32; ++i)
68 } __attribute__((packed));
74 Unsigned64 cap_and_id; // offset 0x00
76 Unsigned64 config; // offset 0x10
78 Unsigned64 irq_status; // offset 0x20
79 Unsigned64 _pad2[1 + 2 * 12];
80 Unsigned64 counter_val; // 0ffset 0xf0
90 int num_timers() const { return ((cap_and_id >> 8) & 0xf) + 1; }
92 Hpet_timer *timer(int idx) const
93 { return reinterpret_cast<Hpet_timer *>((char *)this + 0x100 + idx * 0x20); }
95 void enable() { config |= ENABLE_CNF; Mem::mb(); }
96 void disable() { config &= ~ENABLE_CNF; Mem::mb(); }
98 Unsigned32 counter_clk_period() const { return cap_and_id >> 32; }
99 void reset_counter() { counter_val = 0; Mem::mb(); }
101 void clear_level_irq(int timer_nr)
102 { irq_status = 1 << timer_nr; Mem::mb(); }
104 } __attribute__((packed));
109 static void set_periodic() { _hpet_timer->set_periodic(); }
110 static void enable_timer() { _hpet_timer->enable_int(); }
111 static void disable_timer() { _hpet_timer->disable_int(); }
112 static void clear_timer() { /* _hpet->clear_level_irq(2); */ }
113 static int int_num() { return _hpet_timer->get_int(); }
114 static bool int_avail(int i) { return _hpet_timer->int_avail(i); }
116 static void enable() { _hpet->enable(); }
117 static void dump() { _hpet->dump(); }
120 static Acpi_hpet const *_acpi_hpet;
121 static Hpet_device *_hpet;
122 static Hpet_timer *_hpet_timer;
127 Acpi_hpet const *Hpet::_acpi_hpet;
128 Hpet_device *Hpet::_hpet;
129 Hpet_timer *Hpet::_hpet_timer;
135 printf("HPET: cap+id : %016llx\n", cap_and_id);
136 printf(" clk-per: %d femtosecs\n", counter_clk_period());
137 printf(" gen-config: %llx\n", config);
142 Hpet::dump_acpi_infos()
147 printf("ACPI-HPET = %p\n", _acpi_hpet);
149 printf(" event_timer_block_id: %x\n", _acpi_hpet->event_timer_block_id);
150 printf(" base_address: %llx (as: %d, off: %d, w: %d, id: %d)\n",
151 _acpi_hpet->base_address.addr,
152 _acpi_hpet->base_address.access_size,
153 _acpi_hpet->base_address.offset,
154 _acpi_hpet->base_address.width,
155 _acpi_hpet->base_address.id);
156 printf(" hpet_number: %d\n", _acpi_hpet->hpet_number);
157 printf(" min_clock_ticks_for_irq: %d\n", _acpi_hpet->min_clock_ticks_for_irq);
158 printf(" page_prot_and_oem_attr: %x\n", _acpi_hpet->page_prot_and_oem_attr);
161 PUBLIC static FIASCO_INIT
165 _acpi_hpet = Acpi::find<Acpi_hpet const *>("HPET");
169 printf("Could not find HPET in RSDT nor XSDT, skipping init\n");
176 Address a = _acpi_hpet->base_address.addr;
177 Address va = Mem_layout::alloc_io_vmem(Config::PAGE_SIZE);
180 Kmem::map_phys_page(a, va, false, true, &offs);
182 Kip::k()->add_mem_region(Mem_desc(a, a + 1023, Mem_desc::Reserved));
184 _hpet = (Hpet_device *)(va + offs);
189 _hpet->reset_counter();
193 for (; i < _hpet->num_timers(); ++i)
197 if (t->can_periodic() && t->int_route_cap())
203 t->set_int(t->get_first_int());
205 t->comp_val = div32(1000000000000ULL, _hpet->counter_clk_period());
213 printf("ERROR: Did not find a HPET timer that can do periodic mode.\n");