1use core::any::Any;
2
3use crate::drivers::virtio::VirtioHal;
4use crate::sync::UPIntrFreeCell;
5use alloc::sync::Arc;
6use lazy_static::*;
7use virtio_drivers::{VirtIOHeader, VirtIONet};
8
9const VIRTIO8: usize = 0x10004000;
10
11lazy_static! {
12 pub static ref NET_DEVICE: Arc<dyn NetDevice> = Arc::new(VirtIONetWrapper::new());
13}
14
15pub trait NetDevice: Send + Sync + Any {
16 fn transmit(&self, data: &[u8]);
17 fn receive(&self, data: &mut [u8]) -> usize;
18}
19
20pub struct VirtIONetWrapper(UPIntrFreeCell<VirtIONet<'static, VirtioHal>>);
21
22impl NetDevice for VirtIONetWrapper {
23 fn transmit(&self, data: &[u8]) {
24 self.0
25 .exclusive_access()
26 .send(data)
27 .expect("can't send data")
28 }
29
30 fn receive(&self, data: &mut [u8]) -> usize {
31 self.0
32 .exclusive_access()
33 .recv(data)
34 .expect("can't receive data")
35 }
36}
37
38impl VirtIONetWrapper {
39 pub fn new() -> Self {
40 unsafe {
41 let virtio = VirtIONet::<VirtioHal>::new(&mut *(VIRTIO8 as *mut VirtIOHeader))
42 .expect("can't create net device by virtio");
43 VirtIONetWrapper(UPIntrFreeCell::new(virtio))
44 }
45 }
46}