mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
818 lines
29 KiB
Rust
818 lines
29 KiB
Rust
// 参考手册: PCIe* GbE Controllers Open Source Software Developer’s Manual
|
||
// Refernce: PCIe* GbE Controllers Open Source Software Developer’s Manual
|
||
|
||
use alloc::string::ToString;
|
||
use alloc::sync::Arc;
|
||
use alloc::vec::Vec;
|
||
use core::intrinsics::unlikely;
|
||
use core::mem::size_of;
|
||
use core::ptr::NonNull;
|
||
use core::slice::{from_raw_parts, from_raw_parts_mut};
|
||
use core::sync::atomic::{compiler_fence, Ordering};
|
||
use log::{debug, info};
|
||
|
||
use super::e1000e_driver::e1000e_driver_init;
|
||
use crate::driver::base::device::DeviceId;
|
||
use crate::driver::net::dma::{dma_alloc, dma_dealloc};
|
||
use crate::driver::net::irq_handle::DefaultNetIrqHandler;
|
||
use crate::driver::pci::pci::{
|
||
get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError,
|
||
PCI_DEVICE_LINKEDLIST,
|
||
};
|
||
use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ};
|
||
use crate::exception::IrqNumber;
|
||
|
||
use crate::libs::volatile::{ReadOnly, Volatile, WriteOnly};
|
||
|
||
const PAGE_SIZE: usize = 4096;
|
||
const NETWORK_CLASS: u8 = 0x2;
|
||
const ETHERNET_SUBCLASS: u8 = 0x0;
|
||
// e1000e系列网卡的device id列表,来源:https://admin.pci-ids.ucw.cz/read/PC/8086
|
||
const E1000E_DEVICE_ID: [u16; 14] = [
|
||
0x10d3, // 8574L, qemu default
|
||
0x10cc, // 82567LM-2
|
||
0x10cd, // 82567LF-2
|
||
0x105f, // 82571EB
|
||
0x1060, // 82571EB
|
||
0x107f, // 82572EI
|
||
0x109a, // 82573L
|
||
0x10ea, // 82577LM
|
||
0x10eb, // 82577LC
|
||
0x10ef, // 82578DM
|
||
0x10f0, // 82578DC
|
||
0x1502, // 82579LM
|
||
0x1503, // 82579V
|
||
0x150c, // 82583V
|
||
];
|
||
|
||
// e1000e网卡与BAR有关的常量
|
||
// BAR0空间大小(128KB)
|
||
const E1000E_BAR_REG_SIZE: u32 = 128 * 1024;
|
||
// BAR0空间对齐(64bit)
|
||
#[allow(dead_code)]
|
||
const E1000E_BAR_REG_ALIGN: u8 = 64;
|
||
// 单个寄存器大小(32bit, 4字节)
|
||
#[allow(dead_code)]
|
||
const E1000E_REG_SIZE: u8 = 4;
|
||
|
||
// TxBuffer和RxBuffer的大小(DMA页)
|
||
const E1000E_DMA_PAGES: usize = 1;
|
||
|
||
// 中断相关
|
||
const E1000E_RECV_VECTOR: IrqNumber = IrqNumber::new(57);
|
||
|
||
// napi队列中暂时存储的buffer个数
|
||
const E1000E_RECV_NAPI: usize = 1024;
|
||
|
||
// 收/发包的描述符结构 pp.24 Table 3-1
|
||
#[repr(C)]
|
||
#[derive(Copy, Clone, Debug)]
|
||
struct E1000ETransDesc {
|
||
addr: u64,
|
||
len: u16,
|
||
cso: u8,
|
||
cmd: u8,
|
||
status: u8,
|
||
css: u8,
|
||
special: u8,
|
||
}
|
||
// pp.54 Table 3-12
|
||
#[repr(C)]
|
||
#[derive(Copy, Clone, Debug)]
|
||
struct E1000ERecvDesc {
|
||
addr: u64,
|
||
len: u16,
|
||
chksum: u16,
|
||
status: u16,
|
||
error: u8,
|
||
special: u8,
|
||
}
|
||
#[derive(Copy, Clone)]
|
||
// Buffer的Copy只是指针操作,不涉及实际数据的复制,因此要小心使用,确保不同的buffer不会使用同一块内存
|
||
pub struct E1000EBuffer {
|
||
buffer: NonNull<u8>,
|
||
paddr: usize,
|
||
// length字段为0则表示这个buffer是一个占位符,不指向实际内存
|
||
// the buffer is empty and no page is allocated if length field is set 0
|
||
length: usize,
|
||
}
|
||
|
||
impl E1000EBuffer {
|
||
pub fn new(length: usize) -> Self {
|
||
assert!(length <= PAGE_SIZE);
|
||
if unlikely(length == 0) {
|
||
// 在某些情况下,我们并不需要实际分配buffer,只需要提供一个占位符即可
|
||
// we dont need to allocate dma pages for buffer in some cases
|
||
E1000EBuffer {
|
||
buffer: NonNull::dangling(),
|
||
paddr: 0,
|
||
length: 0,
|
||
}
|
||
} else {
|
||
let (paddr, vaddr) = dma_alloc(E1000E_DMA_PAGES);
|
||
E1000EBuffer {
|
||
buffer: vaddr,
|
||
paddr,
|
||
length,
|
||
}
|
||
}
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub fn as_addr(&self) -> NonNull<u8> {
|
||
assert!(self.length != 0);
|
||
return self.buffer;
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub fn as_addr_u64(&self) -> u64 {
|
||
assert!(self.length != 0);
|
||
return self.buffer.as_ptr() as u64;
|
||
}
|
||
|
||
pub fn as_paddr(&self) -> usize {
|
||
assert!(self.length != 0);
|
||
return self.paddr;
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub fn as_slice(&self) -> &[u8] {
|
||
assert!(self.length != 0);
|
||
return unsafe { from_raw_parts(self.buffer.as_ptr(), self.length) };
|
||
}
|
||
|
||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||
assert!(self.length != 0);
|
||
return unsafe { from_raw_parts_mut(self.buffer.as_ptr(), self.length) };
|
||
}
|
||
|
||
pub fn set_length(&mut self, length: usize) {
|
||
self.length = length;
|
||
}
|
||
|
||
pub fn len(&self) -> usize {
|
||
return self.length;
|
||
}
|
||
// 释放buffer内部的dma_pages,需要小心使用
|
||
pub fn free_buffer(self) {
|
||
if self.length != 0 {
|
||
unsafe { dma_dealloc(self.paddr, self.buffer, E1000E_DMA_PAGES) };
|
||
}
|
||
}
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub struct E1000EDevice {
|
||
// 设备寄存器
|
||
// device registers
|
||
general_regs: NonNull<GeneralRegs>,
|
||
interrupt_regs: NonNull<InterruptRegs>,
|
||
rctl_regs: NonNull<ReceiveCtrlRegs>,
|
||
receive_regs: NonNull<ReceiveRegs>,
|
||
tctl_regs: NonNull<TransmitCtrlRegs>,
|
||
transimit_regs: NonNull<TransimitRegs>,
|
||
pcie_regs: NonNull<PCIeRegs>,
|
||
|
||
// descriptor环形队列,在操作系统与设备之间共享
|
||
// descriptor rings are shared between os and device
|
||
recv_desc_ring: &'static mut [E1000ERecvDesc],
|
||
trans_desc_ring: &'static mut [E1000ETransDesc],
|
||
recv_ring_pa: usize,
|
||
trans_ring_pa: usize,
|
||
|
||
// 设备收/发包缓冲区数组
|
||
// buffers of receive/transmit packets
|
||
recv_buffers: Vec<E1000EBuffer>,
|
||
trans_buffers: Vec<E1000EBuffer>,
|
||
mac: [u8; 6],
|
||
first_trans: bool,
|
||
// napi队列,用于存放在中断关闭期间通过轮询收取的buffer
|
||
// the napi queue is designed to save buffer/packet when the interrupt is close
|
||
// NOTE: this feature is not completely implemented and not used in the current version
|
||
napi_buffers: Vec<E1000EBuffer>,
|
||
napi_buffer_head: usize,
|
||
napi_buffer_tail: usize,
|
||
napi_buffer_empty: bool,
|
||
}
|
||
|
||
impl E1000EDevice {
|
||
// 从PCI标准设备进行驱动初始化
|
||
// init the device for PCI standard device struct
|
||
#[allow(unused_assignments)]
|
||
pub fn new(
|
||
device: &mut PciDeviceStructureGeneralDevice,
|
||
device_id: Arc<DeviceId>,
|
||
) -> Result<Self, E1000EPciError> {
|
||
// 从BAR0获取我们需要的寄存器
|
||
// Build registers sturcts from BAR0
|
||
device.bar_ioremap().unwrap()?;
|
||
device.enable_master();
|
||
let bar = device.bar().ok_or(E1000EPciError::BarGetFailed)?;
|
||
let bar0 = bar.get_bar(0)?;
|
||
let (address, size) = bar0
|
||
.memory_address_size()
|
||
.ok_or(E1000EPciError::UnexpectedBarType)?;
|
||
if address == 0 {
|
||
return Err(E1000EPciError::BarNotAllocated);
|
||
}
|
||
if size != E1000E_BAR_REG_SIZE {
|
||
return Err(E1000EPciError::UnexpectedBarSize);
|
||
}
|
||
let vaddress = bar0
|
||
.virtual_address()
|
||
.ok_or(E1000EPciError::BarGetVaddrFailed)?
|
||
.data() as u64;
|
||
|
||
// 初始化msi中断
|
||
// initialize msi interupt
|
||
let irq_vector = device.irq_vector_mut().unwrap();
|
||
irq_vector.push(E1000E_RECV_VECTOR);
|
||
device.irq_init(IRQ::PCI_IRQ_MSI).expect("IRQ Init Failed");
|
||
let msg = PciIrqMsg {
|
||
irq_common_message: IrqCommonMsg::init_from(
|
||
0,
|
||
"E1000E_RECV_IRQ".to_string(),
|
||
&DefaultNetIrqHandler,
|
||
device_id,
|
||
),
|
||
irq_specific_message: IrqSpecificMsg::msi_default(),
|
||
};
|
||
device.irq_install(msg)?;
|
||
device.irq_enable(true)?;
|
||
|
||
let general_regs: NonNull<GeneralRegs> =
|
||
get_register_ptr(vaddress, E1000E_GENERAL_REGS_OFFSET);
|
||
let interrupt_regs: NonNull<InterruptRegs> =
|
||
get_register_ptr(vaddress, E1000E_INTERRRUPT_REGS_OFFSET);
|
||
let rctl_regs: NonNull<ReceiveCtrlRegs> =
|
||
get_register_ptr(vaddress, E1000E_RECEIVE_CTRL_REG_OFFSET);
|
||
let receive_regs: NonNull<ReceiveRegs> =
|
||
get_register_ptr(vaddress, E1000E_RECEIVE_REGS_OFFSET);
|
||
let tctl_regs: NonNull<TransmitCtrlRegs> =
|
||
get_register_ptr(vaddress, E1000E_TRANSMIT_CTRL_REG_OFFSET);
|
||
let transimit_regs: NonNull<TransimitRegs> =
|
||
get_register_ptr(vaddress, E1000E_TRANSMIT_REGS_OFFSET);
|
||
let pcie_regs: NonNull<PCIeRegs> = get_register_ptr(vaddress, E1000E_PCIE_REGS_OFFSET);
|
||
let ra_regs: NonNull<ReceiveAddressRegs> =
|
||
get_register_ptr(vaddress, E1000E_RECEIVE_ADDRESS_REGS_OFFSET);
|
||
// 开始设备初始化 14.3
|
||
// Initialization Sequence
|
||
unsafe {
|
||
let mut ctrl = volread!(general_regs, ctrl);
|
||
// 关闭中断
|
||
// close the interrupt
|
||
volwrite!(interrupt_regs, imc, E1000E_IMC_CLEAR);
|
||
//SW RESET
|
||
volwrite!(general_regs, ctrl, ctrl | E1000E_CTRL_RST);
|
||
compiler_fence(Ordering::AcqRel);
|
||
// PHY RESET
|
||
ctrl = volread!(general_regs, ctrl);
|
||
volwrite!(general_regs, ctrl, ctrl | E1000E_CTRL_PHY_RST);
|
||
volwrite!(general_regs, ctrl, ctrl);
|
||
// 关闭中断
|
||
// close the interrupt
|
||
volwrite!(interrupt_regs, imc, E1000E_IMC_CLEAR);
|
||
let mut gcr = volread!(pcie_regs, gcr);
|
||
gcr |= 1 << 22;
|
||
volwrite!(pcie_regs, gcr, gcr);
|
||
compiler_fence(Ordering::AcqRel);
|
||
// PHY Initialization 14.8.1
|
||
// MAC/PHY Link Setup 14.8.2
|
||
ctrl = volread!(general_regs, ctrl);
|
||
ctrl &= !(E1000E_CTRL_FRCSPD | E1000E_CTRL_FRCDPLX);
|
||
volwrite!(general_regs, ctrl, ctrl | E1000E_CTRL_SLU);
|
||
}
|
||
let status = unsafe { volread!(general_regs, status) };
|
||
debug!("Status: {status:#X}");
|
||
|
||
// 读取设备的mac地址
|
||
// Read mac address
|
||
let ral = unsafe { volread!(ra_regs, ral0) };
|
||
let rah = unsafe { volread!(ra_regs, rah0) };
|
||
let mac: [u8; 6] = [
|
||
(ral & 0xFF) as u8,
|
||
((ral >> 8) & 0xFF) as u8,
|
||
((ral >> 16) & 0xFF) as u8,
|
||
((ral >> 24) & 0xFF) as u8,
|
||
(rah & 0xFF) as u8,
|
||
((rah >> 8) & 0xFF) as u8,
|
||
];
|
||
// 初始化receive和transimit descriptor环形队列
|
||
// initialize receive and transimit desciptor ring
|
||
let (recv_ring_pa, recv_ring_va) = dma_alloc(E1000E_DMA_PAGES);
|
||
let (trans_ring_pa, trans_ring_va) = dma_alloc(E1000E_DMA_PAGES);
|
||
let recv_ring_length = PAGE_SIZE / size_of::<E1000ERecvDesc>();
|
||
let trans_ring_length = PAGE_SIZE / size_of::<E1000ETransDesc>();
|
||
|
||
let recv_desc_ring = unsafe {
|
||
from_raw_parts_mut::<E1000ERecvDesc>(recv_ring_va.as_ptr().cast(), recv_ring_length)
|
||
};
|
||
let trans_desc_ring = unsafe {
|
||
from_raw_parts_mut::<E1000ETransDesc>(trans_ring_va.as_ptr().cast(), trans_ring_length)
|
||
};
|
||
|
||
// 初始化receive和transmit packet的缓冲区
|
||
// initialzie receive and transmit buffers
|
||
let mut recv_buffers: Vec<E1000EBuffer> = Vec::with_capacity(recv_ring_length);
|
||
let mut trans_buffers: Vec<E1000EBuffer> = Vec::with_capacity(trans_ring_length);
|
||
|
||
// 初始化缓冲区与descriptor,descriptor 中的addr字典应当指向buffer的物理地址
|
||
// Receive buffers of appropriate size should be allocated and pointers to these buffers should be stored in the descriptor ring.
|
||
for ring in recv_desc_ring.iter_mut().take(recv_ring_length) {
|
||
let buffer = E1000EBuffer::new(PAGE_SIZE);
|
||
ring.addr = buffer.as_paddr() as u64;
|
||
ring.status = 0;
|
||
recv_buffers.push(buffer);
|
||
}
|
||
// Same as receive buffers
|
||
for ring in trans_desc_ring.iter_mut().take(recv_ring_length) {
|
||
let buffer = E1000EBuffer::new(PAGE_SIZE);
|
||
ring.addr = buffer.as_paddr() as u64;
|
||
ring.status = 1;
|
||
trans_buffers.push(buffer);
|
||
}
|
||
|
||
// Receive Initialization 14.6
|
||
// Initialzie mutlicast table array to 0b
|
||
// 初始化MTA,遍历0x05200-0x053FC中每个寄存器,写入0b,一共128个寄存器
|
||
let mut mta_adress = vaddress + E1000E_MTA_REGS_START_OFFSET;
|
||
while mta_adress != vaddress + E1000E_MTA_REGS_END_OFFSET {
|
||
let mta: NonNull<MTARegs> = get_register_ptr(mta_adress, 0);
|
||
unsafe { volwrite!(mta, mta, 0) };
|
||
mta_adress += 4;
|
||
}
|
||
// 连续的寄存器读-写操作,放在同一个unsafe块中
|
||
unsafe {
|
||
// 设置descriptor环形队列的基地址
|
||
// Program the descriptor base address with the address of the region.
|
||
volwrite!(receive_regs, rdbal0, (recv_ring_pa) as u32);
|
||
volwrite!(receive_regs, rdbah0, (recv_ring_pa >> 32) as u32);
|
||
// 设置descriptor环形队列的长度
|
||
// Set the length register to the size of the descriptor ring.
|
||
volwrite!(receive_regs, rdlen0, PAGE_SIZE as u32);
|
||
// 设置队列的首尾指针
|
||
// Program the head and tail registers
|
||
volwrite!(receive_regs, rdh0, 0);
|
||
volwrite!(receive_regs, rdt0, (recv_ring_length - 1) as u32);
|
||
// 设置控制寄存器的相关功能 14.6.1
|
||
// Set the receive control register
|
||
volwrite!(
|
||
rctl_regs,
|
||
rctl,
|
||
E1000E_RCTL_EN
|
||
| E1000E_RCTL_BAM
|
||
| E1000E_RCTL_BSIZE_4K
|
||
| E1000E_RCTL_BSEX
|
||
| E1000E_RCTL_SECRC
|
||
);
|
||
|
||
// Transmit Initialization 14.7
|
||
// 开启发包descriptor的回写功能
|
||
// Program the TXDCTL register with the desired TX descriptor write-back policy
|
||
volwrite!(
|
||
transimit_regs,
|
||
txdctl,
|
||
E1000E_TXDCTL_WTHRESH | E1000E_TXDCTL_GRAN
|
||
);
|
||
// 设置descriptor环形队列的基地址,长度与首尾指针
|
||
// Program the descriptor base address with the address of the region
|
||
volwrite!(transimit_regs, tdbal0, trans_ring_pa as u32);
|
||
volwrite!(transimit_regs, tdbah0, (trans_ring_pa >> 32) as u32);
|
||
// Set the length register to the size of the descriptor ring.
|
||
volwrite!(transimit_regs, tdlen0, PAGE_SIZE as u32);
|
||
// Program the head and tail registerss
|
||
volwrite!(transimit_regs, tdh0, 0);
|
||
volwrite!(transimit_regs, tdt0, 0);
|
||
// Program the TIPG register
|
||
volwrite!(
|
||
tctl_regs,
|
||
tipg,
|
||
E1000E_TIPG_IPGT | E1000E_TIPG_IPGR1 | E1000E_TIPG_IPGR2
|
||
);
|
||
// Program the TCTL register.
|
||
volwrite!(
|
||
tctl_regs,
|
||
tctl,
|
||
E1000E_TCTL_EN | E1000E_TCTL_PSP | E1000E_TCTL_CT_VAL | E1000E_TCTL_COLD_VAL
|
||
);
|
||
|
||
let icr = volread!(interrupt_regs, icr);
|
||
volwrite!(interrupt_regs, icr, icr);
|
||
// 开启收包相关的中断
|
||
// Enable receive interrupts
|
||
let mut ims = volread!(interrupt_regs, ims);
|
||
ims = E1000E_IMS_LSC | E1000E_IMS_RXT0 | E1000E_IMS_RXDMT0 | E1000E_IMS_OTHER;
|
||
volwrite!(interrupt_regs, ims, ims);
|
||
}
|
||
return Ok(E1000EDevice {
|
||
general_regs,
|
||
interrupt_regs,
|
||
rctl_regs,
|
||
receive_regs,
|
||
tctl_regs,
|
||
transimit_regs,
|
||
pcie_regs,
|
||
recv_desc_ring,
|
||
trans_desc_ring,
|
||
recv_ring_pa,
|
||
trans_ring_pa,
|
||
recv_buffers,
|
||
trans_buffers,
|
||
mac,
|
||
first_trans: true,
|
||
napi_buffers: vec![E1000EBuffer::new(0); E1000E_RECV_NAPI],
|
||
napi_buffer_head: 0,
|
||
napi_buffer_tail: 0,
|
||
napi_buffer_empty: true,
|
||
});
|
||
}
|
||
pub fn e1000e_receive(&mut self) -> Option<E1000EBuffer> {
|
||
self.e1000e_intr();
|
||
let mut rdt = unsafe { volread!(self.receive_regs, rdt0) } as usize;
|
||
let index = (rdt + 1) % self.recv_desc_ring.len();
|
||
let desc = &mut self.recv_desc_ring[index];
|
||
if (desc.status & E1000E_RXD_STATUS_DD) == 0 {
|
||
return None;
|
||
}
|
||
let mut buffer = self.recv_buffers[index];
|
||
let new_buffer = E1000EBuffer::new(PAGE_SIZE);
|
||
self.recv_buffers[index] = new_buffer;
|
||
desc.addr = new_buffer.as_paddr() as u64;
|
||
buffer.set_length(desc.len as usize);
|
||
rdt = index;
|
||
unsafe { volwrite!(self.receive_regs, rdt0, rdt as u32) };
|
||
// debug!("e1000e: receive packet");
|
||
return Some(buffer);
|
||
}
|
||
|
||
pub fn e1000e_can_transmit(&self) -> bool {
|
||
let tdt = unsafe { volread!(self.transimit_regs, tdt0) } as usize;
|
||
let index = tdt % self.trans_desc_ring.len();
|
||
let desc = &self.trans_desc_ring[index];
|
||
if (desc.status & E1000E_TXD_STATUS_DD) == 0 {
|
||
return false;
|
||
}
|
||
true
|
||
}
|
||
|
||
pub fn e1000e_transmit(&mut self, packet: E1000EBuffer) {
|
||
let mut tdt = unsafe { volread!(self.transimit_regs, tdt0) } as usize;
|
||
let index = tdt % self.trans_desc_ring.len();
|
||
let desc = &mut self.trans_desc_ring[index];
|
||
let buffer = self.trans_buffers[index];
|
||
self.trans_buffers[index] = packet;
|
||
// recycle unused transmit buffer
|
||
buffer.free_buffer();
|
||
// Set the transmit descriptor
|
||
desc.addr = packet.as_paddr() as u64;
|
||
desc.len = packet.len() as u16;
|
||
desc.status = 0;
|
||
desc.cmd = E1000E_TXD_CMD_EOP | E1000E_TXD_CMD_RS | E1000E_TXD_CMD_IFCS;
|
||
tdt = (tdt + 1) % self.trans_desc_ring.len();
|
||
unsafe { volwrite!(self.transimit_regs, tdt0, tdt as u32) };
|
||
self.first_trans = false;
|
||
}
|
||
pub fn mac_address(&self) -> [u8; 6] {
|
||
return self.mac;
|
||
}
|
||
// 向ICR寄存器中的某一bit写入1b表示该中断已经被接收,同时会清空该位
|
||
// we need to clear ICR to tell e1000e we have read the interrupt
|
||
pub fn e1000e_intr(&mut self) {
|
||
let icr = unsafe { volread!(self.interrupt_regs, icr) };
|
||
// write 1b to any bit in ICR will clear the bit
|
||
unsafe { volwrite!(self.interrupt_regs, icr, icr) };
|
||
}
|
||
|
||
// 切换是否接受分组到达的中断
|
||
// change whether the receive timer interrupt is enabled
|
||
// Note: this method is not completely implemented and not used in the current version
|
||
#[allow(dead_code)]
|
||
pub fn e1000e_intr_set(&mut self, state: bool) {
|
||
let mut ims = unsafe { volread!(self.interrupt_regs, ims) };
|
||
match state {
|
||
true => ims |= E1000E_IMS_RXT0,
|
||
false => ims &= !E1000E_IMS_RXT0,
|
||
}
|
||
unsafe { volwrite!(self.interrupt_regs, ims, ims) };
|
||
}
|
||
|
||
// 实现了一部分napi机制的收包函数, 现在还没有投入使用
|
||
// This method is a partial implementation of napi (New API) techniques
|
||
// Note: this method is not completely implemented and not used in the current version
|
||
#[allow(dead_code)]
|
||
pub fn e1000e_receive2(&mut self) -> Option<E1000EBuffer> {
|
||
// 向设备表明我们已经接受到了之前的中断
|
||
// Tell e1000e we have received the interrupt
|
||
self.e1000e_intr();
|
||
// 如果napi队列不存在已经收到的分组...
|
||
// if napi queue is empty...
|
||
if self.napi_buffer_empty {
|
||
// 暂时关闭设备中断
|
||
// close interrupt
|
||
self.e1000e_intr_set(false);
|
||
loop {
|
||
if self.napi_buffer_tail == self.napi_buffer_head && !self.napi_buffer_empty {
|
||
// napi缓冲队列已满,停止收包
|
||
// napi queue is full, stop
|
||
break;
|
||
}
|
||
match self.e1000e_receive() {
|
||
Some(buffer) => {
|
||
self.napi_buffers[self.napi_buffer_tail] = buffer;
|
||
self.napi_buffer_tail = (self.napi_buffer_tail + 1) % E1000E_RECV_NAPI;
|
||
self.napi_buffer_empty = false;
|
||
}
|
||
None => {
|
||
// 设备队列中没有剩余的已到达的数据包
|
||
// no packet remains in the device buffer
|
||
break;
|
||
}
|
||
};
|
||
}
|
||
// 重新打开设备中断
|
||
// open the interrupt
|
||
self.e1000e_intr_set(true);
|
||
}
|
||
|
||
let result = self.napi_buffers[self.napi_buffer_head];
|
||
match result.len() {
|
||
0 => {
|
||
// napi队列和网卡队列中都不存在数据包
|
||
// both napi queue and device buffer is empty, no packet will receive
|
||
return None;
|
||
}
|
||
_ => {
|
||
// 有剩余的已到达的数据包
|
||
// there is packet in napi queue
|
||
self.napi_buffer_head = (self.napi_buffer_head + 1) % E1000E_RECV_NAPI;
|
||
if self.napi_buffer_head == self.napi_buffer_tail {
|
||
self.napi_buffer_empty = true;
|
||
}
|
||
return Some(result);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
impl Drop for E1000EDevice {
|
||
fn drop(&mut self) {
|
||
// 释放已分配的所有dma页
|
||
// free all dma pages we have allocated
|
||
debug!("droping...");
|
||
let recv_ring_length = PAGE_SIZE / size_of::<E1000ERecvDesc>();
|
||
let trans_ring_length = PAGE_SIZE / size_of::<E1000ETransDesc>();
|
||
unsafe {
|
||
// 释放所有buffer中的dma页
|
||
// free all dma pages in buffers
|
||
for i in 0..recv_ring_length {
|
||
self.recv_buffers[i].free_buffer();
|
||
}
|
||
for i in 0..trans_ring_length {
|
||
self.trans_buffers[i].free_buffer();
|
||
}
|
||
// 释放descriptor ring
|
||
// free descriptor ring
|
||
dma_dealloc(
|
||
self.recv_ring_pa,
|
||
NonNull::new(self.recv_desc_ring).unwrap().cast(),
|
||
E1000E_DMA_PAGES,
|
||
);
|
||
dma_dealloc(
|
||
self.trans_ring_pa,
|
||
NonNull::new(self.trans_desc_ring).unwrap().cast(),
|
||
E1000E_DMA_PAGES,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
pub fn e1000e_init() {
|
||
match e1000e_probe() {
|
||
Ok(_code) => {
|
||
info!("Successfully init e1000e device!");
|
||
}
|
||
Err(_error) => {
|
||
info!("Error occurred!");
|
||
}
|
||
}
|
||
}
|
||
|
||
pub fn e1000e_probe() -> Result<u64, E1000EPciError> {
|
||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||
let result = get_pci_device_structure_mut(&mut list, NETWORK_CLASS, ETHERNET_SUBCLASS);
|
||
if result.is_empty() {
|
||
return Ok(0);
|
||
}
|
||
for device in result {
|
||
let standard_device = device.as_standard_device_mut().unwrap();
|
||
let header = &standard_device.common_header;
|
||
if header.vendor_id == 0x8086 {
|
||
// intel
|
||
if E1000E_DEVICE_ID.contains(&header.device_id) {
|
||
debug!(
|
||
"Detected e1000e PCI device with device id {:#x}",
|
||
header.device_id
|
||
);
|
||
|
||
// todo: 根据pci的path来生成device id
|
||
let e1000e = E1000EDevice::new(
|
||
standard_device,
|
||
DeviceId::new(None, Some(format!("e1000e_{}", header.device_id))).unwrap(),
|
||
)?;
|
||
e1000e_driver_init(e1000e);
|
||
}
|
||
}
|
||
}
|
||
|
||
return Ok(1);
|
||
}
|
||
|
||
// 用到的e1000e寄存器结构体
|
||
// pp.275, Table 13-3
|
||
// 设备通用寄存器
|
||
#[allow(dead_code)]
|
||
struct GeneralRegs {
|
||
ctrl: Volatile<u32>, //0x00000
|
||
ctrl_alias: Volatile<u32>, //0x00004
|
||
status: ReadOnly<u32>, //0x00008
|
||
status_align: ReadOnly<u32>, //0x0000c
|
||
eec: Volatile<u32>, //0x00010
|
||
eerd: Volatile<u32>, //0x00014
|
||
ctrl_ext: Volatile<u32>, //0x00018
|
||
fla: Volatile<u32>, //0x0001c
|
||
mdic: Volatile<u32>, //0x00020
|
||
}
|
||
// 中断控制
|
||
#[allow(dead_code)]
|
||
struct InterruptRegs {
|
||
icr: Volatile<u32>, //0x000c0 ICR寄存器应当为只读寄存器,但我们需要向其中写入来清除对应位
|
||
itr: Volatile<u32>, //0x000c4
|
||
ics: WriteOnly<u32>, //0x000c8
|
||
ics_align: ReadOnly<u32>, //0x000cc
|
||
ims: Volatile<u32>, //0x000d0
|
||
ims_align: ReadOnly<u32>, //0x000d4
|
||
imc: WriteOnly<u32>, //0x000d8
|
||
}
|
||
// 收包功能控制
|
||
struct ReceiveCtrlRegs {
|
||
rctl: Volatile<u32>, //0x00100
|
||
}
|
||
// 发包功能控制
|
||
#[allow(dead_code)]
|
||
struct TransmitCtrlRegs {
|
||
tctl: Volatile<u32>, //0x00400
|
||
tctl_ext: Volatile<u32>, //0x00404
|
||
unused_1: ReadOnly<u32>, //0x00408
|
||
unused_2: ReadOnly<u32>, //0x0040c
|
||
tipg: Volatile<u32>, //0x00410
|
||
}
|
||
// 收包功能相关
|
||
#[allow(dead_code)]
|
||
struct ReceiveRegs {
|
||
rdbal0: Volatile<u32>, //0x02800
|
||
rdbah0: Volatile<u32>, //0x02804
|
||
rdlen0: Volatile<u32>, //0x02808
|
||
rdl_align: ReadOnly<u32>, //0x0280c
|
||
rdh0: Volatile<u32>, //0x02810
|
||
rdh_align: ReadOnly<u32>, //0x02814
|
||
rdt0: Volatile<u32>, //0x02818
|
||
rdt_align: ReadOnly<u32>, //0x281c
|
||
rdtr: Volatile<u32>, //0x2820
|
||
rdtr_align: ReadOnly<u32>, //0x2824
|
||
rxdctl: Volatile<u32>, //0x2828
|
||
}
|
||
// 发包功能相关
|
||
#[allow(dead_code)]
|
||
struct TransimitRegs {
|
||
tdbal0: Volatile<u32>, //0x03800
|
||
tdbah0: Volatile<u32>, //0x03804
|
||
tdlen0: Volatile<u32>, //0x03808
|
||
tdlen_algin: ReadOnly<u32>, //0x0380c
|
||
tdh0: Volatile<u32>, //0x03810
|
||
tdh_align: ReadOnly<u32>, //0x03814
|
||
tdt0: Volatile<u32>, //0x03818
|
||
tdt_align: ReadOnly<u32>, //0x0381c
|
||
tidv: Volatile<u32>, //0x03820
|
||
tidv_align: ReadOnly<u32>, //0x03824
|
||
txdctl: Volatile<u32>, //0x03828
|
||
tadv: Volatile<u32>, //0x0382c
|
||
}
|
||
// mac地址
|
||
struct ReceiveAddressRegs {
|
||
ral0: Volatile<u32>, //0x05400
|
||
rah0: Volatile<u32>, //0x05404
|
||
}
|
||
// PCIe 通用控制
|
||
struct PCIeRegs {
|
||
gcr: Volatile<u32>, //0x05b00
|
||
}
|
||
#[allow(dead_code)]
|
||
struct StatisticsRegs {}
|
||
|
||
// 0x05200-0x053fc
|
||
// 在Receive Initialization 中按照每次一个32bit寄存器的方式来遍历
|
||
// Multicast Table Array Registers will be written per 32bit
|
||
struct MTARegs {
|
||
mta: Volatile<u32>,
|
||
}
|
||
|
||
const E1000E_GENERAL_REGS_OFFSET: u64 = 0x00000;
|
||
const E1000E_INTERRRUPT_REGS_OFFSET: u64 = 0x000c0;
|
||
const E1000E_RECEIVE_CTRL_REG_OFFSET: u64 = 0x00100;
|
||
const E1000E_RECEIVE_REGS_OFFSET: u64 = 0x02800;
|
||
const E1000E_TRANSMIT_CTRL_REG_OFFSET: u64 = 0x00400;
|
||
const E1000E_TRANSMIT_REGS_OFFSET: u64 = 0x03800;
|
||
const E1000E_RECEIVE_ADDRESS_REGS_OFFSET: u64 = 0x05400;
|
||
const E1000E_PCIE_REGS_OFFSET: u64 = 0x05b00;
|
||
const E1000E_MTA_REGS_START_OFFSET: u64 = 0x05200;
|
||
const E1000E_MTA_REGS_END_OFFSET: u64 = 0x053fc;
|
||
// 寄存器的特定位
|
||
//CTRL
|
||
const E1000E_CTRL_SLU: u32 = 1 << 6;
|
||
const E1000E_CTRL_FRCSPD: u32 = 1 << 11;
|
||
const E1000E_CTRL_FRCDPLX: u32 = 1 << 12;
|
||
const E1000E_CTRL_RST: u32 = 1 << 26;
|
||
#[allow(dead_code)]
|
||
const E1000E_CTRL_RFCE: u32 = 1 << 27;
|
||
#[allow(dead_code)]
|
||
const E1000E_CTRL_TFCE: u32 = 1 << 28;
|
||
const E1000E_CTRL_PHY_RST: u32 = 1 << 31;
|
||
|
||
// IMS
|
||
const E1000E_IMS_LSC: u32 = 1 << 2;
|
||
const E1000E_IMS_RXDMT0: u32 = 1 << 4;
|
||
#[allow(dead_code)]
|
||
const E1000E_IMS_RXO: u32 = 1 << 6;
|
||
const E1000E_IMS_RXT0: u32 = 1 << 7;
|
||
#[allow(dead_code)]
|
||
const E1000E_IMS_RXQ0: u32 = 1 << 20;
|
||
const E1000E_IMS_OTHER: u32 = 1 << 24; // qemu use this bit to set msi-x interrupt
|
||
|
||
// IMC
|
||
const E1000E_IMC_CLEAR: u32 = 0xffffffff;
|
||
|
||
// RCTL
|
||
const E1000E_RCTL_EN: u32 = 1 << 1;
|
||
const E1000E_RCTL_BAM: u32 = 1 << 15;
|
||
const E1000E_RCTL_BSIZE_4K: u32 = 3 << 16;
|
||
const E1000E_RCTL_BSEX: u32 = 1 << 25;
|
||
const E1000E_RCTL_SECRC: u32 = 1 << 26;
|
||
|
||
// TCTL
|
||
const E1000E_TCTL_EN: u32 = 1 << 1;
|
||
const E1000E_TCTL_PSP: u32 = 1 << 3;
|
||
const E1000E_TCTL_CT_VAL: u32 = 0x0f << 4; // suggested 16d collision, 手册建议值:16d
|
||
const E1000E_TCTL_COLD_VAL: u32 = 0x03f << 12; // suggested 64 byte time for Full-Duplex, 手册建议值:64
|
||
// TXDCTL
|
||
const E1000E_TXDCTL_WTHRESH: u32 = 1 << 16;
|
||
const E1000E_TXDCTL_GRAN: u32 = 1 << 24;
|
||
// TIPG
|
||
const E1000E_TIPG_IPGT: u32 = 8;
|
||
const E1000E_TIPG_IPGR1: u32 = 2 << 10;
|
||
const E1000E_TIPG_IPGR2: u32 = 10 << 20;
|
||
|
||
// RxDescriptorStatus
|
||
const E1000E_RXD_STATUS_DD: u16 = 1 << 0;
|
||
|
||
// TxDescriptorStatus
|
||
const E1000E_TXD_STATUS_DD: u8 = 1 << 0;
|
||
const E1000E_TXD_CMD_EOP: u8 = 1 << 0;
|
||
const E1000E_TXD_CMD_IFCS: u8 = 1 << 1;
|
||
const E1000E_TXD_CMD_RS: u8 = 1 << 3;
|
||
|
||
/// E1000E驱动初始化过程中可能的错误
|
||
#[allow(dead_code)]
|
||
pub enum E1000EPciError {
|
||
// 获取到错误类型的BAR(IO BAR)
|
||
// An IO BAR was provided rather than a memory BAR.
|
||
UnexpectedBarType,
|
||
// 获取的BAR没有被分配到某个地址(address == 0)
|
||
// A BAR which we need was not allocated an address(address == 0).
|
||
BarNotAllocated,
|
||
//获取虚拟地址失败
|
||
BarGetVaddrFailed,
|
||
// 没有对应的BAR或者获取BAR失败
|
||
BarGetFailed,
|
||
// BAR的大小与预期不符(128KB)
|
||
// Size of BAR is not 128KB
|
||
UnexpectedBarSize,
|
||
Pci(PciError),
|
||
}
|
||
|
||
/// PCI error到VirtioPciError的转换,层层上报
|
||
impl From<PciError> for E1000EPciError {
|
||
fn from(error: PciError) -> Self {
|
||
Self::Pci(error)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取基地址的某个偏移量的指针,用于在mmio bar中构造寄存器结构体
|
||
* @brief used for build register struct in mmio bar
|
||
* @param vaddr: base address (in virtual memory)
|
||
* @param offset: offset
|
||
*/
|
||
fn get_register_ptr<T>(vaddr: u64, offset: u64) -> NonNull<T> {
|
||
NonNull::new((vaddr + offset) as *mut T).unwrap()
|
||
}
|