/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: HPET driver * Author: Chloe M. */ #include #include #include #include #include #include #include #include #define DTRACE(Fmt, ...) \ TRACE("[ HPET ]: " Fmt, ##__VA_ARGS__) static VOID *MMIOBase = NULL; /* * Write a 64-bit value to an HPET register * * @Register: Register to write to * @Value: Value to write */ static VOID HpetWriteq(UCHAR Register, UQUAD Value) { VOID *RegBase; if (MMIOBase == NULL) { return; } RegBase = PTR_OFFSET(MMIOBase, Register); MMIOWrite64(MMIOBase, Value); } /* * Read a 64-bit value from an HPET register * * @Register: Register to read from */ static UQUAD HpetReadq(UCHAR Register) { VOID *RegBase; if (MMIOBase == NULL) { return 0; } RegBase = PTR_OFFSET(MMIOBase, Register); return MMIORead64(RegBase); } VOID MdHpetInit(VOID) { ACPI_HPET *Hpet; UQUAD GeneralCap; ULONG ClkPeriod; UCHAR RevId; const ACPI_GAS *Gas; Hpet = AcpiQuery("HPET"); if (Hpet == NULL) { KeKnot( KNOT_UNBOUND_RSRC, "could not detect HPET on this platform\n" ); } /* Some informational logging */ DTRACE("detected hpet with pci vendor id : %x\n", Hpet->PciVendorId); DTRACE("counter size : %d\n", Hpet->CounterSize); DTRACE("minimum tick : %d\n", Hpet->MinimumTick); /* Obtain the MMIO base address */ Gas = &Hpet->Gas; MMIOBase = PMA_TO_VMA(Gas->Address); GeneralCap = HpetReadq(HPET_GENERAL_CAP); ClkPeriod = (GeneralCap >> HPET_PERIOD_SHIFT) & HPET_PERIOD_MASK; RevId = GeneralCap & 0xFF; DTRACE("counter clk period : %d\n", ClkPeriod); /* * Verify that the clock period and the revision ID are not * garbage values. */ if (ClkPeriod > HPET_MAX_CLK_PERIOD) KeKnot(KNOT_MISC, "hpet: bad counter clk period\n"); if (RevId == 0) KeKnot(KNOT_MISC, "hpet: bad revision id, must not be zero\n"); }