forked from koniifer/ableos
working IDE DMA implementation
This commit is contained in:
parent
998a1d30cf
commit
f140938ee6
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -54,6 +54,7 @@ dependencies = [
|
|||
"rdrand",
|
||||
"riscv",
|
||||
"rkyv",
|
||||
"seq-macro",
|
||||
"serde",
|
||||
"spin 0.9.4",
|
||||
"toml",
|
||||
|
@ -648,6 +649,12 @@ version = "4.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "seq-macro"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0772c5c30e1a0d91f6834f8e545c69281c099dfa9a3ac58d96a9fd629c8d4898"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.141"
|
||||
|
|
|
@ -78,7 +78,7 @@ versioning = { git = "https://git.ablecorp.us/able/aos_userland" }
|
|||
pc-keyboard = "0.5"
|
||||
# mini-backtrace = "0.1"
|
||||
clparse = { git = "https://git.ablecorp.us/able/core_utils", default-features = false }
|
||||
|
||||
seq-macro = "0.3"
|
||||
|
||||
[dependencies.linked_list_allocator]
|
||||
version = "0.9.0"
|
||||
|
|
|
@ -6,10 +6,16 @@
|
|||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
use crate::{arch::gdt, println, rhai_shell::KEYBUFF};
|
||||
use crate::{
|
||||
arch::gdt,
|
||||
devices::pci::{PciDevice, PCI_DEVICES},
|
||||
println,
|
||||
rhai_shell::KEYBUFF,
|
||||
};
|
||||
use cpuio::outb;
|
||||
use pic8259::ChainedPics;
|
||||
use qrcode::QrCode;
|
||||
use seq_macro::seq;
|
||||
use spin::Lazy;
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||
|
||||
|
@ -30,6 +36,9 @@ pub enum InterruptIndex {
|
|||
/// Mouse offset
|
||||
Mouse = 44,
|
||||
|
||||
/// Disk offset
|
||||
Disk = 46,
|
||||
|
||||
// SecondInterrupt = PIC_2_OFFSET,
|
||||
Cmos = 0x70,
|
||||
}
|
||||
|
@ -47,9 +56,9 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
|||
reset_pit_for_cpu();
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
|
||||
for int in 32..=255 {
|
||||
idt[int].set_handler_fn(undefined_handler);
|
||||
}
|
||||
seq!(N in 32..=255 {
|
||||
idt[N].set_handler_fn(undefined_handler_~N);
|
||||
});
|
||||
|
||||
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||
unsafe {
|
||||
|
@ -68,12 +77,21 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
|||
idt
|
||||
});
|
||||
|
||||
extern "x86-interrupt" fn undefined_handler(stack_frame: InterruptStackFrame) {
|
||||
error!("{:?}", stack_frame);
|
||||
seq!(N in 32..=255 {
|
||||
extern "x86-interrupt" fn undefined_handler_~N(stack_frame: InterruptStackFrame) {
|
||||
error!("INT {}: {:?}", N, stack_frame);
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
.notify_end_of_interrupt(N);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extern "x86-interrupt" fn software_int_handler(stack_frame: InterruptStackFrame) {
|
||||
trace!("EXCEPTION: SOFTWARE INT\n{:#?}", stack_frame);
|
||||
unsafe {
|
||||
PICS.lock().notify_end_of_interrupt(54);
|
||||
}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
use core::fmt;
|
||||
|
||||
use serde::de::value;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
use super::{
|
||||
|
@ -24,7 +25,7 @@ pub const INTEL_PIIX4_IDE: DeviceID = DeviceID::new(IntelCorp, 0x7111);
|
|||
// Display_VGA (0x0300)
|
||||
pub const VMWARE_SVGA2: DeviceID = DeviceID::new(VMWareInc, 0x0405);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// A struct containing info about a PCI device.
|
||||
pub struct PciDeviceInfo {
|
||||
pub header_type: u8,
|
||||
|
@ -44,18 +45,29 @@ impl PciDeviceInfo {
|
|||
/// Get the bar, 0-indexed
|
||||
pub fn bar(&self, bar: u8) -> u32 {
|
||||
assert!(bar < 6);
|
||||
unsafe { self.io_read(0, 0x10 + bar * 4) }
|
||||
unsafe { self.read(0, 0x10 + bar * 4) }
|
||||
}
|
||||
|
||||
/// Get the interrupt pin
|
||||
pub fn interrupt_pin(&self) -> u8 {
|
||||
let last_row = unsafe { self.io_read(0, 0x3C) };
|
||||
let last_row = unsafe { self.read(0, 0x3C) };
|
||||
((last_row >> 8) & 0xFF) as u8
|
||||
}
|
||||
|
||||
/// Read from IO space
|
||||
pub unsafe fn io_read(&self, func: u8, offset: u8) -> u32 {
|
||||
pci_io_read(self.bus, self.device, func, offset)
|
||||
/// Enable bus mastering. This allows the PCI device to do DMA
|
||||
pub fn enable_bus_mastering(&self) {
|
||||
let command = unsafe { self.read(0, 4) } | 1 << 2;
|
||||
unsafe { self.write(0, 4, command) }
|
||||
}
|
||||
|
||||
/// Read from configuration space
|
||||
pub unsafe fn read(&self, func: u8, offset: u8) -> u32 {
|
||||
pci_config_read(self.bus, self.device, func, offset)
|
||||
}
|
||||
|
||||
/// Write to IO space
|
||||
pub unsafe fn write(&self, func: u8, offset: u8, value: u32) {
|
||||
pci_config_write(self.bus, self.device, func, offset, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +128,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let reg2 = unsafe { pci_io_read(bus, device, 0, 0x8) };
|
||||
let reg2 = unsafe { pci_config_read(bus, device, 0, 0x8) };
|
||||
let class = ((reg2 >> 16) & 0x0000FFFF) as u16;
|
||||
let pci_class = PciFullClass::from_u16(class);
|
||||
let header_type = get_header_type(bus, device, 0);
|
||||
|
@ -134,7 +146,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
|||
})
|
||||
}
|
||||
|
||||
unsafe fn pci_io_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||
unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
|
@ -144,23 +156,39 @@ unsafe fn pci_io_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
|||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32;
|
||||
|
||||
// write address
|
||||
Port::<u32>::new(0xCF8).write(address);
|
||||
Port::new(0xCF8).write(address);
|
||||
|
||||
// read data
|
||||
Port::<u32>::new(0xCFC).read()
|
||||
Port::new(0xCFC).read()
|
||||
}
|
||||
|
||||
unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address =
|
||||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32;
|
||||
|
||||
// write address
|
||||
Port::new(0xCF8).write(address);
|
||||
|
||||
// write data
|
||||
Port::new(0xCFC).write(value);
|
||||
}
|
||||
|
||||
fn get_header_type(bus: u8, device: u8, function: u8) -> u8 {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
let res = unsafe { pci_io_read(bus, device, function, 0x0C) };
|
||||
let res = unsafe { pci_config_read(bus, device, function, 0x0C) };
|
||||
((res >> 16) & 0xFF) as u8
|
||||
}
|
||||
|
||||
fn get_ids(bus: u8, device: u8, function: u8) -> (u16, u16) {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
let res = unsafe { pci_io_read(bus, device, function, 0) };
|
||||
let res = unsafe { pci_config_read(bus, device, function, 0) };
|
||||
let dev_id = ((res >> 16) & 0xFFFF) as u16;
|
||||
let vnd_id = (res & 0xFFFF) as u16;
|
||||
(dev_id, vnd_id)
|
||||
|
|
|
@ -9,30 +9,48 @@ pub mod device;
|
|||
pub mod vendors;
|
||||
|
||||
// MassStorage_IDE (0x0101)
|
||||
pub mod piix;
|
||||
pub mod piix_ide;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
pub use class::*;
|
||||
pub use device::*;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
use x86_64::structures::paging::{Mapper, Size4KiB};
|
||||
|
||||
use crate::arch::memory::BootInfoFrameAllocator;
|
||||
|
||||
use self::piix::Piix;
|
||||
use self::piix_ide::PiixIde;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PCI_DEVICES: Mutex<Vec<Arc<Mutex<PciDevice>>>> = Default::default();
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub enum PciDevice {
|
||||
// MassStorage_IDE (0x0101)
|
||||
PiixIde(PiixIde),
|
||||
// Variant so that we aren't about irrefutable if-let patterns
|
||||
// FIXME: remove as soon as we have other variants
|
||||
_0,
|
||||
}
|
||||
|
||||
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||
pub fn init(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut BootInfoFrameAllocator) {
|
||||
for bus in 0..=255 {
|
||||
for device in 0..32 {
|
||||
if let Some(device_info) = device::check_device(bus, device) {
|
||||
trace!("{device_info}");
|
||||
match device_info.device_id {
|
||||
// FIXME: Unknown class
|
||||
S3INC_TRIO64V2 => {}
|
||||
|
||||
// MassStorage_IDE (0x0101)
|
||||
INTEL_PIIX3_IDE | INTEL_PIIX4_IDE => {
|
||||
let mut piix = Piix::new(bus, device).unwrap();
|
||||
let mut piix = PiixIde::new(bus, device).unwrap();
|
||||
piix.allocate_dma_frame(mapper, frame_allocator).unwrap();
|
||||
piix.read().unwrap();
|
||||
let mut devices = PCI_DEVICES.lock();
|
||||
devices.push(Arc::new(Mutex::new(PciDevice::PiixIde(piix))));
|
||||
}
|
||||
|
||||
// Display_VGA (0x0300)
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::mem;
|
||||
use core::num::TryFromIntError;
|
||||
|
||||
use x86_64::instructions::interrupts;
|
||||
use x86_64::instructions::port::Port;
|
||||
use x86_64::instructions::{hlt, interrupts};
|
||||
use x86_64::structures::paging::{FrameAllocator, FrameDeallocator};
|
||||
// FIXME: platform agnostic paging stuff
|
||||
use x86_64::structures::paging::{mapper::MapToError, Mapper, Page, PhysFrame, Size4KiB};
|
||||
|
@ -16,8 +17,11 @@ use x86_64::VirtAddr;
|
|||
use crate::arch::memory::BootInfoFrameAllocator;
|
||||
use crate::devices::pci::check_device;
|
||||
|
||||
const PRDT_START: u64 = 0x_ffff_ffff_0000_0000;
|
||||
const BUFFER_START: u64 = 0x_ffff_ffff_0000_1000;
|
||||
use super::PciDeviceInfo;
|
||||
|
||||
// FIXME: un-hardcode these
|
||||
const PRDT_START: u64 = 0xffff_ffff_0000_0000;
|
||||
const BUFFER_START: u64 = 0xffff_ffff_0000_1000;
|
||||
|
||||
/// Bus Master IDE Command
|
||||
const BMIC_OFFSET: u16 = 0;
|
||||
|
@ -38,6 +42,18 @@ const SECONDARY_COMMAND: u16 = 0x0170;
|
|||
/// Data register offset
|
||||
const DATA_OFFSET: u16 = 0;
|
||||
|
||||
/// Sector count register offset
|
||||
const SECCOUNT_OFFSET: u16 = 2;
|
||||
|
||||
/// LBA0 register offset
|
||||
const LBA0_OFFSET: u16 = 3;
|
||||
|
||||
/// LBA1 register offset
|
||||
const LBA1_OFFSET: u16 = 4;
|
||||
|
||||
/// LBA2 register offset
|
||||
const LBA2_OFFSET: u16 = 5;
|
||||
|
||||
/// Drive/Head register offset
|
||||
const DRIVE_HEAD_OFFSET: u16 = 6;
|
||||
|
||||
|
@ -56,19 +72,23 @@ const ALT_STATUS_OFFSET: u16 = 2;
|
|||
/// ATA identification command
|
||||
const CMD_IDENTIFY: u8 = 0xEC;
|
||||
|
||||
pub struct Piix {
|
||||
/// ATA read using LBA48 DMA command
|
||||
const CMD_READ_DMA_EXT: u8 = 0x25;
|
||||
|
||||
pub struct PiixIde {
|
||||
device_info: PciDeviceInfo,
|
||||
ide_devices: Vec<IdeDevice>,
|
||||
prdt_frame: Option<PhysFrame>,
|
||||
buffer_frames: Option<Vec<PhysFrame>>,
|
||||
bmiba: u16,
|
||||
}
|
||||
|
||||
impl Piix {
|
||||
impl PiixIde {
|
||||
// FIXME: make this return a Result
|
||||
pub fn new(bus: u8, device: u8) -> Option<Self> {
|
||||
let device_info = check_device(bus, device)?;
|
||||
trace!("device_info: {device_info}");
|
||||
let idetim = unsafe { device_info.io_read(0, 0x40) };
|
||||
device_info.enable_bus_mastering();
|
||||
let idetim = unsafe { device_info.read(0, 0x40) };
|
||||
trace!("idetim: {idetim:b}");
|
||||
// FIXME: enable the right bits in idetim (and sidetim) to use fast timings
|
||||
|
||||
|
@ -160,6 +180,7 @@ impl Piix {
|
|||
let bmiba = device_info.bar(4) & 0xFFFFFFFC;
|
||||
|
||||
Some(Self {
|
||||
device_info,
|
||||
ide_devices,
|
||||
prdt_frame: None,
|
||||
buffer_frames: None,
|
||||
|
@ -177,6 +198,7 @@ impl Piix {
|
|||
let prdt_frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||
|
||||
let buffer_frames = {
|
||||
let mut frame = frame_allocator
|
||||
.allocate_frame()
|
||||
|
@ -231,7 +253,7 @@ impl Piix {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read(&self) -> Result<(), TryFromIntError> {
|
||||
pub fn read(&mut self) -> Result<(), TryFromIntError> {
|
||||
// prepare PRD table
|
||||
let prd = PRDT_START as *mut PhysRegionDescriptor;
|
||||
unsafe {
|
||||
|
@ -243,19 +265,51 @@ impl Piix {
|
|||
(*prd).byte_count = 512;
|
||||
// this is the end of table
|
||||
(*prd).eot = 1 << 7;
|
||||
// this byte is reserved, we should probably set it to 0
|
||||
(*prd)._0 = 0;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.load_prdt(Channel::Primary);
|
||||
self.stop(Channel::Primary);
|
||||
self.set_read(Channel::Primary);
|
||||
self.clear_status(Channel::Primary);
|
||||
self.clear_bmi_status(Channel::Primary);
|
||||
select_drive(Drive::Master, Channel::Primary);
|
||||
set_lba(Channel::Primary, 0, 1);
|
||||
ata_send_command(CMD_READ_DMA_EXT, Channel::Primary);
|
||||
self.start(Channel::Primary);
|
||||
|
||||
loop {
|
||||
let status = self.bmi_status(Channel::Primary);
|
||||
trace!("read status: 0b{status:b}");
|
||||
|
||||
// Bit 2 (INT) set?
|
||||
if (status >> 2) & 1 == 1 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: error handling
|
||||
|
||||
// Stop DMA
|
||||
self.stop(Channel::Primary);
|
||||
|
||||
// Clear the interrupt bit
|
||||
self.clear_bmi_status(Channel::Primary);
|
||||
|
||||
for i in 0..512 {
|
||||
let addr = (BUFFER_START + i) as *mut u8;
|
||||
trace!("byte {i}: {}", *addr);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_info(&self) -> PciDeviceInfo {
|
||||
self.device_info
|
||||
}
|
||||
|
||||
unsafe fn load_prdt(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
|
@ -273,6 +327,21 @@ impl Piix {
|
|||
);
|
||||
}
|
||||
|
||||
unsafe fn start(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIC_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut bmic = port.read();
|
||||
// start transfer
|
||||
bmic |= 1;
|
||||
// write the new bmic
|
||||
port.write(bmic);
|
||||
}
|
||||
|
||||
unsafe fn stop(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
|
@ -318,7 +387,18 @@ impl Piix {
|
|||
port.write(bmic);
|
||||
}
|
||||
|
||||
unsafe fn clear_status(&self, channel: Channel) {
|
||||
unsafe fn bmi_status(&self, channel: Channel) -> u8 {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIS_OFFSET;
|
||||
let mut port = Port::new(addr);
|
||||
port.read()
|
||||
}
|
||||
|
||||
unsafe fn clear_bmi_status(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
|
@ -341,14 +421,15 @@ unsafe fn select_drive(drive: Drive, channel: Channel) {
|
|||
PRIMARY_COMMAND
|
||||
} + DRIVE_HEAD_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut drive_command = port.read();
|
||||
if drive.slave() {
|
||||
// mark bit 4
|
||||
drive_command |= 1 << 4;
|
||||
// FIXME: CHS support
|
||||
let drive_command = if drive.slave() {
|
||||
// slave & LBA
|
||||
0b11110000
|
||||
} else {
|
||||
// clear bit 4
|
||||
drive_command &= !(1 << 4);
|
||||
}
|
||||
// master & LBA
|
||||
0b11100000
|
||||
};
|
||||
|
||||
// write the new drive/head register
|
||||
port.write(drive_command);
|
||||
ata_delay(channel);
|
||||
|
@ -361,7 +442,7 @@ unsafe fn ata_send_command(command: u8, channel: Channel) -> u8 {
|
|||
} else {
|
||||
PRIMARY_COMMAND
|
||||
} + COMMAND_STATUS_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut port = Port::new(addr);
|
||||
port.write(command);
|
||||
ata_delay(channel);
|
||||
port.read()
|
||||
|
@ -380,6 +461,37 @@ unsafe fn ata_delay(channel: Channel) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set LBA and sector count registers. sector_count of 0 means 65536 sectors
|
||||
unsafe fn set_lba(channel: Channel, lba: u64, sector_count: u16) {
|
||||
// FIXME: CHS and LBA24 support
|
||||
assert!(lba < 0xFFFFFFFFFFFF);
|
||||
|
||||
let command_block = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
};
|
||||
let mut seccount = Port::new(command_block + SECCOUNT_OFFSET);
|
||||
let mut lba0 = Port::new(command_block + LBA0_OFFSET);
|
||||
let mut lba1 = Port::new(command_block + LBA1_OFFSET);
|
||||
let mut lba2 = Port::new(command_block + LBA2_OFFSET);
|
||||
|
||||
let lba_bytes = lba.to_le_bytes();
|
||||
let sector_count_bytes = sector_count.to_le_bytes();
|
||||
|
||||
// write the new LBA & sector count registers
|
||||
// if LBA48 {
|
||||
seccount.write(sector_count_bytes[1]);
|
||||
lba0.write(lba_bytes[3]);
|
||||
lba1.write(lba_bytes[4]);
|
||||
lba2.write(lba_bytes[5]);
|
||||
// }
|
||||
seccount.write(sector_count_bytes[0]);
|
||||
lba0.write(lba_bytes[0]);
|
||||
lba1.write(lba_bytes[1]);
|
||||
lba2.write(lba_bytes[2]);
|
||||
}
|
||||
|
||||
unsafe fn read_dword_buffer(port: u16, buffer: *mut u32, mut count: u32) {
|
||||
// FIXME: this assumes x86-64
|
||||
interrupts::without_interrupts(|| {
|
||||
|
@ -398,6 +510,7 @@ struct IdeDevice {
|
|||
pub channel: Channel,
|
||||
pub drive: Drive,
|
||||
pub size: u64, // in sectors
|
||||
// FIXME: model
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use crate::arch::drivers::sysinfo::master;
|
||||
use crate::arch::interrupts::{reset_pit_for_cpu, set_pit_2};
|
||||
use crate::devices::pci::{PciDevice, PCI_DEVICES};
|
||||
use crate::filesystem;
|
||||
use crate::filesystem::vfs::VFS;
|
||||
use crate::systeminfo::{KERNEL_VERSION, RELEASE_TYPE};
|
||||
|
@ -112,6 +113,24 @@ pub fn scratchpad() {
|
|||
BANNER_WIDTH
|
||||
);
|
||||
|
||||
let piix_ide_device = {
|
||||
let pci_devices = PCI_DEVICES.lock();
|
||||
pci_devices
|
||||
.iter()
|
||||
.find_map(|device_ref| {
|
||||
let device = device_ref.lock();
|
||||
if let PciDevice::PiixIde(_) = &*device {
|
||||
Some(device_ref.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap()
|
||||
};
|
||||
let mut piix_ide_device = piix_ide_device.lock();
|
||||
if let PciDevice::PiixIde(device) = &mut *piix_ide_device {
|
||||
device.read().unwrap()
|
||||
}
|
||||
real_shell();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue