diff options
author | Freya Murphy <freya@freyacat.org> | 2025-05-05 09:54:48 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-05-05 09:58:20 -0400 |
commit | 592c6992c7ea0c2e4cbea79fadb1c845f2fc050e (patch) | |
tree | 5d98b664749b67eb20d7fc279ff36bcf44843f21 | |
parent | off by one (diff) | |
download | comus-592c6992c7ea0c2e4cbea79fadb1c845f2fc050e.tar.gz comus-592c6992c7ea0c2e4cbea79fadb1c845f2fc050e.tar.bz2 comus-592c6992c7ea0c2e4cbea79fadb1c845f2fc050e.zip |
pc spkr
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | kernel/cpu/idt.c | 9 | ||||
-rw-r--r-- | kernel/drivers.c | 2 | ||||
-rw-r--r-- | kernel/drivers/pit.c | 60 | ||||
-rw-r--r-- | kernel/drivers/ps2.c | 15 | ||||
-rw-r--r-- | kernel/include/comus/drivers/pit.h | 14 | ||||
-rw-r--r-- | kernel/include/comus/drivers/ps2.h | 13 | ||||
-rw-r--r-- | kernel/include/comus/drivers/spkr.h | 29 | ||||
-rw-r--r-- | kernel/include/lib/klib.h | 5 | ||||
-rw-r--r-- | kernel/lib/panic.c | 17 |
10 files changed, 144 insertions, 21 deletions
@@ -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); + } } |