mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Refactor IoPort
This commit is contained in:
parent
ebfb199512
commit
8c7b5d84d1
@ -1,60 +1,55 @@
|
|||||||
use spin::Mutex;
|
use core::marker::PhantomData;
|
||||||
use x86_64::{
|
|
||||||
instructions::port::Port,
|
pub use x86_64::instructions::port::{
|
||||||
structures::port::{PortRead, PortWrite},
|
PortReadAccess as IoPortReadAccess, PortWriteAccess as IoPortWriteAccess, ReadOnlyAccess,
|
||||||
|
ReadWriteAccess, WriteOnlyAccess,
|
||||||
};
|
};
|
||||||
|
pub use x86_64::structures::port::{PortRead, PortWrite};
|
||||||
|
|
||||||
/// An I/O port, representing a specific address in the I/O address of x86.
|
/// An I/O port, representing a specific address in the I/O address of x86.
|
||||||
///
|
///
|
||||||
/// The following code shows and example to read and write u32 value to an I/O port:
|
/// The following code shows and example to read and write u32 value to an I/O port:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// static PORT: IoPort<u32> = IoPort::new(0x12);
|
/// static PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x12) };
|
||||||
///
|
///
|
||||||
/// fn port_value_increase(){
|
/// fn port_value_increase(){
|
||||||
/// PORT.write(PORT.read() + 1)
|
/// PORT.write(PORT.read() + 1)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
pub struct IoPort<T> {
|
pub struct IoPort<T, A> {
|
||||||
addr: u16,
|
port: u16,
|
||||||
port: Mutex<Port<T>>,
|
value_marker: PhantomData<T>,
|
||||||
|
access_marker: PhantomData<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IoPort<T> {
|
impl<T, A> IoPort<T, A> {
|
||||||
/// Create an I/O port.
|
/// Create an I/O port.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This function is marked unsafe as creating an I/O port is considered
|
/// This function is marked unsafe as creating an I/O port is considered
|
||||||
/// a privileged operation.
|
/// a privileged operation.
|
||||||
pub const unsafe fn new(addr: u16) -> Self {
|
pub const unsafe fn new(port: u16) -> Self {
|
||||||
Self {
|
Self {
|
||||||
addr,
|
port: port,
|
||||||
port: Mutex::new(Port::new(addr)),
|
value_marker: PhantomData,
|
||||||
|
access_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IoPort<T> {
|
impl<T: PortRead, A: IoPortReadAccess> IoPort<T, A> {
|
||||||
/// Get the address of this I/O port.
|
#[inline]
|
||||||
pub fn addr(&self) -> u16 {
|
|
||||||
self.addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PortRead> IoPort<T> {
|
|
||||||
/// Reads from the port.
|
|
||||||
pub fn read(&self) -> T {
|
pub fn read(&self) -> T {
|
||||||
unsafe { (*self.port.lock()).read() }
|
unsafe { PortRead::read_from_port(self.port) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PortWrite> IoPort<T> {
|
impl<T: PortWrite, A: IoPortWriteAccess> IoPort<T, A> {
|
||||||
/// Writes to the port.
|
#[inline]
|
||||||
pub fn write(&self, val: T) {
|
pub fn write(&self, value: T) {
|
||||||
unsafe {
|
unsafe { PortWrite::write_to_port(self.port, value) }
|
||||||
self.port.lock().write(val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
//! Device-related APIs.
|
//! Device-related APIs.
|
||||||
pub mod framebuffer;
|
|
||||||
|
|
||||||
mod io_port;
|
pub mod framebuffer;
|
||||||
|
pub mod io_port;
|
||||||
pub mod pci;
|
pub mod pci;
|
||||||
pub mod serial;
|
pub mod serial;
|
||||||
|
|
||||||
pub use self::io_port::IoPort;
|
|
||||||
|
|
||||||
/// Call after the memory allocator init
|
/// Call after the memory allocator init
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
framebuffer::init();
|
framebuffer::init();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! PCI bus io port
|
//! PCI bus io port
|
||||||
|
|
||||||
use super::io_port::IoPort;
|
use super::io_port::IoPort;
|
||||||
|
use super::io_port::{ReadWriteAccess, WriteOnlyAccess};
|
||||||
|
|
||||||
pub static PCI_ADDRESS_PORT: IoPort<u32> = unsafe { IoPort::new(0x0CF8) };
|
pub static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
|
||||||
pub static PCI_DATA_PORT: IoPort<u32> = unsafe { IoPort::new(0x0CFC) };
|
pub static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
//! A port-mapped UART. Copied from uart_16550.
|
//! A port-mapped UART. Copied from uart_16550.
|
||||||
|
|
||||||
|
use super::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
|
use core::fmt::{self, Write};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use spin::{Mutex, Once};
|
use spin::{Mutex, Once};
|
||||||
use trapframe::TrapFrame;
|
|
||||||
use x86_64::instructions::port::{Port, PortWriteOnly};
|
|
||||||
|
|
||||||
use crate::{driver::pic_allocate_irq, trap::IrqAllocateHandle};
|
use crate::{driver::pic_allocate_irq, trap::IrqAllocateHandle};
|
||||||
use core::fmt::{self, Write};
|
use trapframe::TrapFrame;
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
struct LineSts: u8 {
|
struct LineSts: u8 {
|
||||||
@ -17,16 +18,13 @@ bitflags::bitflags! {
|
|||||||
|
|
||||||
const SERIAL_DATA_PORT: u16 = 0x3F8;
|
const SERIAL_DATA_PORT: u16 = 0x3F8;
|
||||||
|
|
||||||
static SERIAL_DATA: Mutex<Port<u8>> = Mutex::new(Port::new(SERIAL_DATA_PORT));
|
static SERIAL_DATA: IoPort<u8, ReadWriteAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT) };
|
||||||
static SERIAL_INT_EN: Mutex<PortWriteOnly<u8>> =
|
static SERIAL_INT_EN: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT + 1) };
|
||||||
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 1));
|
static SERIAL_FIFO_CTRL: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT + 2) };
|
||||||
static SERIAL_FIFO_CTRL: Mutex<PortWriteOnly<u8>> =
|
static SERIAL_LINE_CTRL: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT + 3) };
|
||||||
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 2));
|
static SERIAL_MODEM_CTRL: IoPort<u8, WriteOnlyAccess> =
|
||||||
static SERIAL_LINE_CTRL: Mutex<PortWriteOnly<u8>> =
|
unsafe { IoPort::new(SERIAL_DATA_PORT + 4) };
|
||||||
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 3));
|
static SERIAL_LINE_STS: IoPort<u8, ReadWriteAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT + 5) };
|
||||||
static SERIAL_MODEM_CTRL: Mutex<PortWriteOnly<u8>> =
|
|
||||||
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 4));
|
|
||||||
static SERIAL_LINE_STS: Mutex<Port<u8>> = Mutex::new(Port::new(SERIAL_DATA_PORT + 5));
|
|
||||||
|
|
||||||
static CONSOLE_IRQ_CALLBACK: Once<Mutex<IrqAllocateHandle>> = Once::new();
|
static CONSOLE_IRQ_CALLBACK: Once<Mutex<IrqAllocateHandle>> = Once::new();
|
||||||
static SERIAL_INPUT_CALLBACKS: Mutex<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>>> =
|
static SERIAL_INPUT_CALLBACKS: Mutex<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>>> =
|
||||||
@ -34,30 +32,23 @@ static SERIAL_INPUT_CALLBACKS: Mutex<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>
|
|||||||
|
|
||||||
/// Initializes the serial port.
|
/// Initializes the serial port.
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
let mut serial_line_ctrl_lock = SERIAL_LINE_CTRL.lock();
|
// Disable interrupts
|
||||||
let mut serial_int_en_lock = SERIAL_INT_EN.lock();
|
SERIAL_INT_EN.write(0x00);
|
||||||
let mut serial_data_lock = SERIAL_DATA.lock();
|
// Enable DLAB
|
||||||
let mut serial_fifo_ctrl_lock = SERIAL_FIFO_CTRL.lock();
|
SERIAL_LINE_CTRL.write(0x80);
|
||||||
let mut serial_modem_ctrl_lock = SERIAL_MODEM_CTRL.lock();
|
// Set maximum speed to 38400 bps by configuring DLL and DLM
|
||||||
unsafe {
|
SERIAL_DATA.write(0x03);
|
||||||
// Disable interrupts
|
SERIAL_INT_EN.write(0x00);
|
||||||
serial_int_en_lock.write(0x00);
|
// Disable DLAB and set data word length to 8 bits
|
||||||
// Enable DLAB
|
SERIAL_LINE_CTRL.write(0x03);
|
||||||
serial_line_ctrl_lock.write(0x80);
|
// Enable FIFO, clear TX/RX queues and
|
||||||
// Set maximum speed to 38400 bps by configuring DLL and DLM
|
// set interrupt watermark at 14 bytes
|
||||||
serial_data_lock.write(0x03);
|
SERIAL_FIFO_CTRL.write(0xC7);
|
||||||
serial_int_en_lock.write(0x00);
|
// Mark data terminal ready, signal request to send
|
||||||
// Disable DLAB and set data word length to 8 bits
|
// and enable auxilliary output #2 (used as interrupt line for CPU)
|
||||||
serial_line_ctrl_lock.write(0x03);
|
SERIAL_MODEM_CTRL.write(0x0B);
|
||||||
// Enable FIFO, clear TX/RX queues and
|
// Enable interrupts
|
||||||
// set interrupt watermark at 14 bytes
|
SERIAL_INT_EN.write(0x01);
|
||||||
serial_fifo_ctrl_lock.write(0xC7);
|
|
||||||
// Mark data terminal ready, signal request to send
|
|
||||||
// and enable auxilliary output #2 (used as interrupt line for CPU)
|
|
||||||
serial_modem_ctrl_lock.write(0x0B);
|
|
||||||
// Enable interrupts
|
|
||||||
serial_int_en_lock.write(0x01);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_serial_input_callback(f: impl Fn(u8) + Send + Sync + 'static) {
|
pub fn register_serial_input_callback(f: impl Fn(u8) + Send + Sync + 'static) {
|
||||||
@ -95,26 +86,23 @@ fn handle_serial_input(trap_frame: &TrapFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn line_sts() -> LineSts {
|
fn line_sts() -> LineSts {
|
||||||
LineSts::from_bits_truncate(unsafe { SERIAL_LINE_STS.lock().read() })
|
LineSts::from_bits_truncate(SERIAL_LINE_STS.read())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a byte on the serial port.
|
/// Sends a byte on the serial port.
|
||||||
pub fn send(data: u8) {
|
pub fn send(data: u8) {
|
||||||
let mut lock = SERIAL_DATA.lock();
|
match data {
|
||||||
unsafe {
|
8 | 0x7F => {
|
||||||
match data {
|
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
||||||
8 | 0x7F => {
|
SERIAL_DATA.write(8);
|
||||||
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
||||||
lock.write(8);
|
SERIAL_DATA.write(b' ');
|
||||||
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
||||||
lock.write(b' ');
|
SERIAL_DATA.write(8);
|
||||||
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
}
|
||||||
lock.write(8);
|
_ => {
|
||||||
}
|
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
||||||
_ => {
|
SERIAL_DATA.write(data);
|
||||||
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
|
|
||||||
lock.write(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +110,7 @@ pub fn send(data: u8) {
|
|||||||
/// Receives a byte on the serial port. non-blocking
|
/// Receives a byte on the serial port. non-blocking
|
||||||
pub fn receive_char() -> Option<u8> {
|
pub fn receive_char() -> Option<u8> {
|
||||||
if line_sts().contains(LineSts::INPUT_FULL) {
|
if line_sts().contains(LineSts::INPUT_FULL) {
|
||||||
unsafe { Some(SERIAL_DATA.lock().read()) }
|
Some(SERIAL_DATA.read())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
use crate::device::io_port::{IoPort, WriteOnlyAccess};
|
||||||
use crate::trap::allocate_target_irq;
|
use crate::trap::allocate_target_irq;
|
||||||
use crate::trap::IrqAllocateHandle;
|
use crate::trap::IrqAllocateHandle;
|
||||||
|
|
||||||
use core::sync::atomic::Ordering::Relaxed;
|
use core::sync::atomic::Ordering::Relaxed;
|
||||||
use core::sync::atomic::{AtomicBool, AtomicU8};
|
use core::sync::atomic::{AtomicBool, AtomicU8};
|
||||||
|
|
||||||
static MASTER_CMD: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x20));
|
static MASTER_CMD: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0x20) };
|
||||||
static MASTER_DATA: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x21));
|
static MASTER_DATA: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0x21) };
|
||||||
static SLAVE_CMD: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0xA0));
|
static SLAVE_CMD: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0xA0) };
|
||||||
static SLAVE_DATA: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0xA1));
|
static SLAVE_DATA: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0xA1) };
|
||||||
|
|
||||||
const IRQ_OFFSET: u8 = 0x20;
|
const IRQ_OFFSET: u8 = 0x20;
|
||||||
|
|
||||||
@ -16,7 +18,6 @@ use alloc::vec::Vec;
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::info;
|
use log::info;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::instructions::port::PortWriteOnly;
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// store the irq, although we have APIC for manage interrupts
|
/// store the irq, although we have APIC for manage interrupts
|
||||||
@ -98,36 +99,30 @@ pub(crate) fn disable_temp() {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) unsafe fn set_mask(master_mask: u8, slave_mask: u8) {
|
pub(crate) unsafe fn set_mask(master_mask: u8, slave_mask: u8) {
|
||||||
let mut master_data_lock = MASTER_DATA.lock();
|
// Start initialization
|
||||||
let mut slave_data_lock = SLAVE_DATA.lock();
|
MASTER_CMD.write(0x11);
|
||||||
unsafe {
|
SLAVE_CMD.write(0x11);
|
||||||
// Start initialization
|
|
||||||
MASTER_CMD.lock().write(0x11);
|
|
||||||
SLAVE_CMD.lock().write(0x11);
|
|
||||||
|
|
||||||
// Set offsets
|
// Set offsets
|
||||||
// map master PIC vector 0x00~0x07 to 0x20~0x27 IRQ number
|
// map master PIC vector 0x00~0x07 to 0x20~0x27 IRQ number
|
||||||
master_data_lock.write(IRQ_OFFSET);
|
MASTER_DATA.write(IRQ_OFFSET);
|
||||||
// map slave PIC vector 0x00~0x07 to 0x28~0x2f IRQ number
|
// map slave PIC vector 0x00~0x07 to 0x28~0x2f IRQ number
|
||||||
slave_data_lock.write(IRQ_OFFSET + 0x08);
|
SLAVE_DATA.write(IRQ_OFFSET + 0x08);
|
||||||
|
|
||||||
// Set up cascade, there is slave at IRQ2
|
// Set up cascade, there is slave at IRQ2
|
||||||
master_data_lock.write(4);
|
MASTER_DATA.write(4);
|
||||||
slave_data_lock.write(2);
|
SLAVE_DATA.write(2);
|
||||||
|
|
||||||
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
||||||
master_data_lock.write(1);
|
MASTER_DATA.write(1);
|
||||||
slave_data_lock.write(1);
|
SLAVE_DATA.write(1);
|
||||||
|
|
||||||
// mask interrupts
|
// mask interrupts
|
||||||
master_data_lock.write(master_mask);
|
MASTER_DATA.write(master_mask);
|
||||||
slave_data_lock.write(slave_mask);
|
SLAVE_DATA.write(slave_mask);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ack() {
|
pub(crate) fn ack() {
|
||||||
unsafe {
|
MASTER_CMD.write(0x20);
|
||||||
MASTER_CMD.lock().write(0x20);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,19 @@ use core::sync::atomic::AtomicU8;
|
|||||||
use core::sync::atomic::Ordering::Relaxed;
|
use core::sync::atomic::Ordering::Relaxed;
|
||||||
|
|
||||||
use acpi::{fadt::Fadt, sdt::Signature};
|
use acpi::{fadt::Fadt, sdt::Signature};
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::instructions::port::{PortReadOnly, PortWriteOnly};
|
|
||||||
|
|
||||||
|
use crate::device::io_port::{IoPort, ReadOnlyAccess, WriteOnlyAccess};
|
||||||
use crate::time::Time;
|
use crate::time::Time;
|
||||||
|
|
||||||
use super::acpi::ACPI_TABLES;
|
use super::acpi::ACPI_TABLES;
|
||||||
|
|
||||||
static CMOS_ADDRESS: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x70));
|
static CMOS_ADDRESS: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0x70) };
|
||||||
static CMOS_DATA: Mutex<PortReadOnly<u8>> = Mutex::new(PortReadOnly::new(0x71));
|
static CMOS_DATA: IoPort<u8, ReadOnlyAccess> = unsafe { IoPort::new(0x71) };
|
||||||
|
|
||||||
pub(crate) static CENTURY_REGISTER: AtomicU8 = AtomicU8::new(0);
|
pub(crate) static CENTURY_REGISTER: AtomicU8 = AtomicU8::new(0);
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref READ_TIME: Mutex<Time> = Mutex::new(Time::default());
|
static ref READ_TIME: Mutex<Time> = Mutex::new(Time::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,17 +31,13 @@ pub fn init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cmos(reg: u8) -> u8 {
|
pub fn get_cmos(reg: u8) -> u8 {
|
||||||
unsafe {
|
CMOS_ADDRESS.write(reg);
|
||||||
CMOS_ADDRESS.lock().write(reg);
|
CMOS_DATA.read()
|
||||||
CMOS_DATA.lock().read()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_updating() -> bool {
|
pub fn is_updating() -> bool {
|
||||||
unsafe {
|
CMOS_ADDRESS.write(0x0A);
|
||||||
CMOS_ADDRESS.lock().write(0x0A);
|
CMOS_DATA.read() & 0x80 != 0
|
||||||
CMOS_DATA.lock().read() & 0x80 != 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read() -> Time {
|
pub fn read() -> Time {
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
//! used for PIT Timer
|
//! used for PIT Timer
|
||||||
|
|
||||||
use spin::Mutex;
|
|
||||||
use x86_64::instructions::port::PortWriteOnly;
|
|
||||||
|
|
||||||
use crate::config::TIMER_FREQ;
|
use crate::config::TIMER_FREQ;
|
||||||
|
|
||||||
|
use crate::device::io_port::{IoPort, WriteOnlyAccess};
|
||||||
|
|
||||||
const TIMER_RATE: u32 = 1193182;
|
const TIMER_RATE: u32 = 1193182;
|
||||||
|
|
||||||
static TIMER_PERIOD: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x40));
|
static TIMER_PERIOD: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0x40) };
|
||||||
static TIMER_MOD: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x43));
|
static TIMER_MOD: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0x43) };
|
||||||
static TIMER_SQUARE_WAVE: u8 = 0x36;
|
static TIMER_SQUARE_WAVE: u8 = 0x36;
|
||||||
|
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
// Initialize timer.
|
// Initialize timer.
|
||||||
let cycle = TIMER_RATE / TIMER_FREQ as u32;
|
let cycle = TIMER_RATE / TIMER_FREQ as u32;
|
||||||
unsafe {
|
TIMER_MOD.write(TIMER_SQUARE_WAVE);
|
||||||
TIMER_MOD.lock().write(TIMER_SQUARE_WAVE);
|
TIMER_PERIOD.write((cycle & 0xFF) as _);
|
||||||
TIMER_PERIOD.lock().write((cycle & 0xFF) as _);
|
TIMER_PERIOD.write((cycle >> 8) as _);
|
||||||
TIMER_PERIOD.lock().write((cycle >> 8) as _);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user