Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## Unreleased
- Allow running test in debug mode (#915)
- Use usize milliseconds instead of float seconds for sleep (#916)
- Enable process, syscall, and file system on i686 (#914)
- Add sys::x86::addr module (#912)
Expand Down
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,15 @@ endif
qemu:
$(qemu) $(qemu-opts)

test-opts = --lib
ifeq ($(mode),release)
test-opts += --release
endif

test:
cargo test --release --lib --no-default-features --features serial -- \
cargo test $(test-opts) --no-default-features --features serial -- \
-m $(memory) -cpu $(cpu) -display none -serial stdio \
-device isa-debug-exit,iobase=0xF4,iosize=0x04
-device isa-debug-exit,iobase=0xF4,iosize=0x04 -device $(nic)

limine-version = 11.3.1
limine-url = https://github.com/Limine-Bootloader/Limine/releases/download/v$(limine-version)/limine-$(limine-version).tar.gz
Expand Down Expand Up @@ -172,9 +177,9 @@ limine-image:
limine-test: RUSTFLAGS = -C link-arg=-Trun/boot/multiboot.ld -C link-arg=-z -C link-arg=norelro
limine-test: LIMINE_DIR = $(limine-dir)
limine-test:
cargo test --release --lib --no-default-features --features serial,multiboot --target i686-moros.json -- \
cargo test $(test-opts) --no-default-features --features serial,multiboot --target i686-moros.json -- \
-m $(memory) -cpu pentium3 -display none -serial stdio \
-device isa-debug-exit,iobase=0xF4,iosize=0x04
-device isa-debug-exit,iobase=0xF4,iosize=0x04 -device $(nic)

grub-dir = /usr/lib/grub/i386-pc
grub-modules = multiboot2 $(shell cat $(grub-dir)/partmap.lst)
Expand Down
10 changes: 6 additions & 4 deletions src/sys/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,12 @@ pub fn init() {
}
for id in E1000_DEVICES {
if let Some(dev) = find_device(0x8086, id) {
let io = dev.bar_io(0);
let mem = dev.mem_base();
let bar = dev.bar_type();
let nic = nic::e1000::Device::new(io, mem, bar);
let base = if dev.is_io() {
nic::e1000::Base::IO(dev.bar_io(0))
} else {
nic::e1000::Base::Mem(dev.mem_base())
};
let nic = nic::e1000::Device::new(base);
add(EthernetDevice::E1000(nic), "E1000");
}
}
Expand Down
95 changes: 46 additions & 49 deletions src/sys/net/nic/e1000.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::sys::net::{EthernetDeviceIO, Config, Stats};
use crate::sys::x86::addr::PhysAddr;
use crate::sys::x86::port::*;

use alloc::slice;
use alloc::sync::Arc;
use alloc::vec::Vec;
use bit_field::BitField;
Expand All @@ -18,7 +17,7 @@ use spin::Mutex;
// Registers
const REG_CTRL: u16 = 0x0000; // Device Control Register
const REG_STATUS: u16 = 0x0008; // Device Status Register
const REG_EECD: u16 = 0x0014; // EEPROM/Flash Control & Data Register
const REG_EERD: u16 = 0x0014; // EEPROM Read Register
const REG_ICR: u16 = 0x00C0; // Interrupt Cause Read Register
const REG_IMS: u16 = 0x00D0; // Interrupt Mask Set/Read Register
const REG_IMC: u16 = 0x00D8; // Interrupt Mask Clear Register
Expand All @@ -35,6 +34,8 @@ const REG_TDBAH: u16 = 0x3804; // Transmit Descriptor Base Address High
const REG_TDLEN: u16 = 0x3808; // Transmit Descriptor Length
const REG_TDH: u16 = 0x3810; // Transmit Descriptor Head
const REG_TDT: u16 = 0x3818; // Transmit Descriptor Tail
const REG_RAL: u16 = 0x5400; // Receive Address Low
const REG_RAH: u16 = 0x5404; // Receive Address High
const REG_MTA: u16 = 0x5200; // Multicast Table Array

const CTRL_LRST: u32 = 1 << 3; // Link Reset
Expand Down Expand Up @@ -118,11 +119,15 @@ struct TxDesc {
special: u16,
}

#[derive(Clone)]
pub enum Base {
IO(u16),
Mem(PhysAddr),
}

#[derive(Clone)]
pub struct Device {
mem_base: PhysAddr,
io_base: u16,
bar_type: u16,
base: Base,
has_eeprom: bool,
config: Arc<Config>,
stats: Arc<Stats>,
Expand All @@ -135,14 +140,12 @@ pub struct Device {
}

impl Device {
pub fn new(io_base: u16, mem_base: PhysAddr, bar_type: u16) -> Self {
pub fn new(base: Base) -> Self {
const RX: usize = RX_BUFFERS_COUNT;
const TX: usize = TX_BUFFERS_COUNT;

let mut device = Self {
bar_type: bar_type,
io_base: io_base,
mem_base: mem_base,
base,
has_eeprom: false,
config: Arc::new(Config::new()),
stats: Arc::new(Stats::new()),
Expand Down Expand Up @@ -263,28 +266,14 @@ impl Device {
fn read_mac(&self) -> EthernetAddress {
let mut mac = [0; 6];
if self.has_eeprom {
let mut tmp;
tmp = self.read_eeprom(0);
mac[0] = (tmp &0xff) as u8;
mac[1] = (tmp >> 8) as u8;
tmp = self.read_eeprom(1);
mac[2] = (tmp &0xff) as u8;
mac[3] = (tmp >> 8) as u8;
tmp = self.read_eeprom(2);
mac[4] = (tmp &0xff) as u8;
mac[5] = (tmp >> 8) as u8;
mac[0..2].copy_from_slice(&self.read_eeprom(0).to_le_bytes());
mac[2..4].copy_from_slice(&self.read_eeprom(1).to_le_bytes());
mac[4..6].copy_from_slice(&self.read_eeprom(2).to_le_bytes());
} else {
unsafe {
let phys = self.mem_base + 0x5400;
let addr = sys::mem::phys_to_virt(phys).as_usize();
let mac_32 = core::ptr::read_volatile(addr as *const u32);
if mac_32 != 0 {
let mac_8 = slice::from_raw_parts(addr as *const u8, 6);
mac[..].clone_from_slice(mac_8);
}
}
mac[0..4].copy_from_slice(&self.read(REG_RAL).to_le_bytes());
mac[4..6].copy_from_slice(&self.read(REG_RAH).to_le_bytes()[0..2]);
}
EthernetAddress::from_bytes(&mac[..])
EthernetAddress::from_bytes(&mac)
}

fn link_up(&self) {
Expand All @@ -294,47 +283,55 @@ impl Device {

fn write(&self, addr: u16, data: u32) {
unsafe {
if self.bar_type == 0 {
let phys = self.mem_base + addr as usize;
let addr = sys::mem::phys_to_virt(phys).as_usize() as *mut u32;
core::ptr::write_volatile(addr, data);
} else {
outl(self.io_base + IO_ADDR, addr as u32);
outl(self.io_base + IO_DATA, data);
match self.base {
Base::Mem(mem_base) => {
let phys = mem_base + addr as usize;
let virt = sys::mem::phys_to_virt(phys);
let ptr = virt.as_mut_ptr::<u32>();
core::ptr::write_volatile(ptr, data);
}
Base::IO(io_base) => {
outl(io_base + IO_ADDR, addr as u32);
outl(io_base + IO_DATA, data);
}
}
}
}

fn read(&self, addr: u16) -> u32 {
unsafe {
if self.bar_type == 0 {
let phys = self.mem_base + addr as usize;
let addr = sys::mem::phys_to_virt(phys).as_usize() as *mut u32;
core::ptr::read_volatile(addr)
} else {
outl(self.io_base + IO_ADDR, addr as u32);
inl(self.io_base + IO_DATA)
match self.base {
Base::Mem(mem_base) => {
let phys = mem_base + addr as usize;
let virt = sys::mem::phys_to_virt(phys);
let ptr = virt.as_ptr::<u32>();
core::ptr::read_volatile(ptr)
}
Base::IO(io_base) => {
outl(io_base + IO_ADDR, addr as u32);
inl(io_base + IO_DATA)
}
}
}
}

fn detect_eeprom(&mut self) {
self.write(REG_EECD, 1);
self.write(REG_EERD, 1);
let mut i = 0;
while !self.has_eeprom && i < 1000 {
self.has_eeprom = self.read(REG_EECD) & 0x10 > 0;
self.has_eeprom = self.read(REG_EERD) & 0x10 > 0;
i += 1;
}
}

fn read_eeprom(&self, addr: u16) -> u32 {
fn read_eeprom(&self, addr: u16) -> u16 {
let e = if self.has_eeprom { 4 } else { 0 };
self.write(REG_EECD, 1 | ((addr as u32) << (2 * e)));
self.write(REG_EERD, 1 | ((addr as u32) << (2 * e)));
let mut res = 0;
while res & (1 << e) == 0 {
res = self.read(REG_EECD);
res = self.read(REG_EERD);
}
(res >> 16) & 0xFFFF
(res >> 16) as u16
}

#[allow(dead_code)]
Expand Down
16 changes: 8 additions & 8 deletions src/sys/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,17 @@ impl DeviceConfig {
self.command = register.read() as u16;
}

pub fn bar_type(&self) -> u16 {
self.base_addresses[0].get_bits(1..3) as u16
pub fn is_io(&self) -> bool {
self.base_addresses[0].get_bit(0)
}

pub fn bar_io(&self, n: usize) -> u16 {
debug_assert!(self.is_io());
(self.base_addresses[n] as u16) & 0xFFFC
}

pub fn mem_base(&self) -> PhysAddr {
debug_assert!(self.base_addresses[0].get_bit(0) == false);
debug_assert!(!self.is_io());
let bar0 = self.base_addresses[0];
let bar1 = self.base_addresses[1];
let addr = match bar0.get_bits(1..3) {
Expand All @@ -126,11 +131,6 @@ impl DeviceConfig {
};
PhysAddr::new(addr as usize)
}

pub fn bar_io(&self, n: usize) -> u16 {
debug_assert!(self.base_addresses[n].get_bit(0) == true);
(self.base_addresses[n] as u16) & 0xFFF0
}
}

lazy_static! {
Expand Down
1 change: 0 additions & 1 deletion src/sys/vga/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use bit_field::BitField;
use core::cmp;
use core::fmt;
use core::fmt::Write;
use core::num::ParseIntError;

const ATTR_ADDR_REG: u16 = 0x3C0;
const ATTR_WRITE_REG: u16 = 0x3C0;
Expand Down
23 changes: 12 additions & 11 deletions src/sys/vga/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,22 +549,23 @@ impl fmt::Write for Writer {
}
}

fn parse_palette(palette: &str) -> Result<(usize, u8, u8, u8), ParseIntError> {
debug_assert!(palette.len() == 8);
debug_assert!(palette.starts_with('P'));
fn parse_palette(palette: &str) -> Result<(usize, u8, u8, u8), ()> {
if palette.len() != 8 || !palette.starts_with('P') {
return Err(());
}

let i = usize::from_str_radix(&palette[1..2], 16)?;
let r = u8::from_str_radix(&palette[2..4], 16)?;
let g = u8::from_str_radix(&palette[4..6], 16)?;
let b = u8::from_str_radix(&palette[6..8], 16)?;
let i = usize::from_str_radix(&palette[1..2], 16).map_err(|_| ())?;
let r = u8::from_str_radix(&palette[2..4], 16).map_err(|_| ())?;
let g = u8::from_str_radix(&palette[4..6], 16).map_err(|_| ())?;
let b = u8::from_str_radix(&palette[6..8], 16).map_err(|_| ())?;

Ok((i, r, g, b))
}

#[test_case]
fn test_parse_palette() {
assert_eq!(parse_palette("P0282828"), Ok((0, 0x28, 0x28, 0x28)));
assert_eq!(parse_palette("P4CC241D"), Ok((4, 0xCC, 0x24, 0x1D)));
assert!(parse_palette("BAAAAAAD").is_ok());
assert!(parse_palette("GOOOOOOD").is_err());
assert_eq!(parse_palette("P0282828"), Ok((0x0, 0x28, 0x28, 0x28)));
assert_eq!(parse_palette("PADDDDED"), Ok((0xA, 0xDD, 0xDD, 0xED)));
assert_eq!(parse_palette("BAAAAAAD"), Err(()));
assert_eq!(parse_palette("BAD"), Err(()));
}