Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
ecf733e
Add keyboard interrupts
amerikrainian Apr 5, 2025
9ca1113
basic hda interface
krathod18 Apr 7, 2025
4fae1be
Merge branch 'main' of https://github.com/TAOS-Labs/TAOS into audio
krathod18 Apr 7, 2025
95710d9
base address identified
krathod18 Apr 7, 2025
f78319e
set up regs and stream descrriptors
krathod18 Apr 8, 2025
0b0f46b
can send commands to hardwaree
krathod18 Apr 10, 2025
97d7cb4
lpib = 0
krathod18 Apr 11, 2025
8247086
added more print statements
krathod18 Apr 11, 2025
3c90924
Restored disappeared code
kiranchandrasekhar Apr 11, 2025
f6f75c7
Thread-safe MMIO ptrs + Eliminate HDA spinning
kiranchandrasekhar Apr 11, 2025
a67c0cb
fixed ? fmt ptr issue
kiranchandrasekhar Apr 11, 2025
fe0c166
changed some offsets
kiranchandrasekhar Apr 11, 2025
e52efe4
added widgets
krathod18 Apr 11, 2025
91ec0d7
widgets still 0
krathod18 Apr 13, 2025
e06fbbc
Refactor HdaRegisters to use MMioPtr
krathod18 Apr 14, 2025
19662a8
Cleaned some pointer issues
krathod18 Apr 14, 2025
efabdeb
LPIB still 0
krathod18 Apr 14, 2025
aa5289a
added manual wrrite for lpib
krathod18 Apr 14, 2025
1797d86
Small changes
kiranchandrasekhar Apr 11, 2025
4fea279
MMio generics
kiranchandrasekhar Apr 14, 2025
f031ec4
overflow panic
krathod18 Apr 15, 2025
d299c5f
fixed kernel panics
kiranchandrasekhar Apr 15, 2025
6eb7d48
Joseph will look into compile issues
krathod18 Apr 15, 2025
af99c60
corb/rirb works
krathod18 Apr 16, 2025
bf1fad5
modified limage_config.toml
krathod18 Apr 16, 2025
fc45984
Merge branch 'main' into audio
milkman1015 Apr 17, 2025
9f927f1
remade Cargo.lock
milkman1015 Apr 17, 2025
bb3d775
added enums for commands
krathod18 Apr 17, 2025
b139e6a
Began rewriting the code we have so far.
milkman1015 Apr 23, 2025
948f79d
finished trace_path_to_dac and set stream channel and alll
krathod18 Apr 23, 2025
cdea69f
for some reason I do not think the BDL is being read and I do not kno…
milkman1015 Apr 23, 2025
25644ff
LETS GOOOOOO
kiranchandrasekhar Apr 25, 2025
77a1f46
wav parserr
krathod18 Apr 25, 2025
b48d350
updated wav dependancies
krathod18 Apr 25, 2025
8e4c600
Patched wav crate
kiranchandrasekhar Apr 25, 2025
a89e579
fmt fixed
krathod18 Apr 25, 2025
64f42e0
wrong fmt
krathod18 Apr 27, 2025
3268deb
deleted one wav file
krathod18 Apr 27, 2025
da52635
new romantics running
krathod18 Apr 27, 2025
0658599
Removed thud at beginning of audio (now not including format data in …
kiranchandrasekhar Apr 27, 2025
bf19e25
probably enabled interrupts but I can not test so idk
milkman1015 Apr 27, 2025
d43dadc
removed assert(false) that I accidently pushed in my last commit
milkman1015 Apr 27, 2025
060ea8a
interrupts dont workk + kernel panic
krathod18 Apr 28, 2025
5924187
Co-authored-by: Wyatt Borden <milkman1015@users.noreply.github.com>
krathod18 Apr 28, 2025
26fd7dd
some version of new romantics playing
krathod18 Apr 28, 2025
d139178
contiguous bytes
krathod18 Apr 28, 2025
d000474
song works
krathod18 Apr 28, 2025
a47bb18
audio working
krathod18 Apr 28, 2025
efa5c0a
some initial setup
milkman1015 Apr 28, 2025
c238465
got something running but it sounds crunchy and speed up
milkman1015 Apr 29, 2025
105ab3e
figured out that stereo does not work for some reason and ioc sts bit…
milkman1015 Apr 30, 2025
ca127f1
was able to change the bdl once one completes, so we can now play a w…
milkman1015 Apr 30, 2025
405c253
removed some things from config that I require to run on personal mac…
milkman1015 May 2, 2025
0329676
I think we can play audio of any length but we have not been able to …
milkman1015 May 2, 2025
923c9fb
removed all debug prints and a couple of unnecessary files
milkman1015 May 2, 2025
e93702f
made a struct that was public only within its crate pub everywhere
milkman1015 May 2, 2025
ba5c441
Merge branch 'main' into audio
milkman1015 May 2, 2025
e3e4923
final commit before making PR
milkman1015 May 2, 2025
ba96588
rust updated so I had to make one last change to make the crab happy
milkman1015 May 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
/target

.DS_Store
kernel/qemu.wav
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ Compilation has been tested with WSL, Linux, and Mac. We provide no guarantees t
- To run in terminal mode: make run-term
- To run tests: make test
- To ensure compliance with clippy and formatting: make check
- To format: make fmt
- To format: make fmt
- If you want to hear audio, uncomment [kernel/src/devices/audio/hda.rs:137](kernel/src/devices/audio/hda.rs#L137) and run in terminal mode
Binary file added kernel/.DS_Store
Binary file not shown.
22 changes: 14 additions & 8 deletions kernel/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ futures-util = { version = "0.3.31", default-features = false, features = [
"async-await-macro",
"futures-macro",
] }
wavv = {version = "0.2.0"}
goblin = { version = "0.9.3", default-features = false, features = [
"alloc",
"elf64",
Expand Down Expand Up @@ -59,3 +60,6 @@ talc = "4.4.2"
uart_16550 = "0.3.2"
x86_64 = "0.15.2"
zerocopy = { version = "0.8", features = ["derive"] }

[patch.crates-io]
wavv = { git = 'https://github.com/samuelleeuwenburg/wavv.git' }
5 changes: 3 additions & 2 deletions kernel/limage_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ base_args = [
"-device", "usb-net,netdev=net0",

# Audio
"-device", "intel-hda",
"-device", "hda-duplex",
"-audiodev", "wav,id=snd0",
"-device", "intel-hda,debug=0",
"-device", "hda-duplex,audiodev=snd0",

# General Storage
"-drive", "id=mysdcard,file=storage_test.img,if=none,format=raw",
Expand Down
Binary file added kernel/src/.DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions kernel/src/constants/devices.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub const SD_REQ_TIMEOUT_NANOS: u64 = 1_000_000_000;

pub const TEST_WAV: &[u8] = include_bytes!("../devices/audio/new_romantics_swift.wav");
1 change: 1 addition & 0 deletions kernel/src/constants/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ pub const TIMER_VECTOR: u8 = 32;
pub const SYSCALL_HANDLER: u8 = 0x80;
pub const KEYBOARD_VECTOR: u8 = 33;
pub const MOUSE_VECTOR: u8 = 44;
pub const HDA_VECTOR: u8 = 45;

pub const TLB_SHOOTDOWN_VECTOR: u8 = 33;
4 changes: 2 additions & 2 deletions kernel/src/constants/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ pub const FRAME_SIZE: usize = 4096;
pub const HEAP_START: *mut u8 = 0x_FFFF_8100_0000_0000 as *mut u8;

/// Initial size of the kernel heap (10 MB).
pub const HEAP_SIZE: usize = 1024 * 1024 * 10;
pub const HEAP_SIZE: usize = 1024 * 1024 * 30;

/// Maximum number of frames that can be allocated.
pub const MAX_ALLOCATED_FRAMES: usize = 1024 * 5;
pub const MAX_ALLOCATED_FRAMES: usize = 1024 * 10;

/// Size of each bitmap entry in bits.
pub const BITMAP_ENTRY_SIZE: usize = 64;
Expand Down
Binary file added kernel/src/devices/.DS_Store
Binary file not shown.
Binary file added kernel/src/devices/audio/.DS_Store
Binary file not shown.
61 changes: 61 additions & 0 deletions kernel/src/devices/audio/buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use core::ptr::write_volatile;

/// Intel HDA Buffer Descriptor (BDL) Entry
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct BdlEntry {
pub address: u32,
pub address_high: u32,
pub length: u32,
pub flags: u32,
}

impl BdlEntry {
pub const IOC_FLAG: u32 = 1;

pub fn new(addr: u64, len: u32, interrupt_on_completion: bool) -> Self {
BdlEntry {
address: addr as u32,
address_high: (addr >> 32) as u32,
length: len,
flags: if interrupt_on_completion {
Self::IOC_FLAG
} else {
0
},
}
}
}
/// Write BDL entries into the physical memory region (must be DMA accessible)
///
/// # Safety
/// preforms a pointer write
pub unsafe fn setup_bdl(
bdl_virt_addr: *mut BdlEntry,
buffer_phys_start: u64,
total_size: u32,
entry_size: u32,
) -> usize {
let num_entries_needed = total_size.div_ceil(entry_size) as u64;
let num_entries = if num_entries_needed > 256 {
256
} else {
num_entries_needed
};

let mut offset = 0;

for i in 0..num_entries {
let phys_addr = buffer_phys_start + offset as u64;
let is_last = i == num_entries - 1;
let entry = BdlEntry::new(phys_addr, entry_size, is_last);

unsafe {
write_volatile(bdl_virt_addr.add(i as usize), entry);
}

offset += entry_size;
}

num_entries as usize
}
181 changes: 181 additions & 0 deletions kernel/src/devices/audio/command_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
use crate::devices::audio::dma::DmaBuffer;
use core::ptr::{read_volatile, write_volatile};

use super::commands::{CorbEntry, RirbEntry};

// These bitflags are not a bad idea, they should have been actual bitflags types and we should have used them
// TODO: refactor some of this code to be nicer.
// const CORBRUN: u8 = 1 << 1;
// const CORBRPRST: u16 = 1 << 15;
// const RIRBDMAEN: u8 = 1 << 1;
// const RINTCTL: u8 = 1 << 0;
// const RIRBWPRST: u16 = 1 << 15;
// const ICB: u16 = 1 << 0;
// const IRV: u16 = 1 << 1;

#[derive(Copy, Clone)]
pub struct WidgetAddr(pub u8, pub u8);

/// A struct for operating the CORB
pub struct CorbBuffer {
/// The virtual base address of the CORB
pub base: u64,
/// The physical base address of the CORB
pub phys_base: u64,
/// The next block to be written to. It is an index
pub write_idx: u16,
/// The next block to read from, only hear to see when the CORB is full.
pub read_idx: u16,
/// Then number of entries that are in this CORB
pub size: u16,
}

unsafe impl Send for CorbBuffer {}
unsafe impl Sync for CorbBuffer {}

impl CorbBuffer {
/// Initializes a new CORB
///
/// # Arguments
/// * `base`: a DmaBuffer object that points to the memory that the CORB is on
/// * `size`: The number of entries that are contained in this CORB
///
/// # Returns
/// `self`
pub fn new(base: &DmaBuffer, size: u16) -> Self {
Self {
base: base.virt_addr.as_u64(),
phys_base: base.phys_addr.as_u64(),
write_idx: 0,
read_idx: 0,
size,
}
}

/// Returns the index of the last written command
pub fn get_write_idx(&self) -> u16 {
self.write_idx
}

/// Returns the index of the last read command from the hardware
pub fn get_read_idx(&self) -> u16 {
self.read_idx
}

/// Sets the read idx to `idx`
pub fn set_read_idx(&mut self, idx: u16) {
self.read_idx = idx;
}

/// Checks to see if the CORB is full
///
/// # Returns
/// * `true` if `write_idx + 1 == read_idx`
/// * `false` otherwise
pub fn is_full(&self) -> bool {
let mut next_write = self.write_idx + 1;
if next_write == self.size {
next_write = 0;
}
next_write == self.read_idx
}

/// Sends a cmd onto the CORB and increments the write index
///
/// # Arguments
/// * `cmd`: the command to be written onto the CORB
///
/// # Safety
/// This function preforms a raw pointer write to write the command to the CORB. This function assumes that the CORB is not full.
pub async unsafe fn send(&mut self, cmd: CorbEntry) {
assert!(!self.is_full());
let mut next_write = self.write_idx + 1;
if next_write == self.size {
next_write = 0;
}

let write_address = (self.base + next_write as u64 * 4) as *mut CorbEntry;
write_volatile(write_address, cmd);

self.write_idx = next_write;
}
}

/// A struct for operating the RIRB
pub struct RirbBuffer {
/// The virtual base address of the RIRB
pub base: u64,
/// The physical base address of the RIRB
pub phys_base: u64,
/// The next block to be written to
pub write_idx: u16,
/// The next block to read from
pub read_idx: u16,
/// Then number of entries that are in this RIRB
pub size: u16,
}

unsafe impl Send for RirbBuffer {}
unsafe impl Sync for RirbBuffer {}

impl RirbBuffer {
/// Initializes a new RIRB
///
/// # Arguments
/// * `base`: a DmaBuffer object that points to the memory that the RIRB is on
/// * `size`: The number of entries that are contained in this RIRB
///
/// # Returns
/// `self`
pub fn new(base: &DmaBuffer, size: u16) -> Self {
Self {
base: base.virt_addr.as_u64(),
phys_base: base.phys_addr.as_u64(),
write_idx: 0,
read_idx: 0,
size,
}
}

/// Returns the current read index
pub fn get_read_idx(&self) -> u16 {
self.read_idx
}

/// Sets the read index
pub fn set_read_idx(&mut self, idx: u16) {
self.read_idx = idx;
}

/// sets the index of the last written command
pub fn set_write_idx(&mut self, idx: u16) {
self.write_idx = idx;
}

/// Checks to see if the RIRB is empty
///
/// # Returns
/// * `true` if `write_idx == read_idx`
/// * `false` otherwise
pub fn is_empty(&self) -> bool {
self.write_idx == self.read_idx
}

/// Reads the next response from the RIRB and increments the read index
///
/// # Returns
/// Returns the 8 byte response that is on the RIRB
///
/// # Safety
/// This function preforms a raw pointer read to read from the RIRB. This function assumes that the RIRB is not empty.
pub async unsafe fn read(&mut self) -> RirbEntry {
assert!(!self.is_empty());
let next_idx = (self.read_idx + 1) % self.size;

let read_addr = (self.base + (next_idx as u64 * 8)) as *mut RirbEntry;
let response = read_volatile(read_addr);

self.read_idx = next_idx;
response
}
}
Loading
Loading