Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix RTL8139 driver issues #483

Merged
merged 13 commits into from
May 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
18 changes: 18 additions & 0 deletions dsk/var/www/index.html
Original file line number Diff line number Diff line change
@@ -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>
1 change: 1 addition & 0 deletions dsk/var/www/moros.css
1 change: 1 addition & 0 deletions dsk/var/www/moros.png
2 changes: 1 addition & 1 deletion src/sys/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
69 changes: 40 additions & 29 deletions src/sys/net/rtl8139.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)),
Expand All @@ -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) }

Expand All @@ -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); }
}
}

Expand All @@ -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;
}

Expand All @@ -247,16 +250,20 @@ 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())
}

fn transmit_packet(&mut self, len: usize) {
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).
Expand All @@ -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);

// 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 {}
fence(Ordering::SeqCst);

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] {
Expand Down
10 changes: 6 additions & 4 deletions src/usr/httpd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down
5 changes: 3 additions & 2 deletions src/usr/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
2 changes: 1 addition & 1 deletion www/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down