sb16: finally make the driver work

This commit is contained in:
2026-05-20 14:50:17 +03:00
parent 312c543510
commit a77b51699c
6 changed files with 186 additions and 30 deletions
+2
View File
@@ -75,6 +75,8 @@ iso:
cp grubshit/main katauos/main cp grubshit/main katauos/main
cp grubshit/video.dat katauos/katau/video.dat cp grubshit/video.dat katauos/katau/video.dat
cp grubshit/statx katauos/katau/statx cp grubshit/statx katauos/katau/statx
cp grubshit/kplayer katauos/katau/kplr
cp grubshit/iosys.wav katauos/katau/io.wav
sudo umount tmp/ sudo umount tmp/
grub-mkrescue -o boot.iso katauos/ grub-mkrescue -o boot.iso katauos/
+6 -4
View File
@@ -1,10 +1,12 @@
#ifndef SB16_H #ifndef SB16_H
#define SB16_H #define SB16_H
int sb16_dsp_reset(); extern int sb16_irq;
int sb16_get_irq();
void* sb16_allocate_buf(); bool sb16_is_full();
void sb16_get_version(int* major, int* minor); void sb16_ack();
size_t sb16_write(uint8_t* input_buffer, size_t size);
bool sb16_is_playing();
void sb16_init(); void sb16_init();
#endif #endif
+141 -24
View File
@@ -1,6 +1,11 @@
#include "../include/utils.h" #include "../include/utils.h"
#include "../include/paging.h" #include "../include/paging.h"
#include "../include/liballoc.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_RESET 0x226
#define DSP_READ 0x22A #define DSP_READ 0x22A
@@ -8,6 +13,32 @@
#define MIXER 0x224 #define MIXER 0x224
#define MIXER_DATA 0x225 #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() int sb16_dsp_reset()
{ {
outb(DSP_RESET, 1); outb(DSP_RESET, 1);
@@ -49,15 +80,11 @@ int sb16_get_irq()
return irq; return irq;
} }
void* buffer; void sb16_allocate_buf()
void* sb16_allocate_buf()
{ {
const size_t size = 64*1024;//64 KB buffer_virt = kvalloc(BUFFER_PAGE_COUNT);
buffer_phys = get_physaddr(buffer_virt);
buffer = malloc(size); memset(buffer_virt, 0x80, buffer_size);//fill the buffer with silence
return get_physaddr(buffer);
} }
void sb16_get_version(int* major, int* minor) void sb16_get_version(int* major, int* minor)
@@ -68,23 +95,25 @@ void sb16_get_version(int* major, int* minor)
*minor = inb(DSP_READ); *minor = inb(DSP_READ);
} }
void sb16_program_dma() void sb16_program_dma(uint32_t buf_size)
{ {
const int transfer_mode = 0x48; const int transfer_mode = 0x48;
const int channel = 1; const int channel = 1;
const int page_number = 0;//page that contains sound data
int buffer_pos = (uint32_t)buffer & 0xffff; int buffer_pos = (uint32_t)buffer_phys + (current_slot << 15);
int count = 0; 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(0x0A, 0x4 + channel);//0x4 + channel number (1 in this case)
outb(0x0C, 1);//flip flop outb(0x0C, 1);//flip flop
outb(0x0B, transfer_mode + channel); outb(0x0B, transfer_mode + channel);
outb(0x83, page_number); outb(0x83, ((uint32_t)buffer_pos >> 16) & 0xFF);
//set the position //set the position
outb(0x02, (buffer_pos) & 0xFF); outb(0x02, ((uint32_t)buffer_pos) & 0xFF);
outb(0x02, (buffer_pos >> 8) & 0xFF); outb(0x02, ((uint32_t)buffer_pos >> 8) & 0xFF);
//set the count //set the count
outb(0x03, (count - 1) & 0xFF); outb(0x03, (count - 1) & 0xFF);
@@ -93,25 +122,102 @@ void sb16_program_dma()
outb(0x0A, 1); outb(0x0A, 1);
} }
void sb16_program() void sb16_program(uint32_t buf_size)
{ {
const int samples_count = 0; const int samples_count = buf_size;
outb(DSP_WRITE, 0x40);//time constant outb(DSP_WRITE, 0x41);//sample rate
outb(DSP_WRITE, 165);//10989 Hz
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, 0xC0);//8-bit sound
outb(DSP_WRITE, 0x00);//mono unsigned outb(DSP_WRITE, 0x00);//mono unsigned
outb(DSP_WRITE, (samples_count - 1) & 0xFF); outb(DSP_WRITE, (samples_count - 1) & 0xFF);
outb(DSP_WRITE, ((samples_count - 1) >> 8) & 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() void sb16_init()
{ {
int status = sb16_dsp_reset(); int status = sb16_dsp_reset();
printf("sb16 status: 0x%X\n", status); 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); 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; int major, minor = 0;
sb16_get_version(&major, &minor); sb16_get_version(&major, &minor);
@@ -119,6 +225,17 @@ void sb16_init()
outb(DSP_WRITE, 0xD1);//enable speaker outb(DSP_WRITE, 0xD1);//enable speaker
sb16_program_dma(); printf("PIC mask before enable: 0x%X\n", inb(0x21));
sb16_program(); 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();
} }
+16
View File
@@ -5,6 +5,7 @@
#include "../include/keyboard.h" #include "../include/keyboard.h"
#include "../include/task.h" #include "../include/task.h"
#include "../include/apic.h" #include "../include/apic.h"
#include "../include/sb16.h"
#include <stddef.h> #include <stddef.h>
@@ -20,6 +21,7 @@ struct interrupt_frame
__attribute__((interrupt)) void spurious(struct interrupt_frame *frame); __attribute__((interrupt)) void spurious(struct interrupt_frame *frame);
__attribute__((interrupt)) void isr_timer(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 isr_custom();
void default_handler(); void default_handler();
@@ -65,6 +67,7 @@ void isr_install() {
idt_set_descriptor(0x20, (uint32_t)isr_timer, 0x8E); idt_set_descriptor(0x20, (uint32_t)isr_timer, 0x8E);
idt_set_descriptor(0x21, (uint32_t)isr_custom, 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); 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() void isr0()
{ {
printf(exception_messages[0]); printf(exception_messages[0]);
+1 -1
View File
@@ -143,7 +143,7 @@ void kmain(unsigned int magic, unsigned int info)
sb16_init(); sb16_init();
//exec_from_file(&file, &dir); exec_from_file(&file, &dir);
while(1) while(1)
{ {
+20 -1
View File
@@ -256,6 +256,7 @@ int sys_read(TrapFrame *tf)
} }
} }
#include "../../include/sb16.h"
int sys_write(TrapFrame *tf) int sys_write(TrapFrame *tf)
{ {
if(tf->ebx < 3) if(tf->ebx < 3)
@@ -283,7 +284,25 @@ int sys_write(TrapFrame *tf)
{ {
return -EBADF; 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);
} }
} }