diff options
| author | Ada Christine <adachristine18@gmail.com> | 2022-02-17 13:40:55 +0000 |
|---|---|---|
| committer | Ada Christine <adachristine18@gmail.com> | 2022-02-17 13:40:55 +0000 |
| commit | 9b63c0000b2e0d9d0a306e56dbc7bc28403e5549 (patch) | |
| tree | 17ef5aa53d37c4232f8efcca97c5f118a96fb96f /kc/core/pit8253.c | |
| parent | b8ef8b401d9dd1e15f2703eb997fb79a70ae531a (diff) | |
many changes have happned
- updates to panic() interface
- genericized timer interface
- (yet unused) additions to task management
Diffstat (limited to 'kc/core/pit8253.c')
| -rw-r--r-- | kc/core/pit8253.c | 75 |
1 files changed, 56 insertions, 19 deletions
diff --git a/kc/core/pit8253.c b/kc/core/pit8253.c index 0cf5232..4728020 100644 --- a/kc/core/pit8253.c +++ b/kc/core/pit8253.c @@ -3,6 +3,8 @@ #include "port.h" #include "kprint.h" +#include <stdatomic.h> + #define PIT8253_DATA0 0x40 #define PIT8253_CMD 0x43 @@ -13,51 +15,86 @@ #define CONFIG_CHANNEL_0 (SEL_CHANNEL0|ACC_LOHI|MODE_RATE|BIN_COUNT) +#define PIT_IRQ 0 #define PIT_HZ 1193182U +#define PIT_HZ_MIN (PIT_HZ/0xffff) + +static void pit8253_set_divisor(uint16_t divisor); -static uint64_t count = 0; +static atomic_uint_fast64_t count = 0; +static uint16_t divisor = 0; + +const struct timer_source pit8253_timer_source = +{ + "pit8253", + pit8253_init, + pit8253_start, + pit8253_stop, + + pit8253_set_frequency, + pit8253_get_frequency, + + pit8253_nanoseconds_elapsed, + pit8253_nanoseconds_delta +}; int pit8253_callback(uint8_t irq) { (void)irq; count++; - if (!(count % (185))) - { - kprintf("it's been about %lu seconds since starting\n", count / 18); - } - return 0; } void pit8253_init(void) { - kprintf( - "initializing timer to an approximate frequency of %uHz\n", - PIT_HZ / 0xffff); - outb(PIT8253_CMD, CONFIG_CHANNEL_0); - outb(PIT8253_DATA0, 0xff); - outb(PIT8253_DATA0, 0xff); - - pic8259_irq_install(0, pit8253_callback); - pic8259_irq_unmask(0); + pic8259_irq_install(PIT_IRQ, pit8253_callback); } void pit8253_start(void) { + pic8259_irq_unmask(PIT_IRQ); } void pit8253_stop(void) { + pic8259_irq_mask(PIT_IRQ); } -uint64_t pit8253_count(void) +void pit8253_set_frequency(uint32_t frequency) { - return count; + uint32_t d = PIT_HZ / frequency; + + if (d > UINT16_MAX) + { + kprintf("warning: %uHz is too slow for 8253 pit\n", PIT_HZ/d); + d = UINT16_MAX; + kprintf("warning: set timer to minimum frequency\n"); + } + + pit8253_set_divisor(d); +} + +uint32_t pit8253_get_frequency(void) +{ + return PIT_HZ/divisor; +} + +uint64_t pit8253_nanoseconds_elapsed(void) +{ + return pit8253_nanoseconds_delta() * count; +} + +uint64_t pit8253_nanoseconds_delta(void) +{ + return (TIMER_NANOSECOND * divisor)/PIT_HZ; } -void pit8253_set_hz(uint16_t hz) +static void pit8253_set_divisor(uint16_t d) { - (void)hz; + outb(PIT8253_CMD, CONFIG_CHANNEL_0); + outb(PIT8253_DATA0, (uint8_t)d); + outb(PIT8253_DATA0, (uint8_t)(d >> 8)); + divisor = d; } |
