summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-05-05 09:54:48 -0400
committerFreya Murphy <freya@freyacat.org>2025-05-05 09:58:20 -0400
commit592c6992c7ea0c2e4cbea79fadb1c845f2fc050e (patch)
tree5d98b664749b67eb20d7fc279ff36bcf44843f21
parentoff by one (diff)
downloadcomus-592c6992c7ea0c2e4cbea79fadb1c845f2fc050e.tar.gz
comus-592c6992c7ea0c2e4cbea79fadb1c845f2fc050e.tar.bz2
comus-592c6992c7ea0c2e4cbea79fadb1c845f2fc050e.zip
pc spkr
Diffstat (limited to '')
-rw-r--r--Makefile1
-rw-r--r--kernel/cpu/idt.c9
-rw-r--r--kernel/drivers.c2
-rw-r--r--kernel/drivers/pit.c60
-rw-r--r--kernel/drivers/ps2.c15
-rw-r--r--kernel/include/comus/drivers/pit.h14
-rw-r--r--kernel/include/comus/drivers/ps2.h13
-rw-r--r--kernel/include/comus/drivers/spkr.h29
-rw-r--r--kernel/include/lib/klib.h5
-rw-r--r--kernel/lib/panic.c17
10 files changed, 144 insertions, 21 deletions
diff --git a/Makefile b/Makefile
index 3739534..2b78eb6 100644
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,7 @@ GRUB ?= grub-mkrescue
QEMUOPTS += -cdrom $(BIN)/$(ISO) \
-no-reboot \
-drive format=raw,file=user/bin/initrd.tar \
+ -audiodev pa,id=speaker -machine pcspk-audiodev=speaker \
-serial mon:stdio \
-m 4G \
-name kern
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index 7cbbb65..50e15e0 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -1,3 +1,5 @@
+#include "comus/drivers/spkr.h"
+#include "lib/klib.h"
#include <lib.h>
#include <comus/memory.h>
#include <comus/asm.h>
@@ -64,10 +66,11 @@ void idt_init(void)
uint64_t isr = (uint64_t)isr_stub_table[vector];
// interrupts before 0x20 are for cpu exceptions
+ uint64_t gate_type = (isr < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT;
entry->kernel_cs = 0x08; // offset of 1 into GDT
entry->ist = 0;
- entry->flags = PRESENT | RING0 | GATE_64BIT_INT;
+ entry->flags = PRESENT | RING0 | gate_type;
entry->isr_low = isr & 0xffff;
entry->isr_mid = (isr >> 16) & 0xffff;
entry->isr_high = (isr >> 32) & 0xffffffff;
@@ -148,9 +151,7 @@ __attribute__((noreturn)) void idt_exception_handler(uint64_t exception,
log_backtrace_ex((void *)state->rip, (void *)state->rbp);
- while (1) {
- halt();
- }
+ fatal_loop();
}
void isr_save(struct cpu_regs *regs)
diff --git a/kernel/drivers.c b/kernel/drivers.c
index 3d6ec10..572ab98 100644
--- a/kernel/drivers.c
+++ b/kernel/drivers.c
@@ -10,7 +10,7 @@
void drivers_init(void)
{
- pit_set_divider(1193); // 1ms
+ pit_set_freq(CHAN_TIMER, 1000); // 1ms
uart_init();
ps2_init();
pci_init();
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
index 53a9263..0c7a207 100644
--- a/kernel/drivers/pit.c
+++ b/kernel/drivers/pit.c
@@ -1,29 +1,65 @@
+#include "lib/klib.h"
#include <comus/asm.h>
#include <comus/drivers/pit.h>
+#include <comus/drivers/spkr.h>
+#include <lib.h>
-#define CHAN_0 0x40
-#define CHAN_1 0x41
-#define CHAN_2 0x42
#define CMD 0x43
+#define SPKR 0x61
+
+#define BASE 1193180
volatile uint64_t ticks = 0;
-uint16_t pit_read_divider(void)
+uint32_t pit_read_freq(uint8_t chan)
{
- uint16_t count = 0;
+ uint16_t div = 0;
cli();
outb(CMD, 0); // clear bits
- count = inb(CHAN_0); // low byte
- count |= inb(CHAN_0) << 8; // highbyte
+ div = inb(chan); // low byte
+ div |= inb(chan) << 8; // highbyte
sti();
- return count;
+ return div * BASE;
}
-void pit_set_divider(uint16_t count)
+void pit_set_freq(uint8_t chan, uint32_t hz)
{
- (void)count;
+ uint16_t div = BASE / hz;
cli();
- outb(CHAN_0, count & 0xFF); // low byte
- outb(CHAN_0, (count & 0xFF00) >> 8); // high byte
+ outb(CMD, 0xb6);
+ outb(chan, div & 0xFF); // low byte
+ outb(chan, (div & 0xFF00) >> 8); // high byte
sti();
}
+
+void spkr_play_tone(uint32_t hz)
+{
+ uint8_t reg;
+
+ if (hz == 0) {
+ spkr_quiet();
+ return;
+ }
+
+ // set spkr freq
+ pit_set_freq(CHAN_SPKR, hz);
+
+ // enable spkr gate
+ reg = inb(SPKR);
+ if (reg != (reg | 0x3))
+ outb(SPKR, reg | 0x3);
+}
+
+void spkr_quiet(void)
+{
+ uint8_t reg;
+ reg = inb(SPKR) & 0xFC;
+ outb(SPKR, reg);
+}
+
+void spkr_beep(void)
+{
+ spkr_play_tone(1000);
+ kspin_milliseconds(100);
+ spkr_quiet();
+}
diff --git a/kernel/drivers/ps2.c b/kernel/drivers/ps2.c
index e260f6b..f605c1d 100644
--- a/kernel/drivers/ps2.c
+++ b/kernel/drivers/ps2.c
@@ -266,3 +266,18 @@ int ps2_init(void)
sti();
return 0;
}
+
+int ps2_set_leds(uint8_t state)
+{
+ uint8_t result;
+
+ if (!(has_mouse || has_kbd))
+ return 1;
+
+ ps2ctrl_out_cmd(0xED);
+ ps2ctrl_out_data(state);
+ if ((result = ps2ctrl_in()) != 0xFA)
+ return 1;
+
+ return 0;
+}
diff --git a/kernel/include/comus/drivers/pit.h b/kernel/include/comus/drivers/pit.h
index 77f0a14..22b8153 100644
--- a/kernel/include/comus/drivers/pit.h
+++ b/kernel/include/comus/drivers/pit.h
@@ -9,13 +9,23 @@
#ifndef PIT_H_
#define PIT_H_
+#define CHAN_TIMER 0x40
+#define CHAN_SPKR 0x42
+
#include <stdint.h>
// how many time the pit has ticked
// not accurate time, good for spinning though
extern volatile uint64_t ticks;
-uint16_t pit_read_divider(void);
-void pit_set_divider(uint16_t count);
+/**
+ * Read timer frequency
+ */
+uint32_t pit_read_freq(uint8_t chan);
+
+/**
+ * Set timer frequency
+ */
+void pit_set_freq(uint8_t chan, uint32_t hz);
#endif
diff --git a/kernel/include/comus/drivers/ps2.h b/kernel/include/comus/drivers/ps2.h
index 7634e5f..c012ad4 100644
--- a/kernel/include/comus/drivers/ps2.h
+++ b/kernel/include/comus/drivers/ps2.h
@@ -9,6 +9,8 @@
#ifndef PS2_H_
#define PS2_H_
+#include <stdint.h>
+
/**
* Initalize the ps2 controller
*/
@@ -24,4 +26,15 @@ void ps2kb_recv(void);
*/
void ps2mouse_recv(void);
+/**
+ * Set ps2 led state
+ *
+ * Bits
+ * ----
+ * 0 - Scroll lock
+ * 1 - Num Lock
+ * 2 - Caps lock
+ */
+int ps2_set_leds(uint8_t state);
+
#endif /* ps2.h */
diff --git a/kernel/include/comus/drivers/spkr.h b/kernel/include/comus/drivers/spkr.h
new file mode 100644
index 0000000..f9e427e
--- /dev/null
+++ b/kernel/include/comus/drivers/spkr.h
@@ -0,0 +1,29 @@
+/**
+ * @file spkr.h
+ *
+ * @author Freya Murphy <freya@freyacat.org>
+ *
+ * PC Speaker
+ */
+
+#ifndef SPKR_H_
+#define SPKR_H_
+
+#include <stdint.h>
+
+/**
+ * Play a tone on the pc speaker continuously
+ */
+void spkr_play_tone(uint32_t hz);
+
+/**
+ * Shut up the pc speaker
+ */
+void spkr_quiet(void);
+
+/**
+ * Beep the pc speaker for a short period
+ */
+void spkr_beep(void);
+
+#endif /* spkr.h */
diff --git a/kernel/include/lib/klib.h b/kernel/include/lib/klib.h
index b4d26ed..f549a09 100644
--- a/kernel/include/lib/klib.h
+++ b/kernel/include/lib/klib.h
@@ -264,6 +264,11 @@ __attribute__((noreturn, format(printf, 3, 4))) void
__panic(unsigned int line, const char *file, const char *format, ...);
/**
+ * Loop kernel in fatal notifier (beep and blink caps lock key)
+ */
+__attribute__((noreturn)) void fatal_loop(void);
+
+/**
* Fill dst with a stack trace consisting of return addresses in order
* from top to bottom
*
diff --git a/kernel/lib/panic.c b/kernel/lib/panic.c
index 3a6e029..35ea0b1 100644
--- a/kernel/lib/panic.c
+++ b/kernel/lib/panic.c
@@ -1,6 +1,8 @@
#include <lib.h>
#include <stdarg.h>
#include <comus/asm.h>
+#include <comus/drivers/ps2.h>
+#include <comus/drivers/spkr.h>
__attribute__((noreturn)) void __panic(unsigned int line, const char *file,
const char *format, ...)
@@ -16,6 +18,17 @@ __attribute__((noreturn)) void __panic(unsigned int line, const char *file,
log_backtrace();
#endif
- while (1)
- halt();
+ fatal_loop();
+}
+
+__attribute__((noreturn)) void fatal_loop(void)
+{
+ while(1) {
+ spkr_play_tone(1000);
+ ps2_set_leds(0x4);
+ kspin_milliseconds(200);
+ spkr_quiet();
+ ps2_set_leds(0x0);
+ kspin_milliseconds(800);
+ }
}