mirror of
https://github.com/rcore-os/rCore.git
synced 2025-01-19 01:07:05 +04:00
Move COM1 to drivers
This commit is contained in:
parent
5cc8e825ef
commit
7644694158
@ -102,7 +102,7 @@ pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
|
||||
COM1 => com1(),
|
||||
COM2 => com2(),
|
||||
_ => {
|
||||
if IRQ_MANAGER.read().try_handle_interrupt(Some(irq as u32)) {
|
||||
if IRQ_MANAGER.read().try_handle_interrupt(Some(irq)) {
|
||||
debug!("driver processed interrupt");
|
||||
return;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use super::{
|
||||
pub struct AHCIDriver(Mutex<AHCI<Provider>>);
|
||||
|
||||
impl Driver for AHCIDriver {
|
||||
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ impl BlockDriver for AHCIDriver {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(_irq: Option<u32>, header: usize, size: usize) -> Option<Arc<AHCIDriver>> {
|
||||
pub fn init(_irq: Option<usize>, header: usize, size: usize) -> Option<Arc<AHCIDriver>> {
|
||||
if let Some(ahci) = AHCI::new(header, size) {
|
||||
let driver = Arc::new(AHCIDriver(Mutex::new(ahci)));
|
||||
DRIVERS.write().push(driver.clone());
|
||||
|
@ -12,7 +12,7 @@ use crate::{drivers::NetDriver, sync::SpinNoIrqLock as Mutex};
|
||||
struct VirtIOBlkDriver(Mutex<VirtIOBlk<'static>>);
|
||||
|
||||
impl Driver for VirtIOBlkDriver {
|
||||
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||
self.0.lock().ack_interrupt()
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ impl PortOps for PortOpsImpl {
|
||||
|
||||
/// Enable the pci device and its interrupt
|
||||
/// Return assigned MSI interrupt number when applicable
|
||||
unsafe fn enable(loc: Location) -> Option<u32> {
|
||||
unsafe fn enable(loc: Location) -> Option<usize> {
|
||||
let ops = &PortOpsImpl;
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
|
||||
@ -101,7 +101,7 @@ unsafe fn enable(loc: Location) -> Option<u32> {
|
||||
am.write32(ops, loc, cap_ptr + PCI_MSI_ADDR, 0xfee00000 | (0 << 12));
|
||||
MSI_IRQ += 1;
|
||||
let irq = MSI_IRQ;
|
||||
assigned_irq = Some(irq);
|
||||
assigned_irq = Some(irq as usize);
|
||||
// we offset all our irq numbers by 32
|
||||
if (orig_ctrl >> 16) & (1 << 7) != 0 {
|
||||
// 64bit
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
struct VirtIOGpuDriver(Mutex<VirtIOGpu<'static>>);
|
||||
|
||||
impl Driver for VirtIOGpuDriver {
|
||||
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||
self.0.lock().ack_interrupt()
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ use crate::{
|
||||
struct VirtIOInputDriver(Mutex<VirtIOInput<'static>>);
|
||||
|
||||
impl Driver for VirtIOInputDriver {
|
||||
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||
let mut input = self.0.lock();
|
||||
let ack = input.ack_interrupt().expect("failed to ack interrupt");
|
||||
if ack {
|
||||
|
@ -6,7 +6,7 @@ use alloc::vec::Vec;
|
||||
|
||||
pub struct IrqManager {
|
||||
// drivers that only respond to specific irq
|
||||
mapping: BTreeMap<u32, Vec<Arc<dyn Driver>>>,
|
||||
mapping: BTreeMap<usize, Vec<Arc<dyn Driver>>>,
|
||||
// drivers that respond to all irqs
|
||||
all: Vec<Arc<dyn Driver>>,
|
||||
}
|
||||
@ -19,7 +19,7 @@ impl IrqManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_irq(&mut self, irq: u32, driver: Arc<dyn Driver>) {
|
||||
pub fn register_irq(&mut self, irq: usize, driver: Arc<dyn Driver>) {
|
||||
match self.mapping.entry(irq) {
|
||||
Entry::Occupied(mut e) => {
|
||||
e.get_mut().push(driver);
|
||||
@ -36,7 +36,7 @@ impl IrqManager {
|
||||
self.all.push(driver);
|
||||
}
|
||||
|
||||
pub fn register_opt(&mut self, irq_opt: Option<u32>, driver: Arc<dyn Driver>) {
|
||||
pub fn register_opt(&mut self, irq_opt: Option<usize>, driver: Arc<dyn Driver>) {
|
||||
if let Some(irq) = irq_opt {
|
||||
self.register_irq(irq, driver);
|
||||
} else {
|
||||
@ -44,7 +44,7 @@ impl IrqManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deregister_irq(&mut self, irq: u32, driver: Arc<dyn Driver>) {
|
||||
pub fn deregister_irq(&mut self, irq: usize, driver: Arc<dyn Driver>) {
|
||||
if let Some(e) = self.mapping.get_mut(&irq) {
|
||||
e.retain(|d| !Arc::ptr_eq(&d, &driver));
|
||||
}
|
||||
@ -54,7 +54,7 @@ impl IrqManager {
|
||||
self.all.retain(|d| !Arc::ptr_eq(&d, &driver));
|
||||
}
|
||||
|
||||
pub fn try_handle_interrupt(&self, irq_opt: Option<u32>) -> bool {
|
||||
pub fn try_handle_interrupt(&self, irq_opt: Option<usize>) -> bool {
|
||||
if let Some(irq) = irq_opt {
|
||||
if let Some(e) = self.mapping.get(&irq) {
|
||||
for dri in e.iter() {
|
||||
|
@ -9,18 +9,31 @@ use spin::RwLock;
|
||||
|
||||
pub use block::BlockDriver;
|
||||
pub use net::NetDriver;
|
||||
use rtc::RtcDriver;
|
||||
pub use rtc::RtcDriver;
|
||||
pub use tty::TtyDriver;
|
||||
|
||||
/// Block device
|
||||
pub mod block;
|
||||
/// Bus controller
|
||||
pub mod bus;
|
||||
/// Character console
|
||||
pub mod console;
|
||||
/// Device tree
|
||||
pub mod device_tree;
|
||||
/// Display controller
|
||||
pub mod gpu;
|
||||
/// Mouse device
|
||||
pub mod input;
|
||||
/// Interrupt controller
|
||||
pub mod irq;
|
||||
/// Network controller
|
||||
pub mod net;
|
||||
/// For isomorphic_drivers
|
||||
pub mod provider;
|
||||
/// Real time clock
|
||||
pub mod rtc;
|
||||
/// Serial port
|
||||
pub mod tty;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum DeviceType {
|
||||
@ -29,6 +42,7 @@ pub enum DeviceType {
|
||||
Input,
|
||||
Block,
|
||||
Rtc,
|
||||
Tty,
|
||||
}
|
||||
|
||||
pub trait Driver: Send + Sync {
|
||||
@ -36,7 +50,7 @@ pub trait Driver: Send + Sync {
|
||||
// return false otherwise
|
||||
// irq number is provided when available
|
||||
// driver should skip handling when irq number is mismatched
|
||||
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool;
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool;
|
||||
|
||||
// return the correspondent device type, see DeviceType
|
||||
fn device_type(&self) -> DeviceType;
|
||||
@ -49,9 +63,14 @@ pub trait Driver: Send + Sync {
|
||||
fn as_net(&self) -> Option<&dyn NetDriver> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_block(&self) -> Option<&dyn BlockDriver> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_rtc(&self) -> Option<&dyn RtcDriver> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
@ -60,6 +79,7 @@ lazy_static! {
|
||||
pub static ref NET_DRIVERS: RwLock<Vec<Arc<dyn NetDriver>>> = RwLock::new(Vec::new());
|
||||
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<dyn BlockDriver>>> = RwLock::new(Vec::new());
|
||||
pub static ref RTC_DRIVERS: RwLock<Vec<Arc<dyn RtcDriver>>> = RwLock::new(Vec::new());
|
||||
pub static ref TTY_DRIVERS: RwLock<Vec<Arc<dyn TtyDriver>>> = RwLock::new(Vec::new());
|
||||
pub static ref IRQ_MANAGER: RwLock<irq::IrqManager> = RwLock::new(irq::IrqManager::new());
|
||||
}
|
||||
|
||||
|
@ -32,11 +32,11 @@ pub struct E1000Interface {
|
||||
iface: Mutex<EthernetInterface<'static, 'static, 'static, E1000Driver>>,
|
||||
driver: E1000Driver,
|
||||
name: String,
|
||||
irq: Option<u32>,
|
||||
irq: Option<usize>,
|
||||
}
|
||||
|
||||
impl Driver for E1000Interface {
|
||||
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||
if irq.is_some() && self.irq.is_some() && irq != self.irq {
|
||||
// not ours, skip it
|
||||
return false;
|
||||
@ -186,7 +186,7 @@ impl phy::TxToken for E1000TxToken {
|
||||
}
|
||||
|
||||
// JudgeDuck-OS/kern/e1000.c
|
||||
pub fn init(name: String, irq: Option<u32>, header: usize, size: usize, index: usize) {
|
||||
pub fn init(name: String, irq: Option<usize>, header: usize, size: usize, index: usize) {
|
||||
info!("Probing e1000 {}", name);
|
||||
|
||||
// randomly generated
|
||||
|
@ -38,12 +38,12 @@ pub struct IXGBEInterface {
|
||||
iface: Mutex<EthernetInterface<'static, 'static, 'static, IXGBEDriver>>,
|
||||
driver: IXGBEDriver,
|
||||
ifname: String,
|
||||
irq: Option<u32>,
|
||||
irq: Option<usize>,
|
||||
id: String,
|
||||
}
|
||||
|
||||
impl Driver for IXGBEInterface {
|
||||
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||
if irq.is_some() && self.irq.is_some() && irq != self.irq {
|
||||
// not ours, skip it
|
||||
return false;
|
||||
@ -196,7 +196,7 @@ impl phy::TxToken for IXGBETxToken {
|
||||
|
||||
pub fn ixgbe_init(
|
||||
name: String,
|
||||
irq: Option<u32>,
|
||||
irq: Option<usize>,
|
||||
header: usize,
|
||||
size: usize,
|
||||
index: usize,
|
||||
|
@ -147,7 +147,7 @@ pub struct RouterInterface {
|
||||
}
|
||||
|
||||
impl Driver for RouterInterface {
|
||||
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||
let mut driver = self.driver.0.lock();
|
||||
|
||||
let isr = unsafe { AXI_STREAM_FIFO_ISR.read_volatile() };
|
||||
|
@ -36,7 +36,7 @@ impl NetDriver for VirtIONetDriver {
|
||||
}
|
||||
|
||||
impl Driver for VirtIONetDriver {
|
||||
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||
self.0.lock().ack_interrupt()
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ fn bcd2bin(num: u64) -> u64 {
|
||||
pub struct RtcCmos;
|
||||
|
||||
impl Driver for RtcCmos {
|
||||
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool {
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
|
66
kernel/src/drivers/tty/com.rs
Normal file
66
kernel/src/drivers/tty/com.rs
Normal file
@ -0,0 +1,66 @@
|
||||
//! COM ports in x86
|
||||
use super::super::DRIVERS;
|
||||
use super::super::IRQ_MANAGER;
|
||||
use super::{super::TTY_DRIVERS, TtyDriver};
|
||||
use crate::{
|
||||
drivers::{DeviceType, Driver},
|
||||
sync::SpinNoIrqLock as Mutex,
|
||||
};
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use uart_16550::SerialPort;
|
||||
|
||||
pub const COM2: usize = 3;
|
||||
pub const COM1: usize = 4;
|
||||
|
||||
struct COM {
|
||||
port: Mutex<SerialPort>,
|
||||
base: u16,
|
||||
}
|
||||
|
||||
impl COM {
|
||||
fn new(base: u16) -> COM {
|
||||
let port = Mutex::new(unsafe { SerialPort::new(base) });
|
||||
port.lock().init();
|
||||
COM { port, base }
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for COM {
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn device_type(&self) -> DeviceType {
|
||||
DeviceType::Tty
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("com_{}", self.base)
|
||||
}
|
||||
}
|
||||
|
||||
impl TtyDriver for COM {
|
||||
fn read(&self) -> u8 {
|
||||
self.port.lock().receive()
|
||||
}
|
||||
|
||||
fn write(&self, data: &[u8]) {
|
||||
let mut port = self.port.lock();
|
||||
for byte in data {
|
||||
port.send(*byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
add(0x3F8, COM1);
|
||||
add(0x2F8, COM2);
|
||||
}
|
||||
|
||||
fn add(base: u16, irq: usize) {
|
||||
let com = Arc::new(COM::new(base));
|
||||
DRIVERS.write().push(com.clone());
|
||||
TTY_DRIVERS.write().push(com.clone());
|
||||
IRQ_MANAGER.write().register_irq(irq, com);
|
||||
}
|
13
kernel/src/drivers/tty/mod.rs
Normal file
13
kernel/src/drivers/tty/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use super::Driver;
|
||||
use super::TTY_DRIVERS;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod com;
|
||||
|
||||
pub trait TtyDriver: Driver {
|
||||
// read one byte from tty
|
||||
fn read(&self) -> u8;
|
||||
|
||||
// write bytes to tty
|
||||
fn write(&self, data: &[u8]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user