twizzler_net/
drivers.rs

1use std::collections::HashMap;
2
3use secgate::TwzError;
4use twizzler_abi::syscall::ThreadSync;
5use twizzler_driver::{
6    device::Device,
7    dma::{DMA_PAGE_SIZE, DmaObject, DmaOptions, DmaSliceRegion, PhysAddr},
8};
9use twizzler_io::packet::PacketObject;
10
11use crate::PacketNum;
12
13mod e1000;
14
15pub type QueueHandle = u32;
16
17#[derive(Default)]
18pub struct Features {}
19
20pub trait NetDriver {
21    fn features(&self) -> Features {
22        Features::default()
23    }
24
25    fn device(&self) -> &Device;
26    fn device_mut(&mut self) -> &mut Device;
27
28    fn setup_rx_queue(&mut self, len: usize) -> Result<QueueHandle, TwzError>;
29    fn destroy_rx_queue(&mut self, queue: QueueHandle) -> Result<(), TwzError>;
30
31    fn setup_tx_queue(&mut self, len: usize) -> Result<QueueHandle, TwzError>;
32    fn destroy_tx_queue(&mut self, queue: QueueHandle) -> Result<(), TwzError>;
33
34    fn tx_queues(&self) -> Vec<QueueHandle>;
35    fn rx_queues(&self) -> Vec<QueueHandle>;
36
37    fn rx_packet_buffer(&self, queue: QueueHandle) -> &DmaPacketObject;
38    fn tx_packet_buffer(&self, queue: QueueHandle) -> &DmaPacketObject;
39
40    fn mac_address(&self, queue: QueueHandle) -> Result<[u8; 6], TwzError>;
41
42    fn set_mac_address(&self, _queue: QueueHandle, _addr: [u8; 6]) -> Result<(), TwzError> {
43        Err(TwzError::NOT_SUPPORTED)
44    }
45
46    fn recv_packets(
47        &mut self,
48        queue: QueueHandle,
49        packets: &mut [Packet],
50    ) -> Result<usize, TwzError>;
51
52    fn send_packets(
53        &mut self,
54        queue: QueueHandle,
55        packets: &mut [Packet],
56    ) -> Result<usize, TwzError>;
57
58    fn has_work(&self, queue: QueueHandle) -> WorkItems;
59    fn waitpoint(&self, queue: QueueHandle) -> ThreadSync;
60}
61
62#[derive(Default, Clone)]
63pub struct Packet {
64    po: Option<PacketObject>,
65    pn: PacketNum,
66    phys_addr: PhysAddr,
67    len: u32,
68}
69
70bitflags::bitflags! {
71    pub struct WorkItems : u32 {
72        const RX_READY = 0x1;
73        const TX_SENT = 0x2;
74        const STATUS_CHANGE = 0x4;
75        const TX_ERROR = 0x8;
76        const RX_ERROR = 0x10;
77    }
78}
79
80pub struct DmaPacketObject {
81    po: PacketObject,
82    dma: DmaObject,
83    regions: HashMap<u32, DmaSliceRegion<u8>>,
84    rev_addr_map: HashMap<PhysAddr, u32>,
85}
86
87impl From<PacketObject> for DmaPacketObject {
88    fn from(value: PacketObject) -> Self {
89        Self {
90            dma: DmaObject::new(value.object().clone()),
91            po: value,
92            regions: HashMap::new(),
93            rev_addr_map: HashMap::new(),
94        }
95    }
96}
97
98impl DmaPacketObject {
99    pub fn packet_object(&self) -> &PacketObject {
100        &self.po
101    }
102
103    pub fn dma(&self) -> &DmaObject {
104        &self.dma
105    }
106
107    pub fn allocate_packet(&mut self) -> Option<(u32, PhysAddr)> {
108        let num = self.packet_object().allocate_packet()?;
109        Some((num, self.phys_addr(num)?))
110    }
111
112    pub fn phys_addr(&mut self, packet: u32) -> Option<PhysAddr> {
113        let size = self
114            .packet_object()
115            .packet_size()
116            .next_multiple_of(DMA_PAGE_SIZE);
117        let entry = self.regions.entry(packet).or_insert_with(|| {
118            let offset = self.po.packet_offset(packet);
119            self.dma.slice_region::<u8>(
120                offset,
121                size,
122                twizzler_driver::dma::Access::BiDirectional,
123                DmaOptions::empty(),
124            )
125        });
126        let pin = entry.pin().ok()?;
127        if !self.rev_addr_map.contains_key(&pin.backing[0].addr()) {
128            self.rev_addr_map.insert(pin.backing[0].addr(), packet);
129        }
130        Some(pin.backing[0].addr())
131    }
132
133    pub fn packet_num(&self, addr: PhysAddr) -> Option<u32> {
134        self.rev_addr_map.get(&addr).copied()
135    }
136
137    pub fn release_packet(&self, packet: u32) {
138        self.packet_object().release_packet(packet);
139    }
140}