123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #include "HPET.h"
- #include <common/kprint.h>
- #include <mm/mm.h>
- #include <driver/interrupt/apic/apic.h>
- #include <exception/softirq.h>
- #include <driver/timers/timer.h>
- #include <process/process.h>
- #include <sched/sched.h>
- #include <smp/ipi.h>
- #include <driver/video/video.h>
- static struct acpi_HPET_description_table_t *hpet_table;
- static uint64_t HPET_REG_BASE = 0;
- static uint32_t HPET_COUNTER_CLK_PERIOD = 0;
- static double HPET_freq = 0;
- static uint8_t HPET_NUM_TIM_CAP = 0;
- extern struct rtc_time_t rtc_now;
- enum
- {
- GCAP_ID = 0x00,
- GEN_CONF = 0x10,
- GINTR_STA = 0x20,
- MAIN_CNT = 0xf0,
- TIM0_CONF = 0x100,
- TIM0_COMP = 0x108,
- TIM1_CONF = 0x120,
- TIM1_COMP = 0x128,
- TIM2_CONF = 0x140,
- TIM2_COMP = 0x148,
- TIM3_CONF = 0x160,
- TIM3_COMP = 0x168,
- TIM4_CONF = 0x180,
- TIM4_COMP = 0x188,
- TIM5_CONF = 0x1a0,
- TIM5_COMP = 0x1a8,
- TIM6_CONF = 0x1c0,
- TIM6_COMP = 0x1c8,
- TIM7_CONF = 0x1e0,
- TIM7_COMP = 0x1e8,
- };
- hardware_intr_controller HPET_intr_controller =
- {
- .enable = apic_ioapic_enable,
- .disable = apic_ioapic_disable,
- .install = apic_ioapic_install,
- .uninstall = apic_ioapic_uninstall,
- .ack = apic_ioapic_edge_ack,
- };
- void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
- {
-
- switch (param)
- {
- case 0:
- ++timer_jiffies;
-
-
- if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies)
- set_softirq_status((1 << TIMER_SIRQ));
-
-
- if (timer_jiffies >= video_refresh_expire_jiffies)
- {
- raise_softirq(VIDEO_REFRESH_SIRQ);
- }
- else
- {
- if (video_last_refresh_pid != current_pcb->pid)
- raise_softirq(VIDEO_REFRESH_SIRQ);
- }
- sched_update_jiffies();
- break;
- default:
- kwarn("Unsupported HPET irq: %d.", number);
- break;
- }
- }
- int HPET_init()
- {
- kinfo("Initializing HPET...");
-
- ul hpet_table_addr = 0;
- acpi_iter_SDT(acpi_get_HPET, &hpet_table_addr);
-
- if (hpet_table_addr == 0)
- {
- kwarn("ACPI: HPET Table Not Found On This Computer!");
- if (RCBA_vaddr != 0)
- {
- kerror("NO HPET found on this computer!");
- uint32_t *hptc = (uint32_t *)(RCBA_vaddr + 0x3404UL);
-
- io_mfence();
-
- switch ((*hptc) & 0x3)
- {
- case 0:
- HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed00000;
- break;
- case 1:
- HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed01000;
- break;
- case 2:
- HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed02000;
- break;
- case 3:
- HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed03000;
- break;
- default:
- break;
- }
-
- *hptc = 0x80;
- io_mfence();
- }
- else
- {
-
- HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed00000;
- kwarn("There is no RCBA register on this computer, and HPET regs base use default value.");
- }
- }
- else
- {
- hpet_table = (struct acpi_HPET_description_table_t *)hpet_table_addr;
-
-
- HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + hpet_table->address;
- }
-
- uint64_t tmp;
- tmp = *(uint64_t *)(HPET_REG_BASE + GCAP_ID);
- HPET_COUNTER_CLK_PERIOD = (tmp >> 32) & 0xffffffff;
- HPET_freq = 1.0 * 1e15 / HPET_COUNTER_CLK_PERIOD;
- HPET_NUM_TIM_CAP = (tmp >> 8) & 0x1f;
-
- kdebug("HPET_freq=%ld", (long)HPET_freq);
-
- struct apic_IO_APIC_RTE_entry entry;
-
- apic_make_rte_entry(&entry, 34, IO_APIC_FIXED, DEST_PHYSICAL, IDLE, POLARITY_HIGH, IRR_RESET, EDGE_TRIGGER, MASKED, 0);
-
- uint64_t clks_to_intr = 0.001 * HPET0_INTERVAL * HPET_freq;
-
- if (clks_to_intr <= 0 || clks_to_intr > (HPET_freq * 8))
- {
- kBUG("HPET0: Numof clocks to generate interrupt is INVALID! value=%lld", clks_to_intr);
- while (1)
- hlt();
- }
- *(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0;
- io_mfence();
- *(uint64_t *)(HPET_REG_BASE + TIM0_CONF) = 0x004c;
- io_mfence();
- *(uint64_t *)(HPET_REG_BASE + TIM0_COMP) = clks_to_intr;
-
- io_mfence();
- rtc_get_cmos_time(&rtc_now);
- kinfo("HPET Initialized.");
- *(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 3;
- io_mfence();
-
- irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0");
- }
|