use alloc::{borrow::Cow, sync::Arc};
use ax_memory_addr::PhysAddrRange;
use axpoll::{IoEvents, Pollable};
use sg2002_tpu::ion::IonBuffer;
use super::{FileLike, Kstat};
use crate::{
StarryError, StarryResult,
pseudofs::{DeviceMmap, dev::ION_DEVICE},
};
pub struct IonBufferFile {
buffer: Arc<IonBuffer>,
}
impl IonBufferFile {
pub fn new(buffer: Arc<IonBuffer>) -> Self {
Self { buffer }
}
pub fn phys_range(&self) -> PhysAddrRange {
PhysAddrRange::from_start_size(
ax_memory_addr::PhysAddr::from(self.buffer.dma_addr().as_u64() as usize),
self.buffer.size,
)
}
pub fn buffer(&self) -> &Arc<IonBuffer> {
&self.buffer
}
}
impl Pollable for IonBufferFile {
fn poll(&self) -> IoEvents {
IoEvents::IN | IoEvents::OUT
}
unsafe fn register_shared(
&self,
_sink: &mut dyn axpoll::SharedRegistrationSink,
_events: IoEvents,
) {
}
}
impl FileLike for IonBufferFile {
fn read(&self, _dst: &mut super::IoDst) -> StarryResult<usize> {
Err(StarryError::InvalidInput)
}
fn write(&self, _src: &mut super::IoSrc) -> StarryResult<usize> {
Err(StarryError::InvalidInput)
}
fn stat(&self) -> StarryResult<Kstat> {
Ok(Kstat {
size: self.buffer.size as u64,
..Default::default()
})
}
fn path(&self) -> Cow<'_, str> {
Cow::Borrowed("/dev/ion_buffer")
}
fn device_mmap(&self, _offset: u64, _length: u64) -> StarryResult<DeviceMmap> {
Ok(DeviceMmap::Physical(self.phys_range(), None))
}
}
impl Drop for IonBufferFile {
fn drop(&mut self) {
let handle = self.buffer.handle.as_u32();
debug!("Dropping IonBufferFile, releasing handle: {}", handle);
if let Some(dev) = ION_DEVICE.get() {
dev.release_handle(handle);
} else {
error!(
"Failed to find ion device to free buffer handle: {}",
handle
);
}
}
}