mirror of https://github.com/vinc/moros.git
348 lines
10 KiB
Rust
348 lines
10 KiB
Rust
use crate::sys;
|
|
use crate::sys::allocator::PhysBuf;
|
|
use crate::sys::net::{Config, EthernetDeviceIO, Stats};
|
|
|
|
use alloc::sync::Arc;
|
|
use alloc::vec::Vec;
|
|
use bit_field::BitField;
|
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
|
use smoltcp::wire::EthernetAddress;
|
|
use x86_64::instructions::port::Port;
|
|
|
|
const CSR0_INIT: usize = 0;
|
|
const CSR0_STRT: usize = 1;
|
|
//const CSR0_STOP: usize = 2;
|
|
const CSR0_TDMD: usize = 3;
|
|
//const CSR0_TXON: usize = 4;
|
|
//const CSR0_RXON: usize = 5;
|
|
//const CSR0_IENA: usize = 6;
|
|
//const CSR0_INTR: usize = 7;
|
|
const CSR0_IDON: usize = 8;
|
|
//const CSR0_TINT: usize = 9;
|
|
//const CSR0_RINT: usize = 10;
|
|
//const CSR0_MERR: usize = 11;
|
|
//const CSR0_MISS: usize = 12;
|
|
//const CSR0_CERR: usize = 13;
|
|
//const CSR0_BABL: usize = 14;
|
|
//const CSR0_ERR: usize = 0;
|
|
|
|
const DE_ENP: usize = 0;
|
|
const DE_STP: usize = 1;
|
|
//const DE_BUFF: usize = 2;
|
|
//const DE_CRC: usize = 3;
|
|
//const DE_OFLO: usize = 4;
|
|
//const DE_FRAM: usize = 5;
|
|
//const DE_ERR: usize = 6;
|
|
const DE_OWN: usize = 7;
|
|
|
|
#[derive(Clone)]
|
|
pub struct Ports {
|
|
pub mac: [Port<u8>; 6],
|
|
pub rdp_16: Port<u16>,
|
|
pub rap_16: Port<u16>,
|
|
pub rst_16: Port<u16>,
|
|
pub bdp_16: Port<u16>,
|
|
|
|
pub rdp_32: Port<u32>,
|
|
pub rap_32: Port<u32>,
|
|
pub rst_32: Port<u32>,
|
|
pub bdp_32: Port<u32>,
|
|
}
|
|
|
|
impl Ports {
|
|
pub fn new(io_base: u16) -> Self {
|
|
Self {
|
|
mac: [
|
|
Port::new(io_base + 0x00),
|
|
Port::new(io_base + 0x01),
|
|
Port::new(io_base + 0x02),
|
|
Port::new(io_base + 0x03),
|
|
Port::new(io_base + 0x04),
|
|
Port::new(io_base + 0x05),
|
|
],
|
|
|
|
rdp_16: Port::new(io_base + 0x10),
|
|
rap_16: Port::new(io_base + 0x12),
|
|
rst_16: Port::new(io_base + 0x14),
|
|
bdp_16: Port::new(io_base + 0x16),
|
|
|
|
rdp_32: Port::new(io_base + 0x10),
|
|
rap_32: Port::new(io_base + 0x14),
|
|
rst_32: Port::new(io_base + 0x18),
|
|
bdp_32: Port::new(io_base + 0x1C),
|
|
}
|
|
}
|
|
|
|
fn write_rap_32(&mut self, val: u32) {
|
|
unsafe { self.rap_32.write(val) }
|
|
}
|
|
|
|
fn read_csr_32(&mut self, csr: u32) -> u32 {
|
|
self.write_rap_32(csr);
|
|
unsafe { self.rdp_32.read() }
|
|
}
|
|
|
|
fn write_csr_32(&mut self, csr: u32, val: u32) {
|
|
self.write_rap_32(csr);
|
|
unsafe { self.rdp_32.write(val) }
|
|
}
|
|
|
|
fn read_bcr_32(&mut self, bcr: u32) -> u32 {
|
|
self.write_rap_32(bcr);
|
|
unsafe { self.bdp_32.read() }
|
|
}
|
|
|
|
fn write_bcr_32(&mut self, bcr: u32, val: u32) {
|
|
self.write_rap_32(bcr);
|
|
unsafe { self.bdp_32.write(val) }
|
|
}
|
|
|
|
fn mac(&mut self) -> [u8; 6] {
|
|
unsafe {
|
|
[
|
|
self.mac[0].read(),
|
|
self.mac[1].read(),
|
|
self.mac[2].read(),
|
|
self.mac[3].read(),
|
|
self.mac[4].read(),
|
|
self.mac[5].read(),
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
const MTU: usize = 1536;
|
|
const RX_BUFFERS_COUNT: usize = 32;
|
|
const TX_BUFFERS_COUNT: usize = 8;
|
|
const DE_LEN: usize = 16;
|
|
|
|
fn log2(x: u8) -> u8 {
|
|
8 - 1 - x.leading_zeros() as u8
|
|
}
|
|
|
|
fn is_buffer_owner(des: &PhysBuf, i: usize) -> bool {
|
|
// This bit indicates that the descriptor entry is owned
|
|
// by the host (OWN=0) or by the PCnet-PCI controller (OWN=1)
|
|
!des[DE_LEN * i + 7].get_bit(DE_OWN)
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Device {
|
|
config: Arc<Config>,
|
|
stats: Arc<Stats>,
|
|
ports: Ports,
|
|
|
|
rx_buffers: [PhysBuf; RX_BUFFERS_COUNT],
|
|
tx_buffers: [PhysBuf; TX_BUFFERS_COUNT],
|
|
rx_des: PhysBuf, // Ring buffer of rx descriptor entries
|
|
tx_des: PhysBuf, // Ring buffer of tx descriptor entries
|
|
rx_id: Arc<AtomicUsize>,
|
|
tx_id: Arc<AtomicUsize>,
|
|
}
|
|
|
|
impl Device {
|
|
pub fn new(io_base: u16) -> Self {
|
|
let mut device = Self {
|
|
config: Arc::new(Config::new()),
|
|
stats: Arc::new(Stats::new()),
|
|
ports: Ports::new(io_base),
|
|
rx_buffers: [(); RX_BUFFERS_COUNT].map(|_| PhysBuf::new(MTU)),
|
|
tx_buffers: [(); TX_BUFFERS_COUNT].map(|_| PhysBuf::new(MTU)),
|
|
rx_des: PhysBuf::new(RX_BUFFERS_COUNT * DE_LEN),
|
|
tx_des: PhysBuf::new(TX_BUFFERS_COUNT * DE_LEN),
|
|
rx_id: Arc::new(AtomicUsize::new(0)),
|
|
tx_id: Arc::new(AtomicUsize::new(0)),
|
|
};
|
|
device.init();
|
|
device
|
|
}
|
|
|
|
fn init(&mut self) {
|
|
// Read MAC addr
|
|
let mac = self.ports.mac();
|
|
self.config.update_mac(EthernetAddress::from_bytes(&mac));
|
|
|
|
// Reset to 16-bit access
|
|
unsafe {
|
|
self.ports.rst_32.read();
|
|
self.ports.rst_16.read();
|
|
}
|
|
|
|
// Switch to 32-bit access
|
|
unsafe {
|
|
self.ports.rdp_32.write(0);
|
|
}
|
|
|
|
// SWSTYLE
|
|
let mut csr_58 = self.ports.read_csr_32(58);
|
|
csr_58 &= 0xFF00;
|
|
csr_58 |= 2;
|
|
self.ports.write_csr_32(58, csr_58);
|
|
|
|
// ASEL
|
|
let mut bcr_2 = self.ports.read_bcr_32(2);
|
|
bcr_2 |= 2;
|
|
self.ports.write_bcr_32(2, bcr_2);
|
|
|
|
// Initialize ring buffers
|
|
let is_rx = true;
|
|
for i in 0..RX_BUFFERS_COUNT {
|
|
self.init_descriptor_entry(i, is_rx);
|
|
}
|
|
for i in 0..TX_BUFFERS_COUNT {
|
|
self.init_descriptor_entry(i, !is_rx);
|
|
}
|
|
|
|
// Card register setup
|
|
let mut init_struct = PhysBuf::new(28);
|
|
init_struct[0] = 0; // Mode
|
|
init_struct[1] = 0; // Mode
|
|
init_struct[2].set_bits(4..8, log2(RX_BUFFERS_COUNT as u8));
|
|
init_struct[3].set_bits(4..8, log2(TX_BUFFERS_COUNT as u8));
|
|
init_struct[4] = mac[0];
|
|
init_struct[5] = mac[1];
|
|
init_struct[6] = mac[2];
|
|
init_struct[7] = mac[3];
|
|
init_struct[8] = mac[4];
|
|
init_struct[9] = mac[5];
|
|
let rx_addr = self.rx_des.addr().to_le_bytes();
|
|
init_struct[20] = rx_addr[0];
|
|
init_struct[21] = rx_addr[1];
|
|
init_struct[22] = rx_addr[2];
|
|
init_struct[23] = rx_addr[3];
|
|
let tx_addr = self.tx_des.addr().to_le_bytes();
|
|
init_struct[24] = tx_addr[0];
|
|
init_struct[25] = tx_addr[1];
|
|
init_struct[26] = tx_addr[2];
|
|
init_struct[27] = tx_addr[3];
|
|
let addr = init_struct.addr();
|
|
self.ports.write_csr_32(1, addr.get_bits(0..16) as u32);
|
|
self.ports.write_csr_32(2, addr.get_bits(16..32) as u32);
|
|
|
|
// STOP
|
|
debug_assert!(self.ports.read_csr_32(0) == 0b000000100);
|
|
|
|
// self.ports.write_csr_32(4, 1 << 11); // Pad short ethernet packets
|
|
|
|
// Set INIT bit
|
|
self.ports.write_csr_32(0, 1 << CSR0_INIT);
|
|
|
|
// Wait until init is done
|
|
while !self.ports.read_csr_32(0).get_bit(CSR0_IDON) {
|
|
sys::time::halt();
|
|
}
|
|
|
|
// IDON + INTR + INIT
|
|
debug_assert!(self.ports.read_csr_32(0) == 0b110000001);
|
|
|
|
// Start the card
|
|
self.ports.write_csr_32(0, 1 << CSR0_STRT);
|
|
|
|
// IDON + INTR + RXON + TXON + STRT + INIT
|
|
debug_assert!(self.ports.read_csr_32(0) == 0b110110011);
|
|
}
|
|
|
|
fn init_descriptor_entry(&mut self, i: usize, is_rx: bool) {
|
|
let des = if is_rx {
|
|
&mut self.rx_des
|
|
} else {
|
|
&mut self.tx_des
|
|
};
|
|
|
|
// Set buffer address
|
|
let addr = if is_rx {
|
|
self.rx_buffers[i].addr().to_le_bytes()
|
|
} else {
|
|
self.tx_buffers[i].addr().to_le_bytes()
|
|
};
|
|
des[DE_LEN * i + 0] = addr[0];
|
|
des[DE_LEN * i + 1] = addr[1];
|
|
des[DE_LEN * i + 2] = addr[2];
|
|
des[DE_LEN * i + 3] = addr[3];
|
|
|
|
// Set buffer byte count (0..12 BCNT + 12..16 ONES)
|
|
let bcnt = (0xF000 | (0x0FFF & (1 + !(MTU as u16)))).to_le_bytes();
|
|
des[DE_LEN * i + 4] = bcnt[0];
|
|
des[DE_LEN * i + 5] = bcnt[1];
|
|
|
|
if is_rx {
|
|
des[DE_LEN * i + 7].set_bit(DE_OWN, true); // Set ownership to card
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EthernetDeviceIO for Device {
|
|
fn config(&self) -> Arc<Config> {
|
|
self.config.clone()
|
|
}
|
|
|
|
fn stats(&self) -> Arc<Stats> {
|
|
self.stats.clone()
|
|
}
|
|
|
|
fn receive_packet(&mut self) -> Option<Vec<u8>> {
|
|
let mut packet = Vec::new();
|
|
let mut rx_id = self.rx_id.load(Ordering::SeqCst);
|
|
while is_buffer_owner(&self.rx_des, rx_id) {
|
|
let rmd1 = self.rx_des[rx_id * DE_LEN + 7];
|
|
let end_of_packet = rmd1.get_bit(DE_ENP);
|
|
|
|
// Read packet size
|
|
let packet_size = u16::from_le_bytes([
|
|
self.rx_des[rx_id * DE_LEN + 8],
|
|
self.rx_des[rx_id * DE_LEN + 9],
|
|
]) as usize;
|
|
|
|
let n = if end_of_packet {
|
|
packet_size
|
|
} else {
|
|
self.rx_buffers[rx_id].len()
|
|
};
|
|
packet.extend(&self.rx_buffers[rx_id][0..n]);
|
|
|
|
// Give back ownership
|
|
self.rx_des[rx_id * DE_LEN + 7].set_bit(DE_OWN, true);
|
|
|
|
rx_id = (rx_id + 1) % RX_BUFFERS_COUNT;
|
|
self.rx_id.store(rx_id, Ordering::SeqCst);
|
|
|
|
if end_of_packet {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if !packet.is_empty() {
|
|
Some(packet)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn transmit_packet(&mut self, len: usize) {
|
|
let tx_id = self.tx_id.load(Ordering::SeqCst);
|
|
|
|
// Set start and end of packet
|
|
self.tx_des[tx_id * DE_LEN + 7].set_bit(DE_STP, true);
|
|
self.tx_des[tx_id * DE_LEN + 7].set_bit(DE_ENP, true);
|
|
|
|
// Set buffer byte count (0..12 BCNT + 12..16 ONES)
|
|
let bcnt = (0xF000 | (0x0FFF & (1 + !(len as u16)))).to_le_bytes();
|
|
self.tx_des[tx_id * DE_LEN + 4] = bcnt[0];
|
|
self.tx_des[tx_id * DE_LEN + 5] = bcnt[1];
|
|
|
|
// Give back ownership to the card
|
|
self.tx_des[tx_id * DE_LEN + 7].set_bit(DE_OWN, true);
|
|
|
|
self.tx_id.store((tx_id + 1) % TX_BUFFERS_COUNT, Ordering::SeqCst);
|
|
|
|
if !is_buffer_owner(&self.tx_des, tx_id) {
|
|
self.ports.write_csr_32(0, 1 << CSR0_TDMD); // Send all buffers
|
|
}
|
|
}
|
|
|
|
fn next_tx_buffer(&mut self, len: usize) -> &mut [u8] {
|
|
let tx_id = self.tx_id.load(Ordering::SeqCst);
|
|
&mut self.tx_buffers[tx_id][0..len]
|
|
}
|
|
}
|