sb16: finally make the driver work
This commit is contained in:
@@ -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/
|
||||
|
||||
+6
-4
@@ -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
|
||||
+141
-24
@@ -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();
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../include/keyboard.h"
|
||||
#include "../include/task.h"
|
||||
#include "../include/apic.h"
|
||||
#include "../include/sb16.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -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]);
|
||||
|
||||
+1
-1
@@ -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)
|
||||
{
|
||||
|
||||
+20
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user