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}