From a77b51699c6be368b4297abbedc368ab5343e1d5 Mon Sep 17 00:00:00 2001 From: Ruslan Isaev Date: Sun, 10 May 2026 23:11:54 +0300 Subject: [PATCH] sb16: finally make the driver work --- Makefile | 2 + include/sb16.h | 10 ++- src/drivers/sb16.c | 165 +++++++++++++++++++++++++++++++++++------ src/kernel/isr.c | 16 ++++ src/kernel/kernel.c | 2 +- src/tasking/syscalls.c | 21 +++++- 6 files changed, 186 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 2c25358..2968175 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,8 @@ iso: cp grubshit/main katauos/main cp grubshit/video.dat katauos/katau/video.dat cp grubshit/statx katauos/katau/statx + cp grubshit/kplayer katauos/katau/kplr + cp grubshit/iosys.wav katauos/katau/io.wav sudo umount tmp/ grub-mkrescue -o boot.iso katauos/ diff --git a/include/sb16.h b/include/sb16.h index a6778a4..334a21e 100644 --- a/include/sb16.h +++ b/include/sb16.h @@ -1,10 +1,12 @@ #ifndef SB16_H #define SB16_H -int sb16_dsp_reset(); -int sb16_get_irq(); -void* sb16_allocate_buf(); -void sb16_get_version(int* major, int* minor); +extern int sb16_irq; + +bool sb16_is_full(); +void sb16_ack(); +size_t sb16_write(uint8_t* input_buffer, size_t size); +bool sb16_is_playing(); void sb16_init(); #endif \ No newline at end of file diff --git a/src/drivers/sb16.c b/src/drivers/sb16.c index e2d9c4b..78c04e6 100644 --- a/src/drivers/sb16.c +++ b/src/drivers/sb16.c @@ -1,6 +1,11 @@ #include "../include/utils.h" #include "../include/paging.h" #include "../include/liballoc.h" +#include "../include/string.h" +#include "../include/sb16.h" +#include "../include/apic.h" +#include "../include/kheap.h" +#include "../include/task.h" #define DSP_RESET 0x226 #define DSP_READ 0x22A @@ -8,6 +13,32 @@ #define MIXER 0x224 #define MIXER_DATA 0x225 +extern bool lapic_enabled; +int sb16_irq = 0; + +void* buffer_phys; +void* buffer_virt; +#define BUFFER_PAGE_COUNT 16 +const size_t buffer_size = BUFFER_PAGE_COUNT*4096;//64 KB + +static uint8_t current_slot; +static bool slot_has_anything[2]; +static bool is_playing = false; + +static size_t slot_sizes[2]; + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +void sb16_enable_irq() { + if (!lapic_enabled) { + uint8_t mask = inb(0x21); + mask &= ~(1 << sb16_irq); + outb(0x21, mask); + } else { + ioapic_redirect(sb16_irq, 0x20 + sb16_irq); + } +} + int sb16_dsp_reset() { outb(DSP_RESET, 1); @@ -49,15 +80,11 @@ int sb16_get_irq() return irq; } -void* buffer; - -void* sb16_allocate_buf() +void sb16_allocate_buf() { - const size_t size = 64*1024;//64 KB - - buffer = malloc(size); - - return get_physaddr(buffer); + buffer_virt = kvalloc(BUFFER_PAGE_COUNT); + buffer_phys = get_physaddr(buffer_virt); + memset(buffer_virt, 0x80, buffer_size);//fill the buffer with silence } void sb16_get_version(int* major, int* minor) @@ -68,23 +95,25 @@ void sb16_get_version(int* major, int* minor) *minor = inb(DSP_READ); } -void sb16_program_dma() +void sb16_program_dma(uint32_t buf_size) { const int transfer_mode = 0x48; const int channel = 1; - const int page_number = 0;//page that contains sound data - int buffer_pos = (uint32_t)buffer & 0xffff; - int count = 0; + int buffer_pos = (uint32_t)buffer_phys + (current_slot << 15); + int count = buf_size; + + //printf("buffer_pos: %x buffer: %x\n", buffer_pos, buffer_phys); + //printf("buffer: 0x%x\n", ((uint32_t)buffer_phys >> 16) & 0xFF); outb(0x0A, 0x4 + channel);//0x4 + channel number (1 in this case) outb(0x0C, 1);//flip flop outb(0x0B, transfer_mode + channel); - outb(0x83, page_number); + outb(0x83, ((uint32_t)buffer_pos >> 16) & 0xFF); //set the position - outb(0x02, (buffer_pos) & 0xFF); - outb(0x02, (buffer_pos >> 8) & 0xFF); + outb(0x02, ((uint32_t)buffer_pos) & 0xFF); + outb(0x02, ((uint32_t)buffer_pos >> 8) & 0xFF); //set the count outb(0x03, (count - 1) & 0xFF); @@ -93,25 +122,102 @@ void sb16_program_dma() outb(0x0A, 1); } -void sb16_program() +void sb16_program(uint32_t buf_size) { - const int samples_count = 0; - outb(DSP_WRITE, 0x40);//time constant - outb(DSP_WRITE, 165);//10989 Hz + const int samples_count = buf_size; + outb(DSP_WRITE, 0x41);//sample rate + + const int sample_rate = 44100; + outb(DSP_WRITE, (sample_rate >> 8) & 0xff); + outb(DSP_WRITE, (sample_rate) & 0xff); + + outb(DSP_WRITE, 0xC0);//8-bit sound outb(DSP_WRITE, 0x00);//mono unsigned outb(DSP_WRITE, (samples_count - 1) & 0xFF); outb(DSP_WRITE, ((samples_count - 1) >> 8) & 0xFF); } +void sb16_stop() +{ + outb(DSP_WRITE, 0xD0); +} + +void sb16_play() +{ + outb(DSP_WRITE, 0xD4); +} + +bool sb16_is_playing() +{ + return is_playing; +} + +bool sb16_is_full() +{ + return slot_has_anything[0] && slot_has_anything[1]; +} + +void sb16_ack() +{ + inb(0x22E); + //debug_log("sb16: IRQ ACK, slot: 0x%X\n", current_slot); + slot_has_anything[current_slot] = false; + current_slot = !current_slot; + + if(slot_has_anything[current_slot]) + { + sb16_program_dma(slot_sizes[current_slot]); + sb16_program(slot_sizes[current_slot]); + } + else + { + debug_log("sb16: next slot contains nothing, stopping...\n"); + sb16_stop(); + is_playing = false; + } + +} + +size_t sb16_write(uint8_t* input_buffer, size_t size) +{ + const size_t out_size = min(size, 32768);//32KB max + const uint8_t next_slot = !current_slot; + + uint8_t *dst_buffer = buffer_virt + (next_slot << 15); + + memcpy(dst_buffer, input_buffer, out_size); + + if(out_size < 32768) + { + memset(dst_buffer + out_size, 0x80, 32768 - out_size); + } + + scheduler_lock(); + slot_sizes[next_slot] = out_size; + slot_has_anything[next_slot] = true; + + if(!is_playing){ + current_slot = next_slot; + + sb16_program_dma(slot_sizes[current_slot]); + sb16_program(slot_sizes[current_slot]); + is_playing = true; + } + scheduler_unlock(); + + return out_size; +} + void sb16_init() { int status = sb16_dsp_reset(); printf("sb16 status: 0x%X\n", status); - int sb16_irq = sb16_get_irq(); + sb16_irq = sb16_get_irq(); printf("sb16 irq: 0x%X\n", sb16_irq); - void* sb16_buffer = sb16_allocate_buf(); - printf("sb16 buffer: 0x%X\n", sb16_buffer); + + sb16_allocate_buf(); + printf("sb16 buffer: phys: 0x%X virt: 0x%X\n", buffer_phys, buffer_virt); int major, minor = 0; sb16_get_version(&major, &minor); @@ -119,6 +225,17 @@ void sb16_init() outb(DSP_WRITE, 0xD1);//enable speaker - sb16_program_dma(); - sb16_program(); + printf("PIC mask before enable: 0x%X\n", inb(0x21)); + sb16_enable_irq(); + printf("PIC mask after enable: 0x%X\n", inb(0x21)); + + current_slot = 0; + slot_has_anything[0] = false; + slot_has_anything[1] = false; + + outb(MIXER, 0x80); + printf("SB16 raw irq_code: 0x%X\n", inb(MIXER_DATA)); + + //sb16_program_dma(); + //sb16_program(); } \ No newline at end of file diff --git a/src/kernel/isr.c b/src/kernel/isr.c index 444431c..d351f30 100644 --- a/src/kernel/isr.c +++ b/src/kernel/isr.c @@ -5,6 +5,7 @@ #include "../include/keyboard.h" #include "../include/task.h" #include "../include/apic.h" +#include "../include/sb16.h" #include @@ -20,6 +21,7 @@ struct interrupt_frame __attribute__((interrupt)) void spurious(struct interrupt_frame *frame); __attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame); +__attribute__((interrupt)) void isr_sb16(struct interrupt_frame *frame); void isr_custom(); void default_handler(); @@ -65,6 +67,7 @@ void isr_install() { idt_set_descriptor(0x20, (uint32_t)isr_timer, 0x8E); idt_set_descriptor(0x21, (uint32_t)isr_custom, 0x8E); + idt_set_descriptor(0x25, (uint32_t)isr_sb16, 0x8E); idt_set_descriptor(0x80, (uint32_t)sys_exit_handler, 0xEE); @@ -149,6 +152,19 @@ __attribute__((interrupt)) void isr_custom(struct interrupt_frame *frame) } } +__attribute__((interrupt)) void isr_sb16(struct interrupt_frame *frame) +{ + sb16_ack(); + if(lapic_enabled) + { + lapic_eoi(); + } + else + { + pic_end_int(sb16_irq); + } +} + void isr0() { printf(exception_messages[0]); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 2b92a59..aea1f8c 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -143,7 +143,7 @@ void kmain(unsigned int magic, unsigned int info) sb16_init(); - //exec_from_file(&file, &dir); + exec_from_file(&file, &dir); while(1) { diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index db11f01..b13579c 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -256,6 +256,7 @@ int sys_read(TrapFrame *tf) } } +#include "../../include/sb16.h" int sys_write(TrapFrame *tf) { if(tf->ebx < 3) @@ -283,7 +284,25 @@ int sys_write(TrapFrame *tf) { return -EBADF; } - return 0;//fat_fwrite(current->file_descriptors[tf->ebx], (void*)tf->ecx, tf->edx); + + if(sb16_is_full()) + { + return 0; + } + + size_t sz = sb16_write((uint8_t*)tf->ecx, tf->edx); + + /* + scheduler_lock(); + current->wake_up_time = timer_ticks + 10; + current->state = Waiting; + current->waiting_reason = TIMER; + schedule(); + scheduler_unlock(); + */ + + return sz; + return 1;//fat_fwrite(current->file_descriptors[tf->ebx], (void*)tf->ecx, tf->edx); } }