summaryrefslogtreecommitdiff
path: root/kc/core/pit8253.c
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2022-02-17 13:40:55 +0000
committerAda Christine <adachristine18@gmail.com>2022-02-17 13:40:55 +0000
commit9b63c0000b2e0d9d0a306e56dbc7bc28403e5549 (patch)
tree17ef5aa53d37c4232f8efcca97c5f118a96fb96f /kc/core/pit8253.c
parentb8ef8b401d9dd1e15f2703eb997fb79a70ae531a (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.c75
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;
}