mirror of https://github.com/vinc/moros.git
Fix RTL8139 driver issues (#483)
* Fix typo in rx buffer size * Fix issue with small packets tx * Change tx buffer len * Fix tx ring overflow * Use 1024 bytes for max DMA burst size * Use spin_loop * Add atomic fence before polling for status change * Disable interrupts * Update device capabilities * Fix http service * Update /var/www * Refactor buf len * Update changelog
This commit is contained in:
parent
1396d7c8d2
commit
7665c11a9a
|
@ -1,6 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
- Fix RTL8139 driver issues (#483)
|
||||
- Improve help system (#481)
|
||||
- Refactor lisp functions (#478)
|
||||
- Improve asm binaries (#482)
|
||||
- Add light palette (#480)
|
||||
- Fix invalid bytes from serial (#479)
|
||||
- Refactor lisp functions (#478)
|
||||
- Improve asm binaries (#482)
|
||||
- Add light palette (#480)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MOROS: Obscure Rust Operating System</title>
|
||||
<link rel="stylesheet" type="text/css" href="moros.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>MOROS: Obscure Rust Operating System</h1>
|
||||
|
||||
<p><img src="moros.png" alt="screenshot"></p>
|
||||
|
||||
<p>MOROS is a hobby operating system written in Rust by <a href="https://vinc.cc">Vincent Ollivier</a>.</p>
|
||||
|
||||
<p>It targets computers with a x86-64 architecture and a BIOS, so mostly from 2005
|
||||
to 2020, but it also runs well on most emulators (Bochs, QEMU, and VirtualBox).</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
../../../www/moros.css
|
|
@ -0,0 +1 @@
|
|||
../../../www/moros.png
|
|
@ -79,7 +79,7 @@ impl<'a> smoltcp::phy::Device<'a> for EthernetDevice {
|
|||
fn capabilities(&self) -> DeviceCapabilities {
|
||||
let mut caps = DeviceCapabilities::default();
|
||||
caps.max_transmission_unit = 1500;
|
||||
caps.max_burst_size = Some(1);
|
||||
caps.max_burst_size = Some(64);
|
||||
caps
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ use crate::sys::net::{EthernetDeviceIO, Config, Stats};
|
|||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use core::convert::TryInto;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use core::hint::spin_loop;
|
||||
use core::sync::atomic::{fence, AtomicUsize, Ordering};
|
||||
use smoltcp::wire::EthernetAddress;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
|
@ -14,18 +15,18 @@ use x86_64::instructions::port::Port;
|
|||
// 11 = 64K + 16 bytes
|
||||
const RX_BUFFER_IDX: usize = 0;
|
||||
|
||||
const MTU: usize = 1500;
|
||||
const MTU: usize = 1536;
|
||||
|
||||
const RX_BUFFER_PAD: usize = 16;
|
||||
const RX_BUFFER_LEN: usize = (8129 << RX_BUFFER_IDX) + RX_BUFFER_PAD;
|
||||
const RX_BUFFER_LEN: usize = 8192 << RX_BUFFER_IDX;
|
||||
|
||||
const TX_BUFFER_LEN: usize = 4096;
|
||||
const TX_BUFFER_LEN: usize = 2048;
|
||||
const TX_BUFFERS_COUNT: usize = 4;
|
||||
const ROK: u16 = 0x01;
|
||||
|
||||
const CR_RST: u8 = 1 << 4; // Reset
|
||||
const CR_RE: u8 = 1 << 3; // Receiver Enable
|
||||
const CR_TE: u8 = 1 << 2; // Transmitter Enable
|
||||
const CR_RST: u8 = 1 << 4; // Reset
|
||||
const CR_RE: u8 = 1 << 3; // Receiver Enable
|
||||
const CR_TE: u8 = 1 << 2; // Transmitter Enable
|
||||
const CR_BUFE: u8 = 1 << 0; // Buffer Empty
|
||||
|
||||
// Rx Buffer Length
|
||||
|
@ -37,10 +38,10 @@ const RCR_RBLEN: u32 = (RX_BUFFER_IDX << 11) as u32;
|
|||
// of the buffer. So the buffer must have an additionnal 1500 bytes.
|
||||
const RCR_WRAP: u32 = 1 << 7;
|
||||
|
||||
const RCR_AB: u32 = 1 << 3; // Accept Broadcast packets
|
||||
const RCR_AM: u32 = 1 << 2; // Accept Multicast packets
|
||||
const RCR_APM: u32 = 1 << 1; // Accept Physical Match packets
|
||||
const RCR_AAP: u32 = 1 << 0; // Accept All Packets
|
||||
const RCR_AB: u32 = 1 << 3; // Accept Broadcast packets
|
||||
const RCR_AM: u32 = 1 << 2; // Accept Multicast packets
|
||||
const RCR_APM: u32 = 1 << 1; // Accept Physical Match packets
|
||||
const RCR_AAP: u32 = 1 << 0; // Accept All Packets
|
||||
|
||||
// Interframe Gap Time
|
||||
const TCR_IFG: u32 = 3 << 24;
|
||||
|
@ -78,7 +79,7 @@ pub struct Ports {
|
|||
pub config1: Port<u8>, // Configuration Register 1 (CONFIG1)
|
||||
pub rx_addr: Port<u32>, // Receive (Rx) Buffer Start Address (RBSTART)
|
||||
pub capr: Port<u16>, // Current Address of Packet Read (CAPR)
|
||||
pub cbr: Port<u16>, // Current Buffer Address (CBR)
|
||||
pub cba: Port<u16>, // Current Buffer Address (CBA)
|
||||
pub cmd: Port<u8>, // Command Register (CR)
|
||||
pub imr: Port<u16>, // Interrupt Mask Register (IMR)
|
||||
pub isr: Port<u16>, // Interrupt Status Register (ISR)
|
||||
|
@ -112,7 +113,7 @@ impl Ports {
|
|||
config1: Port::new(io_base + 0x52),
|
||||
rx_addr: Port::new(io_base + 0x30),
|
||||
capr: Port::new(io_base + 0x38),
|
||||
cbr: Port::new(io_base + 0x3A),
|
||||
cba: Port::new(io_base + 0x3A),
|
||||
cmd: Port::new(io_base + 0x37),
|
||||
imr: Port::new(io_base + 0x3C),
|
||||
isr: Port::new(io_base + 0x3E),
|
||||
|
@ -155,7 +156,7 @@ impl Device {
|
|||
ports: Ports::new(io_base),
|
||||
|
||||
// Add MTU to RX_BUFFER_LEN if RCR_WRAP is set
|
||||
rx_buffer: PhysBuf::new(RX_BUFFER_LEN + MTU),
|
||||
rx_buffer: PhysBuf::new(RX_BUFFER_LEN + RX_BUFFER_PAD + MTU),
|
||||
|
||||
rx_offset: 0,
|
||||
tx_buffers: [(); TX_BUFFERS_COUNT].map(|_| PhysBuf::new(TX_BUFFER_LEN)),
|
||||
|
@ -175,9 +176,15 @@ impl Device {
|
|||
// Software reset
|
||||
unsafe {
|
||||
self.ports.cmd.write(CR_RST);
|
||||
while self.ports.cmd.read() & CR_RST != 0 {}
|
||||
fence(Ordering::SeqCst);
|
||||
while self.ports.cmd.read() & CR_RST != 0 {
|
||||
spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
// Set interrupts
|
||||
//unsafe { self.ports.imr.write(IMR_TOK | IMR_ROK) }
|
||||
|
||||
// Enable Receive and Transmitter
|
||||
unsafe { self.ports.cmd.write(CR_RE | CR_TE) }
|
||||
|
||||
|
@ -198,14 +205,11 @@ impl Device {
|
|||
unsafe { self.ports.tx_addrs[i].write(tx_addr as u32) }
|
||||
}
|
||||
|
||||
// Set interrupts
|
||||
unsafe { self.ports.imr.write(IMR_TOK | IMR_ROK) }
|
||||
|
||||
// Configure receive buffer (RCR)
|
||||
unsafe { self.ports.rx_config.write(RCR_RBLEN | RCR_WRAP | RCR_AB | RCR_AM | RCR_APM | RCR_AAP) }
|
||||
|
||||
// Configure transmit buffer (TCR)
|
||||
unsafe { self.ports.tx_config.write(TCR_IFG | TCR_MXDMA0 | TCR_MXDMA1 | TCR_MXDMA2); }
|
||||
unsafe { self.ports.tx_config.write(TCR_IFG | TCR_MXDMA1 | TCR_MXDMA2); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,14 +234,13 @@ impl EthernetDeviceIO for Device {
|
|||
}
|
||||
|
||||
//let isr = unsafe { self.ports.isr.read() };
|
||||
let capr = unsafe { self.ports.capr.read() };
|
||||
let cbr = unsafe { self.ports.cbr.read() };
|
||||
let cba = unsafe { self.ports.cba.read() };
|
||||
// CAPR starts at 65520 and with the pad it overflows to 0
|
||||
let capr = unsafe { self.ports.capr.read() };
|
||||
let offset = ((capr as usize) + RX_BUFFER_PAD) % (1 << 16);
|
||||
|
||||
let header = u16::from_le_bytes(self.rx_buffer[(offset + 0)..(offset + 2)].try_into().unwrap());
|
||||
if header & ROK != ROK {
|
||||
unsafe { self.ports.capr.write(cbr) };
|
||||
unsafe { self.ports.capr.write((((cba as usize) % RX_BUFFER_LEN) - RX_BUFFER_PAD) as u16) };
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -247,9 +250,10 @@ impl EthernetDeviceIO for Device {
|
|||
// Update buffer read pointer
|
||||
self.rx_offset = (offset + n + 4 + 3) & !3;
|
||||
unsafe {
|
||||
self.ports.capr.write((self.rx_offset - RX_BUFFER_PAD) as u16);
|
||||
self.ports.capr.write(((self.rx_offset % RX_BUFFER_LEN) - RX_BUFFER_PAD) as u16);
|
||||
}
|
||||
|
||||
//unsafe { self.ports.isr.write(0x1); }
|
||||
Some(self.rx_buffer[(offset + 4)..(offset + n)].to_vec())
|
||||
}
|
||||
|
||||
|
@ -257,6 +261,9 @@ impl EthernetDeviceIO for Device {
|
|||
let tx_id = self.tx_id.load(Ordering::SeqCst);
|
||||
let mut cmd_port = self.ports.tx_cmds[tx_id].clone();
|
||||
unsafe {
|
||||
// RTL8139 will not transmit packets smaller than 64 bits
|
||||
let len = len.max(60); // 60 + 4 bits of CRC
|
||||
|
||||
// Fill in Transmit Status: the size of this packet, the early
|
||||
// transmit threshold, and clear OWN bit in TSD (this starts the
|
||||
// PCI operation).
|
||||
|
@ -265,12 +272,16 @@ impl EthernetDeviceIO for Device {
|
|||
// transmit threshold means 8 bytes. So we just write the size of
|
||||
// the packet.
|
||||
cmd_port.write(0x1FFF & len as u32);
|
||||
fence(Ordering::SeqCst);
|
||||
|
||||
// When the whole packet is moved to FIFO, the OWN bit is set to 1
|
||||
while cmd_port.read() & OWN != OWN {}
|
||||
// When the whole packet is moved to line, the TOK bit is set to 1
|
||||
while cmd_port.read() & TOK != TOK {}
|
||||
while cmd_port.read() & OWN != OWN {
|
||||
spin_loop();
|
||||
}
|
||||
while cmd_port.read() & TOK != TOK {
|
||||
spin_loop();
|
||||
}
|
||||
}
|
||||
//unsafe { self.ports.isr.write(0x4); }
|
||||
}
|
||||
|
||||
fn next_tx_buffer(&mut self, len: usize) -> &mut [u8] {
|
||||
|
|
|
@ -210,10 +210,11 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
|
|||
println!("{}HTTP Server listening on 0.0.0.0:{}{}", csi_color, port, csi_reset);
|
||||
|
||||
let mtu = iface.device().capabilities().max_transmission_unit;
|
||||
let buf_len = mtu - 14 - 20 - 20; // ETH+TCP+IP headers
|
||||
let mut connections = Vec::new();
|
||||
for _ in 0..MAX_CONNECTIONS {
|
||||
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
|
||||
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
|
||||
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; buf_len]);
|
||||
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; buf_len]);
|
||||
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
||||
let tcp_handle = iface.add_socket(tcp_socket);
|
||||
let send_queue: VecDeque<Vec<u8>> = VecDeque::new();
|
||||
|
@ -339,12 +340,13 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
|
|||
}
|
||||
(buffer.len(), res)
|
||||
}).unwrap();
|
||||
for chunk in res.buf.chunks(mtu) {
|
||||
for chunk in res.buf.chunks(buf_len) {
|
||||
send_queue.push_back(chunk.to_vec());
|
||||
}
|
||||
if socket.can_send() {
|
||||
if let Some(chunk) = send_queue.pop_front() {
|
||||
socket.send_slice(&chunk).unwrap();
|
||||
let sent = socket.send_slice(&chunk).expect("Could not send chunk");
|
||||
debug_assert!(sent == chunk.len());
|
||||
}
|
||||
}
|
||||
if send_queue.is_empty() && !res.is_persistent() {
|
||||
|
|
|
@ -82,8 +82,9 @@ pub fn copy_files(verbose: bool) {
|
|||
copy_file("/tmp/beep/mario.sh", include_bytes!("../../dsk/tmp/beep/mario.sh"), verbose);
|
||||
|
||||
create_dir("/var/www", verbose);
|
||||
copy_file("/var/www/index.html", include_bytes!("../../www/index.html"), verbose);
|
||||
copy_file("/var/www/moros.png", include_bytes!("../../www/moros.png"), verbose);
|
||||
copy_file("/var/www/index.html", include_bytes!("../../dsk/var/www/index.html"), verbose);
|
||||
copy_file("/var/www/moros.png", include_bytes!("../../dsk/var/www/moros.png"), verbose);
|
||||
copy_file("/var/www/moros.css", include_bytes!("../../dsk/var/www/moros.css"), verbose);
|
||||
}
|
||||
|
||||
pub fn main(args: &[&str]) -> Result<(), ExitCode> {
|
||||
|
|
|
@ -14,7 +14,7 @@ for md in ../doc/*.md; do
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>$title</title>
|
||||
<link rel="stylesheet" type="text/css" href="/moros.css">
|
||||
<link rel="stylesheet" type="text/css" href="moros.css">
|
||||
</head>
|
||||
<body>
|
||||
EOF
|
||||
|
|
Loading…
Reference in New Issue