Skip to content

Commit

Permalink
x86: crate finally builds with x86 and x86_64 (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
phip1611 authored Aug 4, 2023
1 parent e1ee971 commit d60387b
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 43 deletions.
19 changes: 16 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,25 @@ jobs:
rustc -Vv
cargo -Vv
- name: "Run cargo build"
run: cargo build
- name: "Run cargo build (x86) [nightly]"
run: |
rustup toolchain add nightly-2023-07-09
rustup component add rust-src --toolchain nightly-2023-07-09
cargo +nightly-2023-07-09 build --target test/x86-unknown-none.json -Z build-std=core,alloc,compiler_builtins -Z build-std-features=compiler-builtins-mem
- name: "Run cargo build (x86_64)"
run: |
rustup target add x86_64-unknown-none
cargo build --target x86_64-unknown-none
- name: "Run cargo build (aarch64)"
run: |
rustup target add aarch64-unknown-none
cargo build --target aarch64-unknown-none
- name: "Run cargo test"
run: cargo test

- name: "Run cargo build for stable"
run: cargo build --no-default-features --features stable
if: runner.os != 'Windows'
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ edition = "2018"
bitflags = "1.1.0"
rustversion = "1.0.5"

[target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = { version = "0.14.9", default-features = false, features = ["instructions"] }
[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
x86 = "0.52"

[features]
default = []
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Build Status](https://github.com/rust-osdev/uart_16550/workflows/Build/badge.svg)](https://github.com/rust-osdev/uart_16550/actions?query=workflow%3ABuild) [![Docs.rs Badge](https://docs.rs/uart_16550/badge.svg)](https://docs.rs/uart_16550/)

Minimal support for [serial communication](https://en.wikipedia.org/wiki/Asynchronous_serial_communication) through [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter) devices, which are compatible to the [16550 UART](https://en.wikipedia.org/wiki/16550_UART). This crate supports port-mapped and memory mapped UARTS.
Minimal support for [serial communication](https://en.wikipedia.org/wiki/Asynchronous_serial_communication) through [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter) devices, which are compatible to the [16550 UART](https://en.wikipedia.org/wiki/16550_UART). This crate supports I/O port-mapped (x86 only) and memory-mapped UARTS.

## Usage

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! through [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter)
//! devices, which are compatible to the [16550 UART](https://en.wikipedia.org/wiki/16550_UART).
//!
//! This crate supports port-mapped and memory mapped UARTS.
//! This crate supports I/O port-mapped (x86 only) and memory-mapped UARTS.
//!
//! ## Usage
//!
Expand Down
1 change: 1 addition & 0 deletions src/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use core::{
use crate::LineStsFlags;

/// A memory-mapped UART.
#[derive(Debug)]
pub struct MmioSerialPort {
data: AtomicPtr<u8>,
int_en: AtomicPtr<u8>,
Expand Down
105 changes: 69 additions & 36 deletions src/port.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,67 @@
use core::fmt;

use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};

use crate::LineStsFlags;

/// A port-mapped UART.
/// A x86 I/O port-mapped UART.
#[cfg_attr(docsrs, doc(cfg(any(target_arch = "x86", target_arch = "x86_64"))))]
pub struct SerialPort {
data: Port<u8>,
int_en: PortWriteOnly<u8>,
fifo_ctrl: PortWriteOnly<u8>,
line_ctrl: PortWriteOnly<u8>,
modem_ctrl: PortWriteOnly<u8>,
line_sts: PortReadOnly<u8>,
}
#[derive(Debug)]
pub struct SerialPort(u16 /* base port */);

impl SerialPort {
/// Creates a new serial port interface on the given I/O port.
/// Base port.
fn port_base(&self) -> u16 {
self.0
}

/// Data port.
///
/// Read and write.
fn port_data(&self) -> u16 {
self.port_base()
}

/// Interrupt enable port.
///
/// Write only.
fn port_int_en(&self) -> u16 {
self.port_base() + 1
}

/// Fifo control port.
///
/// Write only.
fn port_fifo_ctrl(&self) -> u16 {
self.port_base() + 2
}

/// Line control port.
///
/// Write only.
fn port_line_ctrl(&self) -> u16 {
self.port_base() + 3
}

/// Modem control port.
///
/// Write only.
fn port_modem_ctrl(&self) -> u16 {
self.port_base() + 4
}

/// Line status port.
///
/// Read only.
fn port_line_sts(&self) -> u16 {
self.port_base() + 5
}

/// Creates a new serial port interface on the given I/O base port.
///
/// This function is unsafe because the caller must ensure that the given base address
/// really points to a serial port device.
/// really points to a serial port device and that the caller has the necessary rights
/// to perform the I/O operation.
pub const unsafe fn new(base: u16) -> Self {
Self {
data: Port::new(base),
int_en: PortWriteOnly::new(base + 1),
fifo_ctrl: PortWriteOnly::new(base + 2),
line_ctrl: PortWriteOnly::new(base + 3),
modem_ctrl: PortWriteOnly::new(base + 4),
line_sts: PortReadOnly::new(base + 5),
}
Self(base)
}

/// Initializes the serial port.
Expand All @@ -37,33 +70,33 @@ impl SerialPort {
pub fn init(&mut self) {
unsafe {
// Disable interrupts
self.int_en.write(0x00);
x86::io::outb(self.port_int_en(), 0x00);

// Enable DLAB
self.line_ctrl.write(0x80);
x86::io::outb(self.port_line_ctrl(), 0x80);

// Set maximum speed to 38400 bps by configuring DLL and DLM
self.data.write(0x03);
self.int_en.write(0x00);
x86::io::outb(self.port_data(), 0x03);
x86::io::outb(self.port_int_en(), 0x00);

// Disable DLAB and set data word length to 8 bits
self.line_ctrl.write(0x03);
x86::io::outb(self.port_line_ctrl(), 0x03);

// Enable FIFO, clear TX/RX queues and
// set interrupt watermark at 14 bytes
self.fifo_ctrl.write(0xC7);
x86::io::outb(self.port_fifo_ctrl(), 0xc7);

// Mark data terminal ready, signal request to send
// and enable auxilliary output #2 (used as interrupt line for CPU)
self.modem_ctrl.write(0x0B);
x86::io::outb(self.port_modem_ctrl(), 0x0b);

// Enable interrupts
self.int_en.write(0x01);
x86::io::outb(self.port_int_en(), 0x01);
}
}

fn line_sts(&mut self) -> LineStsFlags {
unsafe { LineStsFlags::from_bits_truncate(self.line_sts.read()) }
unsafe { LineStsFlags::from_bits_truncate(x86::io::inb(self.port_line_sts())) }
}

/// Sends a byte on the serial port.
Expand All @@ -72,15 +105,15 @@ impl SerialPort {
match data {
8 | 0x7F => {
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
self.data.write(8);
x86::io::outb(self.port_data(), 8);
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
self.data.write(b' ');
x86::io::outb(self.port_data(), b' ');
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
self.data.write(8)
x86::io::outb(self.port_data(), 8);
}
_ => {
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
self.data.write(data);
x86::io::outb(self.port_data(), data);
}
}
}
Expand All @@ -90,15 +123,15 @@ impl SerialPort {
pub fn send_raw(&mut self, data: u8) {
unsafe {
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
self.data.write(data);
x86::io::outb(self.port_data(), data);
}
}

/// Receives a byte on the serial port.
pub fn receive(&mut self) -> u8 {
unsafe {
wait_for!(self.line_sts().contains(LineStsFlags::INPUT_FULL));
self.data.read()
x86::io::inb(self.port_data())
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions test/x86-unknown-none.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"llvm-target": "i686-unknown-none",
"data-layout": "e-m:e-i32:32-f80:128-n8:16:32-S128-p:32:32",
"arch": "x86",
"target-endian": "little",
"target-pointer-width": "32",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"panic-strategy": "abort",
"disable-redzone": true,
"relocation-model": "static",
"features": "+soft-float,-x87,-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-fma,-3dnow,-3dnowa"
}

0 comments on commit d60387b

Please sign in to comment.