use alloc::{borrow::Cow, sync::Arc};
use ax_errno::{AxError, AxResult};
use ax_memory_addr::PhysAddrRange;
use axpoll::{IoEvents, Pollable};
use sg2002_tpu::ion::IonBuffer;
use super::{FileLike, Kstat};
use crate::pseudofs::{
DeviceMmap, DeviceOps,
dev::{
ION_DEVICE,
ion::{ION_IOC_FREE, IonHandleData},
},
};
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_info.bus_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
}
fn register(&self, _context: &mut core::task::Context<'_>, _events: IoEvents) {
}
}
impl FileLike for IonBufferFile {
fn read(&self, _dst: &mut super::IoDst) -> AxResult<usize> {
Err(AxError::InvalidInput)
}
fn write(&self, _src: &mut super::IoSrc) -> AxResult<usize> {
Err(AxError::InvalidInput)
}
fn stat(&self) -> AxResult<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) -> AxResult<DeviceMmap> {
Ok(DeviceMmap::Physical(self.phys_range()))
}
}
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() {
let handle_data = IonHandleData { handle };
let _ = dev.ioctl(ION_IOC_FREE, &handle_data as *const _ as usize);
} else {
error!(
"Failed to find ion device to free buffer handle: {}",
handle
);
}
}
}