sb16: finally make the driver work
This commit is contained in:
@@ -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
@@ -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
@@ -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();
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user