1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use core::any::Any;

use crate::drivers::virtio::VirtioHal;
use crate::sync::UPIntrFreeCell;
use alloc::sync::Arc;
use lazy_static::*;
use virtio_drivers::{VirtIOHeader, VirtIONet};

const VIRTIO8: usize = 0x10004000;

lazy_static! {
    pub static ref NET_DEVICE: Arc<dyn NetDevice> = Arc::new(VirtIONetWrapper::new());
}

pub trait NetDevice: Send + Sync + Any {
    fn transmit(&self, data: &[u8]);
    fn receive(&self, data: &mut [u8]) -> usize;
}

pub struct VirtIONetWrapper(UPIntrFreeCell<VirtIONet<'static, VirtioHal>>);

impl NetDevice for VirtIONetWrapper {
    fn transmit(&self, data: &[u8]) {
        self.0
            .exclusive_access()
            .send(data)
            .expect("can't send data")
    }

    fn receive(&self, data: &mut [u8]) -> usize {
        self.0
            .exclusive_access()
            .recv(data)
            .expect("can't receive data")
    }
}

impl VirtIONetWrapper {
    pub fn new() -> Self {
        unsafe {
            let virtio = VirtIONet::<VirtioHal>::new(&mut *(VIRTIO8 as *mut VirtIOHeader))
                .expect("can't create net device by virtio");
            VirtIONetWrapper(UPIntrFreeCell::new(virtio))
        }
    }
}