forked from asterinas/asterinas
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtempFileWeek11
More file actions
150 lines (140 loc) · 4.51 KB
/
tempFileWeek11
File metadata and controls
150 lines (140 loc) · 4.51 KB
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#![no_std]
#![deny(unsafe_code)]
#![feature(strict_provenance)]
extern crate alloc;
use alloc::boxed::Box;
use alloc::sync::Arc;
use aster_virtio::device::socket::buffer;
use ostd::mm::VmReader;
use ostd::prelude::println;
use ostd::bus::pci::common_device::PciCommonDevice;
use ostd::sync::Mutex;
use ostd::bus::BusProbeError;
use ostd::bus::pci::PCI_BUS;
use ostd::bus::pci::bus::PciDevice;
use ostd::bus::pci::bus::PciDriver;
use ostd::bus::pci::cfg_space::Bar;
use alloc::{vec, vec::Vec};
use component::{init_component, ComponentInitError};
use ostd::bus::pci::PciDeviceId;
use aster_network::{DmaSegment, RxBuffer, TxBuffer,AnyNetworkDevice,VirtioNetError,EthernetAddr};
use aster_bigtcp::device::DeviceCapabilities;
use core::fmt::Debug;
use alloc::fmt;
use aster_network::dma_pool;
/*
#[init_component]
fn e1000_init() -> Result<(), ComponentInitError> {
driver_e1000_init();
Ok(())
}
*/
/// The dma descriptor for transmitting
#[derive(Debug, Clone)]
#[repr(C, align(16))]
pub struct TD {
addr: u64,
length: u16,
cso: u8,
cmd: u8,
status: u8,
css: u8,
special: u16,
}
/// [E1000 3.2.3]
/// The dma descriptor for receiving
#[derive(Debug, Clone)]
#[repr(C, align(16))]
pub struct RD {
addr: u64, /* Address of the descriptor's data buffer */
length: u16, /* Length of data DMAed into data buffer */
csum: u16, /* Packet checksum */
status: u8, /* Descriptor status */
errors: u8, /* Descriptor Errors */
special: u16,
}
pub struct PciDeviceE1000 {
common_device: PciCommonDevice,
base: usize,
mac_address: EthernetAddr,
header: VirtioNetHdr,
receive_buffers: Vec<Arc<RxBuffer>>,
receive_ring: Vec<Arc<RD>>,
receive_index: usize,
transmit_buffers: Vec<Arc<TxBuffer>>,
transmit_ring: Vec<Arc<TD>>,
//transmit_ring_free: usize,
transmit_index: usize,
transmit_clean_index: usize,
dma_pool_device: Arc<dma_pool::DmaPool>
}
impl PciDeviceE1000{
pub fn new(common_device: PciCommonDevice,mac_address:EthernetAddr) -> self{
let dma_pool_new = dma_pool::DmaPool::new(
mm::PAGE_SIZE,
10,
50,
DmaDirection::Bidirectional,
false,
);
Self{
common_device,
base: 0,
mac_address,
header: VirtioNetHdr::default(),
receive_ring: Vec::with_capacity(64),
receive_buffers: Vec::with_capacity(64),
receive_index: 0,
transmit_ring: Vec::with_capacity(64),
transmit_buffers: Vec::with_capacity(64),
transmit_index: 0,
transmit_clean_index: 0,
dma_pool_device: dma_pool_new,
}
}
pub fn send_packet(&mut self, packet: &[u8]) -> Result<(), VirtioNetError>{
if self.transmit_index >= self.transmit_buffers.len() {
return Err(VirtioNetError::Busy);
}
let segment = self.dma_pool_device.alloc_segment().unwrap();
let mut writer = segment.writer().unwrap();
let buffer = TxBuffer::new(
self.header,
packet,
&TX_BUFFER_POOL
);
// Ensure the TxBuffer can be transformed to bytes stream
writer.write(&mut VmReader::from(TxBuffer));
let buffer_arc = Arc::new(buffer);
writer.write(&mut VmReader::from(buffer_arc));
self.transmit_buffers[self.transmit_index] = buffer_arc;
let td = TD{
addr: std::ptr::addr_of!(buffer), // 填入适当的值
length: packet.len(),
cso: 0,
cmd: 0,
status: 0,
css: 0,
special: 0,
};
writer.write(&mut VmReader::from(td));
let td_arc = Arc::new(td);
writer.write(&mut VmReader::from(td_arc));
self.transmit_ring[self.transmit_index] = td_arc;
self.transmit_index += 1;
OK()
//TODO: Implement notify the device when the data is ready.
}
pub fn receive_packet(&mut self) -> Result<Vec<u8>, VirtioNetError>{
let buffter = self.receive_buffers[self.receive_index].as_ref();
let rd = self.receive_ring[self.receive_index].as_ref();
let mut reader = (&buffer.segment).reader().unwrap();
let packet = [0u8; rd.length];
reader.read(&mut VmWriter::from(&mut packet as &mut [u8]));
self.receive_index = (self.receive_index + 1) % 64;
Ok(packet)
//TODO: Implement notify the receive end when the data arrive.
}
}
static TX_BUFFER_POOL: SpinLock<LinkedList<DmaStream>, LocalIrqDisabled> =
SpinLock::new(LinkedList::new());