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; 6], pub rdp_16: Port, pub rap_16: Port, pub rst_16: Port, pub bdp_16: Port, pub rdp_32: Port, pub rap_32: Port, pub rst_32: Port, pub bdp_32: Port, } 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, stats: Arc, 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, tx_id: Arc, } 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 { self.config.clone() } fn stats(&self) -> Arc { self.stats.clone() } fn receive_packet(&mut self) -> Option> { 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] } }