Replace all physalloc usages with Dma.
This commit is contained in:
@@ -86,6 +86,16 @@ impl<T> Dma<[T]> {
|
||||
|
||||
Ok(Dma { phys, aligned_len, virt: ptr::slice_from_raw_parts_mut(virt.cast(), count) })
|
||||
}
|
||||
pub unsafe fn cast_slice<U>(self) -> Dma<[U]> {
|
||||
let Dma { phys, virt, aligned_len } = self;
|
||||
core::mem::forget(self);
|
||||
|
||||
Dma {
|
||||
phys,
|
||||
virt: virt as *mut [U],
|
||||
aligned_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> Dma<[MaybeUninit<T>]> {
|
||||
pub unsafe fn assume_init(self) -> Dma<[T]> {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use common::dma::Dma;
|
||||
use syscall::io::{Io, Mmio};
|
||||
|
||||
use super::common::*;
|
||||
@@ -345,31 +346,33 @@ pub struct CommandBuffer {
|
||||
corb_rirb_base_phys: usize,
|
||||
|
||||
use_immediate_cmd: bool,
|
||||
mem: Dma<[u8; 0x1000]>,
|
||||
}
|
||||
|
||||
impl CommandBuffer {
|
||||
pub fn new(
|
||||
regs_addr: usize,
|
||||
cmd_buff_frame_phys: usize,
|
||||
cmd_buff_frame: usize,
|
||||
cmd_buff: Dma<[u8; 0x1000]>,
|
||||
) -> CommandBuffer {
|
||||
let corb = Corb::new(regs_addr + CORB_OFFSET, cmd_buff_frame_phys, cmd_buff_frame);
|
||||
let corb = Corb::new(regs_addr + CORB_OFFSET, cmd_buff.physical(), cmd_buff.as_ptr() as usize);
|
||||
let rirb = Rirb::new(
|
||||
regs_addr + RIRB_OFFSET,
|
||||
cmd_buff_frame_phys + CORB_BUFF_MAX_SIZE,
|
||||
cmd_buff_frame + CORB_BUFF_MAX_SIZE,
|
||||
cmd_buff.as_ptr() as usize + CORB_BUFF_MAX_SIZE,
|
||||
cmd_buff.physical() + CORB_BUFF_MAX_SIZE,
|
||||
);
|
||||
|
||||
let icmd = ImmediateCommand::new(regs_addr + ICMD_OFFSET);
|
||||
|
||||
let cmdbuff = CommandBuffer {
|
||||
corb: corb,
|
||||
rirb: rirb,
|
||||
icmd: icmd,
|
||||
corb,
|
||||
rirb,
|
||||
icmd,
|
||||
|
||||
corb_rirb_base_phys: cmd_buff_frame_phys,
|
||||
corb_rirb_base_phys: cmd_buff.physical(),
|
||||
|
||||
use_immediate_cmd: false,
|
||||
|
||||
mem: cmd_buff,
|
||||
};
|
||||
|
||||
cmdbuff
|
||||
|
||||
+16
-25
@@ -7,6 +7,7 @@ use std::str;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use common::dma::Dma;
|
||||
use syscall::error::{Error, EACCES, EBADF, Result, EINVAL};
|
||||
use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END};
|
||||
use syscall::io::{Mmio, Io};
|
||||
@@ -137,8 +138,7 @@ pub struct IntelHDA {
|
||||
|
||||
beep_addr: WidgetAddr,
|
||||
|
||||
buff_desc: &'static mut [BufferDescriptorListEntry; 256],
|
||||
buff_desc_phys: usize,
|
||||
buff_desc: Dma<[BufferDescriptorListEntry; 256]>,
|
||||
|
||||
output_streams: Vec<OutputStream>,
|
||||
|
||||
@@ -153,31 +153,23 @@ impl IntelHDA {
|
||||
pub unsafe fn new(base: usize, vend_prod:u32) -> Result<Self> {
|
||||
let regs = &mut *(base as *mut Regs);
|
||||
|
||||
let buff_desc_phys =
|
||||
syscall::physalloc(0x1000)
|
||||
.expect("Could not allocate physical memory for buffer descriptor list.");
|
||||
let buff_desc = Dma::<[BufferDescriptorListEntry; 256]>::zeroed()
|
||||
.expect("Could not allocate physical memory for buffer descriptor list.")
|
||||
.assume_init();
|
||||
|
||||
let buff_desc_virt =
|
||||
common::physmap(buff_desc_phys, 0x1000, common::Prot::RW, common::MemoryType::Uncacheable)
|
||||
.expect("ihdad: failed to map address for buffer descriptor list.") as usize;
|
||||
log::debug!("Virt: {:016X}, Phys: {:016X}", buff_desc.as_ptr() as usize, buff_desc.physical());
|
||||
|
||||
log::debug!("Virt: {:016X}, Phys: {:016X}", buff_desc_virt, buff_desc_phys);
|
||||
let cmd_buff = Dma::<[u8; 0x1000]>::zeroed()
|
||||
.expect("Could not allocate physical memory for CORB and RIRB.")
|
||||
.assume_init();
|
||||
|
||||
let buff_desc = &mut *(buff_desc_virt as *mut [BufferDescriptorListEntry;256]);
|
||||
|
||||
let cmd_buff_address =
|
||||
syscall::physalloc(0x1000)
|
||||
.expect("Could not allocate physical memory for CORB and RIRB.");
|
||||
|
||||
let cmd_buff_virt = common::physmap(cmd_buff_address, 0x1000, common::Prot::RW, common::MemoryType::Uncacheable).expect("ihdad: failed to map address for CORB/RIRB buff") as usize;
|
||||
|
||||
log::debug!("Virt: {:016X}, Phys: {:016X}", cmd_buff_virt, cmd_buff_address);
|
||||
log::debug!("Virt: {:016X}, Phys: {:016X}", cmd_buff.as_ptr() as usize, cmd_buff.physical());
|
||||
let mut module = IntelHDA {
|
||||
vend_prod: vend_prod,
|
||||
base: base,
|
||||
regs: regs,
|
||||
vend_prod,
|
||||
base,
|
||||
regs,
|
||||
|
||||
cmd: CommandBuffer::new(base + COMMAND_BUFFER_OFFSET, cmd_buff_address, cmd_buff_virt),
|
||||
cmd: CommandBuffer::new(base + COMMAND_BUFFER_OFFSET, cmd_buff),
|
||||
|
||||
beep_addr: (0,0),
|
||||
|
||||
@@ -191,8 +183,7 @@ impl IntelHDA {
|
||||
output_pins: Vec::<WidgetAddr>::new(),
|
||||
input_pins: Vec::<WidgetAddr>::new(),
|
||||
|
||||
buff_desc: buff_desc,
|
||||
buff_desc_phys: buff_desc_phys,
|
||||
buff_desc,
|
||||
|
||||
output_streams: Vec::<OutputStream>::new(),
|
||||
|
||||
@@ -498,7 +489,7 @@ impl IntelHDA {
|
||||
|
||||
// Create output stream
|
||||
let output = self.get_output_stream_descriptor(0).unwrap();
|
||||
output.set_address(self.buff_desc_phys);
|
||||
output.set_address(self.buff_desc.physical());
|
||||
output.set_pcm_format(&super::SR_44_1, BitsPerSample::Bits16, 2);
|
||||
output.set_cyclic_buffer_length((NUM_SUB_BUFFS * SUB_BUFF_SIZE) as u32); // number of bytes
|
||||
output.set_stream_number(1);
|
||||
|
||||
+7
-40
@@ -1,3 +1,4 @@
|
||||
use common::dma::Dma;
|
||||
use syscall::PAGE_SIZE;
|
||||
use syscall::error::{Error, EIO, Result};
|
||||
use syscall::io::{Mmio, Io};
|
||||
@@ -281,8 +282,7 @@ impl BufferDescriptorListEntry {
|
||||
}
|
||||
|
||||
pub struct StreamBuffer {
|
||||
phys: usize,
|
||||
addr: usize,
|
||||
mem: Dma<[u8]>,
|
||||
|
||||
block_cnt: usize,
|
||||
block_len: usize,
|
||||
@@ -293,36 +293,10 @@ pub struct StreamBuffer {
|
||||
impl StreamBuffer {
|
||||
pub fn new(block_length: usize, block_count: usize) -> result::Result<StreamBuffer, &'static str> {
|
||||
let page_aligned_size = (block_length * block_count).next_multiple_of(PAGE_SIZE);
|
||||
|
||||
let phys = match unsafe {
|
||||
syscall::physalloc(page_aligned_size)
|
||||
} {
|
||||
Ok(phys) => phys,
|
||||
Err(_err) => {
|
||||
return Err("Could not allocate physical memory for buffer.");
|
||||
}
|
||||
};
|
||||
|
||||
let addr = match unsafe {
|
||||
common::physmap(phys, page_aligned_size, common::Prot::RW, common::MemoryType::Uncacheable)
|
||||
} {
|
||||
Ok(ptr) => ptr as usize,
|
||||
Err(_err) => {
|
||||
unsafe {
|
||||
syscall::physfree(phys, page_aligned_size);
|
||||
}
|
||||
return Err("Could not map physical memory for buffer.");
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Already zeroed by kernel?
|
||||
unsafe {
|
||||
ptr::write_bytes(addr as *mut u8, 0, block_length * block_count);
|
||||
}
|
||||
let mem = unsafe { Dma::zeroed_slice(page_aligned_size).map_err(|_| "Could not allocate physical memory for buffer.")?.assume_init() };
|
||||
|
||||
Ok(StreamBuffer {
|
||||
phys: phys,
|
||||
addr: addr,
|
||||
mem,
|
||||
block_len: block_length,
|
||||
block_cnt: block_count,
|
||||
cur_pos: 0,
|
||||
@@ -334,11 +308,11 @@ impl StreamBuffer {
|
||||
}
|
||||
|
||||
pub fn addr(&self) -> usize {
|
||||
self.addr
|
||||
self.mem.as_ptr() as usize
|
||||
}
|
||||
|
||||
pub fn phys(&self) -> usize {
|
||||
self.phys
|
||||
self.mem.physical()
|
||||
}
|
||||
|
||||
pub fn block_size(&self) -> usize {
|
||||
@@ -374,13 +348,6 @@ impl StreamBuffer {
|
||||
}
|
||||
impl Drop for StreamBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
log::debug!("IHDA: Deallocating buffer.");
|
||||
let page_aligned_size = (self.block_len * self.block_cnt).next_multiple_of(PAGE_SIZE);
|
||||
|
||||
if syscall::funmap(self.addr, page_aligned_size).is_ok() {
|
||||
let _ = syscall::physfree(self.phys, page_aligned_size);
|
||||
}
|
||||
}
|
||||
log::debug!("IHDA: Deallocating buffer.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{sync::{Weak, atomic::{AtomicU16, Ordering}, Arc}, mem::size_of, fs::Fi
|
||||
use common::dma::Dma;
|
||||
use syscall::{Pio, Io};
|
||||
|
||||
use crate::{transport::{NotifyBell, Transport, Queue, Error, Available, Used, queue_part_sizes, spawn_irq_thread}, spec::{Descriptor, DeviceStatusFlags}};
|
||||
use crate::{transport::{NotifyBell, Transport, Queue, Error, Available, Used, queue_part_sizes, spawn_irq_thread, Mem, Borrowed}, spec::{Descriptor, DeviceStatusFlags}};
|
||||
|
||||
|
||||
pub enum LegacyRegister {
|
||||
@@ -123,10 +123,12 @@ impl Transport for LegacyTransport {
|
||||
};
|
||||
|
||||
let avail_addr = descriptor.physical() + desc_size;
|
||||
let avail = unsafe { Available::from_raw(avail_addr, avail_size, queue_size)? };
|
||||
let avail_virt = (descriptor.as_ptr() as usize) + desc_size;
|
||||
let avail = unsafe { Available::from_raw(Mem::Borrowed(Borrowed::new(avail_addr, avail_virt, avail_size)), queue_size)? };
|
||||
|
||||
let used_addr = avail_addr + avail_size;
|
||||
let used = unsafe { Used::from_raw(used_addr, used_size, queue_size)? };
|
||||
let used_virt = avail_virt + desc_size;
|
||||
let used = unsafe { Used::from_raw(Mem::Borrowed(Borrowed::new(used_addr, used_virt, used_size)), queue_size)? };
|
||||
|
||||
self.write::<u16>(LegacyRegister::QueueMsixVector, vector);
|
||||
self.write::<u32>(LegacyRegister::QueueAddress, (descriptor.physical() as u32) >> 12);
|
||||
|
||||
@@ -263,33 +263,68 @@ unsafe impl Sync for Queue<'_> {}
|
||||
unsafe impl Send for Queue<'_> {}
|
||||
|
||||
pub struct Available<'a> {
|
||||
addr: usize,
|
||||
size: usize,
|
||||
|
||||
mem: Mem<'a>,
|
||||
queue_size: usize,
|
||||
|
||||
ring: &'a mut AvailableRing,
|
||||
}
|
||||
pub struct Borrowed<'a> {
|
||||
phys: usize,
|
||||
virt: usize,
|
||||
size: usize,
|
||||
_unused: &'a (),
|
||||
}
|
||||
pub enum Mem<'a> {
|
||||
Owned(Dma<[u8]>),
|
||||
Borrowed(Borrowed<'a>),
|
||||
}
|
||||
impl Borrowed<'_> {
|
||||
pub unsafe fn new(phys: usize, virt: usize, size: usize) -> Self {
|
||||
Self {
|
||||
phys,
|
||||
virt,
|
||||
size,
|
||||
_unused: &(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> Mem<'a> {
|
||||
pub fn as_ptr<T>(&self) -> *const T {
|
||||
match *self {
|
||||
Self::Owned(ref dma) => dma.as_ptr().cast(),
|
||||
Self::Borrowed(Borrowed { phys, virt, size, _unused }) => virt as *const T,
|
||||
}
|
||||
}
|
||||
pub fn as_mut_ptr<T>(&mut self) -> *mut T {
|
||||
match *self {
|
||||
Self::Owned(ref mut dma) => dma.as_mut_ptr().cast(),
|
||||
Self::Borrowed(Borrowed { phys, virt, size, _unused }) => virt as *mut T,
|
||||
}
|
||||
}
|
||||
pub fn physical(&self) -> usize {
|
||||
match self {
|
||||
Self::Owned(dma) => dma.physical(),
|
||||
Self::Borrowed(borrowed) => borrowed.phys,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Available<'a> {
|
||||
pub fn ring(&self) -> &AvailableRing {
|
||||
unsafe { &*self.mem.as_ptr() }
|
||||
}
|
||||
pub fn ring_mut(&mut self) -> &mut AvailableRing {
|
||||
unsafe { &mut *self.mem.as_mut_ptr() }
|
||||
}
|
||||
pub fn new(queue_size: usize) -> Result<Self, Error> {
|
||||
let (_, _, size) = queue_part_sizes(queue_size);
|
||||
let addr = unsafe { syscall::physalloc(size) }.map_err(Error::SyscallError)?;
|
||||
let mem = unsafe { Dma::zeroed_slice(size).map_err(Error::SyscallError)?.assume_init() };
|
||||
|
||||
unsafe { Self::from_raw(addr, size, queue_size) }
|
||||
unsafe { Self::from_raw(Mem::Owned(mem), queue_size) }
|
||||
}
|
||||
|
||||
/// `addr` is the physical address of the ring.
|
||||
pub unsafe fn from_raw(addr: usize, size: usize, queue_size: usize) -> Result<Self, Error> {
|
||||
let virt = unsafe {
|
||||
common::physmap(addr, size, common::Prot::RW, common::MemoryType::default())
|
||||
}?;
|
||||
|
||||
let ring = unsafe { &mut *(virt as *mut AvailableRing) };
|
||||
pub unsafe fn from_raw(mem: Mem<'a>, queue_size: usize) -> Result<Self, Error> {
|
||||
let ring = Self {
|
||||
addr,
|
||||
size,
|
||||
ring,
|
||||
mem,
|
||||
queue_size,
|
||||
};
|
||||
|
||||
@@ -310,7 +345,7 @@ impl<'a> Available<'a> {
|
||||
// SAFETY: We have exclusive access to the elements and the number of elements
|
||||
// is correct; same as the queue size.
|
||||
unsafe {
|
||||
self.ring
|
||||
self.ring()
|
||||
.elements
|
||||
.as_slice(self.queue_size)
|
||||
.get(index % self.queue_size)
|
||||
@@ -319,58 +354,51 @@ impl<'a> Available<'a> {
|
||||
}
|
||||
|
||||
pub fn head_index(&self) -> u16 {
|
||||
self.ring.head_index.load(Ordering::SeqCst)
|
||||
self.ring().head_index.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
pub fn set_head_idx(&self, index: u16) {
|
||||
self.ring.head_index.store(index, Ordering::SeqCst);
|
||||
self.ring().head_index.store(index, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn phys_addr(&self) -> usize {
|
||||
self.addr
|
||||
self.mem.physical()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Available<'_> {
|
||||
impl<'a> Drop for Available<'a> {
|
||||
fn drop(&mut self) {
|
||||
log::warn!("virtio-core: dropping 'available' ring at {:#x}", self.addr);
|
||||
|
||||
unsafe {
|
||||
syscall::funmap(self.addr, self.size).unwrap();
|
||||
syscall::physfree(self.addr, self.size).unwrap();
|
||||
}
|
||||
log::warn!("virtio-core: dropping 'available' ring at {:#x}", self.phys_addr());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Used<'a> {
|
||||
addr: usize,
|
||||
size: usize,
|
||||
|
||||
mem: Mem<'a>,
|
||||
queue_size: usize,
|
||||
|
||||
ring: &'a mut UsedRing,
|
||||
_unused: &'a (),
|
||||
}
|
||||
|
||||
impl<'a> Used<'a> {
|
||||
fn ring(&self) -> &UsedRing {
|
||||
unsafe { &*self.mem.as_ptr() }
|
||||
}
|
||||
fn ring_mut(&mut self) -> &mut UsedRing {
|
||||
unsafe { &mut *self.mem.as_mut_ptr() }
|
||||
}
|
||||
|
||||
pub fn new(queue_size: usize) -> Result<Self, Error> {
|
||||
let (_, _, size) = queue_part_sizes(queue_size);
|
||||
let addr = unsafe { syscall::physalloc(size) }.map_err(Error::SyscallError)?;
|
||||
let mem = unsafe { Dma::zeroed_slice(size).map_err(Error::SyscallError)?.assume_init() };
|
||||
|
||||
unsafe { Self::from_raw(addr, size, queue_size) }
|
||||
unsafe { Self::from_raw(Mem::Owned(mem), queue_size) }
|
||||
}
|
||||
|
||||
/// `addr` is the physical address of the ring.
|
||||
pub unsafe fn from_raw(addr: usize, size: usize, queue_size: usize) -> Result<Self, Error> {
|
||||
let virt = unsafe {
|
||||
common::physmap(addr, size, common::Prot::RW, common::MemoryType::default())
|
||||
}?;
|
||||
|
||||
let ring = unsafe { &mut *(virt as *mut UsedRing) };
|
||||
pub unsafe fn from_raw(mem: Mem<'a>, queue_size: usize) -> Result<Self, Error> {
|
||||
let mut ring = Self {
|
||||
addr,
|
||||
size,
|
||||
ring,
|
||||
mem,
|
||||
queue_size,
|
||||
_unused: &(),
|
||||
};
|
||||
|
||||
for i in 0..queue_size {
|
||||
@@ -388,7 +416,7 @@ impl<'a> Used<'a> {
|
||||
// SAFETY: We have exclusive access to the elements and the number of elements
|
||||
// is correct; same as the queue size.
|
||||
unsafe {
|
||||
self.ring
|
||||
self.ring()
|
||||
.elements
|
||||
.as_slice(self.queue_size)
|
||||
.get(index % self.queue_size)
|
||||
@@ -401,36 +429,32 @@ impl<'a> Used<'a> {
|
||||
pub fn get_mut_element_at(&mut self, index: usize) -> &mut UsedRingElement {
|
||||
// SAFETY: We have exclusive access to the elements and the number of elements
|
||||
// is correct; same as the queue size.
|
||||
let queue_size = self.queue_size;
|
||||
unsafe {
|
||||
self.ring
|
||||
self.ring_mut()
|
||||
.elements
|
||||
.as_mut_slice(self.queue_size)
|
||||
.as_mut_slice(queue_size)
|
||||
.get_mut(index % 256)
|
||||
.expect("virtio-core::used: index out of bounds")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> u16 {
|
||||
self.ring.flags.get()
|
||||
self.ring().flags.get()
|
||||
}
|
||||
|
||||
pub fn head_index(&self) -> u16 {
|
||||
self.ring.head_index.get()
|
||||
self.ring().head_index.get()
|
||||
}
|
||||
|
||||
pub fn phys_addr(&self) -> usize {
|
||||
self.addr
|
||||
self.mem.physical()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Used<'_> {
|
||||
fn drop(&mut self) {
|
||||
log::warn!("virtio-core: dropping 'used' ring at {:#x}", self.addr);
|
||||
|
||||
unsafe {
|
||||
syscall::funmap(self.addr, self.size).unwrap();
|
||||
syscall::physfree(self.addr, self.size).unwrap();
|
||||
}
|
||||
log::warn!("virtio-core: dropping 'used' ring at {:#x}", self.phys_addr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,21 +130,18 @@ impl<'a> Display<'a> {
|
||||
let bpp = 32;
|
||||
let fb_size = (self.width as usize * self.height as usize * bpp / 8)
|
||||
.next_multiple_of(syscall::PAGE_SIZE);
|
||||
let address = unsafe { syscall::physalloc(fb_size) }?;
|
||||
let mapped = unsafe {
|
||||
common::physmap(
|
||||
address as usize,
|
||||
fb_size,
|
||||
common::Prot::RW,
|
||||
common::MemoryType::default(),
|
||||
)
|
||||
}? as usize;
|
||||
let mut mapped = unsafe { Dma::zeroed_slice(fb_size)?.assume_init() };
|
||||
|
||||
unsafe {
|
||||
core::ptr::write_bytes(mapped as *mut u8, 255, fb_size);
|
||||
core::ptr::write_bytes(mapped.as_mut_ptr() as *mut u8, 255, fb_size);
|
||||
}
|
||||
|
||||
self.map_screen_with(offset, address, fb_size, mapped).await
|
||||
let virt = mapped.as_mut_ptr() as usize;
|
||||
let phys = mapped.physical();
|
||||
core::mem::forget(mapped);
|
||||
// TODO: Keep Dma
|
||||
|
||||
self.map_screen_with(offset, phys, fb_size, virt).await
|
||||
}
|
||||
|
||||
async fn map_screen_with(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use log::debug;
|
||||
use syscall::PAGE_SIZE;
|
||||
use syscall::error::Result;
|
||||
use syscall::io::{Io, Mmio};
|
||||
|
||||
@@ -178,18 +179,18 @@ impl ScratchpadBufferEntry {
|
||||
|
||||
pub struct ScratchpadBufferArray {
|
||||
pub entries: Dma<[ScratchpadBufferEntry]>,
|
||||
pub pages: Vec<usize>,
|
||||
pub pages: Vec<Dma<[u8; PAGE_SIZE]>>,
|
||||
}
|
||||
impl ScratchpadBufferArray {
|
||||
pub fn new(ac64: bool, page_size: usize, entries: u16) -> Result<Self> {
|
||||
pub fn new(ac64: bool, entries: u16) -> Result<Self> {
|
||||
let mut entries = unsafe { Xhci::alloc_dma_zeroed_unsized_raw(ac64, entries as usize)? };
|
||||
|
||||
let pages = entries.iter_mut().map(|entry: &mut ScratchpadBufferEntry| -> Result<usize> {
|
||||
let pointer = unsafe { syscall::physalloc(page_size)? };
|
||||
assert_eq!((pointer as u64) & 0xFFFF_FFFF_FFFF_F000, pointer as u64, "physically allocated pointer (physalloc) wasn't 4k page-aligned");
|
||||
entry.set_addr(pointer as u64);
|
||||
Ok(pointer)
|
||||
}).collect::<Result<Vec<usize>, _>>()?;
|
||||
let pages = entries.iter_mut().map(|entry: &mut ScratchpadBufferEntry| {
|
||||
let dma = unsafe { Dma::<[u8; PAGE_SIZE]>::zeroed()?.assume_init() };
|
||||
assert_eq!(dma.physical() % PAGE_SIZE, 0);
|
||||
entry.set_addr(dma.physical() as u64);
|
||||
Ok(dma)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(Self {
|
||||
entries,
|
||||
|
||||
@@ -9,6 +9,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
|
||||
use std::{mem, process, slice, sync::atomic, task, thread};
|
||||
|
||||
use syscall::PAGE_SIZE;
|
||||
use syscall::error::{Error, Result, EBADF, EBADMSG, ENOENT, EIO};
|
||||
use syscall::flag::{O_RDONLY, PhysallocFlags};
|
||||
use syscall::io::Io;
|
||||
@@ -176,7 +177,7 @@ impl Xhci {
|
||||
pub struct Xhci {
|
||||
// immutable
|
||||
cap: &'static CapabilityRegs,
|
||||
page_size: usize,
|
||||
//page_size: usize,
|
||||
|
||||
// XXX: It would be really useful to be able to mutably access individual elements of a slice,
|
||||
// without having to wrap every element in a lock (which wouldn't work since they're packed).
|
||||
@@ -248,12 +249,12 @@ impl Xhci {
|
||||
let cap = unsafe { &mut *(address as *mut CapabilityRegs) };
|
||||
debug!("CAP REGS BASE {:X}", address);
|
||||
|
||||
let page_size = {
|
||||
/*let page_size = {
|
||||
let memory_fd = syscall::open("memory:", O_RDONLY)?;
|
||||
let mut stat = syscall::data::StatVfs::default();
|
||||
syscall::fstatvfs(memory_fd, &mut stat)?;
|
||||
stat.f_bsize as usize
|
||||
};
|
||||
};*/
|
||||
|
||||
let op_base = address + cap.len.read() as usize;
|
||||
let op = unsafe { &mut *(op_base as *mut OperationalRegs) };
|
||||
@@ -306,7 +307,7 @@ impl Xhci {
|
||||
|
||||
// Create the command ring with 4096 / 16 (TRB size) entries, so that it uses all of the
|
||||
// DMA allocation (which is at least a 4k page).
|
||||
let entries_per_page = page_size / mem::size_of::<Trb>();
|
||||
let entries_per_page = PAGE_SIZE / mem::size_of::<Trb>();
|
||||
let cmd = Ring::new(cap.ac64(), entries_per_page, true)?;
|
||||
|
||||
let (irq_reactor_sender, irq_reactor_receiver) = crossbeam_channel::unbounded();
|
||||
@@ -315,7 +316,7 @@ impl Xhci {
|
||||
base: address as *const u8,
|
||||
|
||||
cap,
|
||||
page_size,
|
||||
//page_size,
|
||||
|
||||
op: Mutex::new(op),
|
||||
ports: Mutex::new(ports),
|
||||
@@ -459,7 +460,7 @@ impl Xhci {
|
||||
if buf_count == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let scratchpad_buf_arr = ScratchpadBufferArray::new(self.cap.ac64(), self.page_size,buf_count)?;
|
||||
let scratchpad_buf_arr = ScratchpadBufferArray::new(self.cap.ac64(), buf_count)?;
|
||||
self.dev_ctx.dcbaa[0] = scratchpad_buf_arr.register() as u64;
|
||||
debug!("Setting up {} scratchpads, at {:#0x}", buf_count, scratchpad_buf_arr.register());
|
||||
self.scratchpad_buf_arr = Some(scratchpad_buf_arr);
|
||||
|
||||
Reference in New Issue
Block a user