#include "types.h" #include "machine/lapic.h" #include "machine/lapic_registers.h" #include "machine/core.h" namespace LAPIC { namespace Timer { /*! \brief Timer Delivery Status */ enum DeliveryStatus { IDLE = 0, SEND_PENDING = 1 }; /*! \brief Timer Mode */ enum TimerMode { ONE_SHOT = 0, PERIODIC = 1, DEADLINE = 2 // reserved }; /*! \brief Timer Mask */ enum Mask { NOT_MASKED = 0, MASKED = 1 }; static const Register INVALID_DIV = 0xff; /*! \brief LAPIC-Timer Control Register * * \see [ISDMv3 10.5.1 Local Vector Table](intel_manual_vol3.pdf#page=375) */ union ControlRegister { struct { uint32_t vector : 8; ///< Vector uint32_t : 4; DeliveryStatus delivery_status : 1; ///< Delivery Status uint32_t : 3; Mask masked : 1; ///< Interrupt Mask (if set, interrupt will not trigger) TimerMode timer_mode : 2; ///< Timer Mode uint32_t : 13; }; Register value; } __attribute__((packed)); /*! \brief LAPIC timer divider table * * \see [ISDMv3 10.5.4 APIC Timer](intel_manual_vol3.pdf#page=378) */ static const Register div_masks[] = { 0xb, ///< divides by 1 0x0, ///< divides by 2 0x1, ///< divides by 4 0x2, ///< divides by 8 0x3, ///< divides by 16 0x8, ///< divides by 32 0x9, ///< divides by 64 0xa ///< divides by 128 }; /*! \brief Calculate the bit mask for the LAPIC-timer divider. * \param div Divider, must be power of two: 1, 2, 4, 8, 16, 32, 64, 128 * \return Bit mask for LAPIC::Timer::set() or `0xff` if `div` is invalid. */ Register getClockDiv(uint8_t div) { // div is zero or not a power of two? if (div == 0 || (div & (div - 1)) != 0) { return INVALID_DIV; } int trail = __builtin_ctz(div); // count trailing 0-bits if (trail > 7) { return INVALID_DIV; } return div_masks[trail]; } uint32_t ticks(void) { uint32_t ticks = 0; // ticks per millisecond // Calculation (Assignment 5) return ticks; } void set(uint32_t counter, uint8_t divide, uint8_t vector, bool periodic, bool masked) { (void) counter; (void) divide; (void) vector; (void) periodic; (void) masked; } } // namespace Timer } // namespace LAPIC