From 5d1b4ed55d2f4febb1d8cb98cb0a6ed671d4de6d Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Mon, 8 Aug 2022 12:50:52 +0300 Subject: [PATCH] ATA: get rid of x86_ata We'll be using our own implementation. --- Cargo.lock | 13 -- ableos/Cargo.toml | 1 - x86_ata/Cargo.toml | 25 --- x86_ata/src/lib.rs | 380 --------------------------------------------- 4 files changed, 419 deletions(-) delete mode 100644 x86_ata/Cargo.toml delete mode 100644 x86_ata/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d6861c6..a19f7b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,7 +65,6 @@ dependencies = [ "wasmi", "watson", "x86_64", - "x86_ata", "y-compositor-protocol", ] @@ -879,18 +878,6 @@ dependencies = [ "volatile 0.4.5", ] -[[package]] -name = "x86_ata" -version = "0.1.0" -dependencies = [ - "bit_field", - "lazy_static", - "log", - "serde", - "spin 0.9.4", - "x86_64", -] - [[package]] name = "y-compositor-protocol" version = "0.1.1" diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index a50c735..deca9cf 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -148,7 +148,6 @@ git = "https://git.ablecorp.us:443/able/externc-libm.git" riscv = "*" [target.'cfg(target_arch = "x86_64")'.dependencies] -x86_ata = { path = "../x86_ata" } bootloader = { version = "0.9.8", features = ["map_physical_memory"] } cpuio = { git = "https://git.ablecorp.us/ondra05/cpuio.git" } pic8259 = "0.10.1" diff --git a/x86_ata/Cargo.toml b/x86_ata/Cargo.toml deleted file mode 100644 index 342b7d3..0000000 --- a/x86_ata/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "x86_ata" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -log = "*" -[dependencies.bit_field] -version = "0.10.0" - -[dependencies.lazy_static] -features = ["spin_no_std"] -version = "1.4.0" - -[dependencies.serde] -default-features = false -version = "1.0.126" - -[dependencies.spin] -version = "0.9.0" - -[dependencies.x86_64] -version = "0.14.3" diff --git a/x86_ata/src/lib.rs b/x86_ata/src/lib.rs deleted file mode 100644 index b2e760f..0000000 --- a/x86_ata/src/lib.rs +++ /dev/null @@ -1,380 +0,0 @@ -#![no_std] - -/// Implementation Courtesy of MOROS. -/// Currently Only Supports ATA-PIO, with 24-bit LBA Addressing. -extern crate alloc; - -use alloc::string::String; -use alloc::vec::Vec; -use bit_field::BitField; -use core::hint::spin_loop; -use lazy_static::lazy_static; -use log::trace; -use spin::Mutex; -use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly}; - -pub type BlockIndex = u32; - -pub const ATA_BLOCK_SIZE: usize = 512; - -fn sleep_ticks(ticks: usize) { - for _ in 0..=ticks { - x86_64::instructions::hlt(); - } -} - -#[repr(u16)] -enum Command { - Read = 0x20, - Write = 0x30, - Identify = 0xEC, -} - -#[allow(dead_code)] -#[repr(usize)] -enum Status { - ERR = 0, - IDX = 1, - CORR = 2, - DRQ = 3, - SRV = 4, - DF = 5, - RDY = 6, - BSY = 7, -} - -#[allow(dead_code)] -#[derive(Debug, Clone)] -pub struct Bus { - id: u8, - irq: u8, - - data_register: Port, - error_register: PortReadOnly, - features_register: PortWriteOnly, - sector_count_register: Port, - lba0_register: Port, - lba1_register: Port, - lba2_register: Port, - drive_register: Port, - status_register: PortReadOnly, - command_register: PortWriteOnly, - - alternate_status_register: PortReadOnly, - control_register: PortWriteOnly, - drive_blockess_register: PortReadOnly, -} - -impl Bus { - pub fn new(id: u8, io_base: u16, ctrl_base: u16, irq: u8) -> Self { - Self { - id, - irq, - - data_register: Port::new(io_base), - error_register: PortReadOnly::new(io_base + 1), - features_register: PortWriteOnly::new(io_base + 1), - sector_count_register: Port::new(io_base + 2), - lba0_register: Port::new(io_base + 3), - lba1_register: Port::new(io_base + 4), - lba2_register: Port::new(io_base + 5), - drive_register: Port::new(io_base + 6), - status_register: PortReadOnly::new(io_base + 7), - command_register: PortWriteOnly::new(io_base + 7), - - alternate_status_register: PortReadOnly::new(ctrl_base), - control_register: PortWriteOnly::new(ctrl_base), - drive_blockess_register: PortReadOnly::new(ctrl_base + 1), - } - } - - fn reset(&mut self) { - unsafe { - self.control_register.write(4); // Set SRST bit - sleep_ticks(2); - self.control_register.write(0); // Then clear it - sleep_ticks(2); - } - } - - fn wait(&mut self) { - for _ in 0..4 { - // Wait about 4 x 100 ns - unsafe { - self.alternate_status_register.read(); - } - } - } - - fn write_command(&mut self, cmd: Command) { - unsafe { - self.command_register.write(cmd as u8); - } - } - - fn status(&mut self) -> u8 { - unsafe { self.status_register.read() } - } - - fn lba1(&mut self) -> u8 { - unsafe { self.lba1_register.read() } - } - - fn lba2(&mut self) -> u8 { - unsafe { self.lba2_register.read() } - } - - fn read_data(&mut self) -> u16 { - unsafe { self.data_register.read() } - } - - fn write_data(&mut self, data: u16) { - unsafe { self.data_register.write(data) } - } - - fn busy_loop(&mut self) { - self.wait(); - let start = 0; - while self.is_busy() { - if 0 - start > 1 { - // Hanged - return self.reset(); - } - - spin_loop(); - } - } - - fn is_busy(&mut self) -> bool { - self.status().get_bit(Status::BSY as usize) - } - - fn is_error(&mut self) -> bool { - self.status().get_bit(Status::ERR as usize) - } - - fn is_ready(&mut self) -> bool { - self.status().get_bit(Status::RDY as usize) - } - - fn select_drive(&mut self, drive: u8) { - // Drive #0 (primary) = 0xA0 - // Drive #1 (secondary) = 0xB0 - let drive_id = 0xA0 | (drive << 4); - unsafe { - self.drive_register.write(drive_id); - } - } - - fn setup(&mut self, drive: u8, block: u32) { - let drive_id = 0xE0 | (drive << 4); - unsafe { - self.drive_register - .write(drive_id | ((block.get_bits(24..28) as u8) & 0x0F)); - self.sector_count_register.write(1); - self.lba0_register.write(block.get_bits(0..8) as u8); - self.lba1_register.write(block.get_bits(8..16) as u8); - self.lba2_register.write(block.get_bits(16..24) as u8); - } - } - - pub fn identify_drive(&mut self, drive: u8) -> Option<[u16; 256]> { - self.reset(); - self.wait(); - self.select_drive(drive); - unsafe { - self.sector_count_register.write(0); - self.lba0_register.write(0); - self.lba1_register.write(0); - self.lba2_register.write(0); - } - - self.write_command(Command::Identify); - - if self.status() == 0 { - return None; - } - - self.busy_loop(); - - if self.lba1() != 0 || self.lba2() != 0 { - return None; - } - - for i in 0.. { - if i == 256 { - self.reset(); - return None; - } - if self.is_error() { - return None; - } - if self.is_ready() { - break; - } - } - - let mut res = [0; 256]; - for i in 0..256 { - res[i] = self.read_data(); - } - Some(res) - } - - /// Read A single, 512-byte long slice from a given block - /// panics if buf isn't EXACTLY 512 Bytes long; - /// Example: - /// ```rust - /// // Read A Single block from a disk - /// pub fn read_single() { - /// use x86_ata::{init, ATA_BLOCK_SIZE, read}; - /// // 1. Initialise ATA Subsystem. (Perform Once, on boot) - /// init().expect("Failed To Start ATA..."); - /// // 2. Create a temporary buffer of size 512. - /// let mut buffer: [u8;ATA_BLOCK_SIZE] = [0; ATA_BLOCK_SIZE]; - /// // 3. Pass the buffer over to the Subsystem, to be filled. - /// read(0, 0, 0, &mut buffer); - /// } - - pub fn read(&mut self, drive: u8, block: BlockIndex, buf: &mut [u8]) { - assert!(buf.len() == 512); - trace!("Reading Block 0x{:8X}", block); - // trace!("{:?}", self); - - self.setup(drive, block); - self.write_command(Command::Read); - self.busy_loop(); - for i in (0..256).step_by(2) { - let data = self.read_data(); - - //log!("Read[{:08X}][{:02X}]: 0x{:04X}\n", block, i, data); - buf[i] = data.get_bits(0..8) as u8; - buf[i + 1] = data.get_bits(8..16) as u8; - } - } - - /// Write A single, 512-byte long slice to a given block - /// panics if buf isn't EXACTLY 512 Bytes long; - /// Example: - /// ```rust - /// // Read A Single block from a disk - /// pub fn write_single() { - /// use x86_ata::{init, ATA_BLOCK_SIZE, write}; - /// // 1. Initialise ATA Subsystem. (Perform Once, on boot) - /// init().expect("Failed To Start ATA..."); - /// // 2. Create a temporary buffer of size 512. - /// let buffer: [u8;ATA_BLOCK_SIZE] = [0; ATA_BLOCK_SIZE]; - /// // 3. Pass the buffer over to the Subsystem, to be filled. - /// write(0, 0, 0, &buffer); - /// } - - pub fn write(&mut self, drive: u8, block: BlockIndex, buf: &[u8]) { - assert!(buf.len() == 512); - self.setup(drive, block); - self.write_command(Command::Write); - self.busy_loop(); - for i in 0..256 { - let mut data = 0_u16; - data.set_bits(0..8, buf[i * 2] as u16); - data.set_bits(8..16, buf[i * 2 + 1] as u16); - - //log!("Data: 0x{:04X} | {}{} \n", data, buf[i * 2] as char, buf[i * 2 + 1] as char); - - self.write_data(data); - } - self.busy_loop(); - } -} - -lazy_static! { - pub static ref BUSES: Mutex> = Mutex::new(Vec::new()); -} - -fn disk_size(sectors: u32) -> (u32, String) { - let bytes = sectors * 512; - if bytes >> 20 < 1000 { - (bytes >> 20, String::from("MB")) - } else { - (bytes >> 30, String::from("GB")) - } -} - -pub fn list() -> Vec<(u8, u8, String, String, u32, String, u32)> { - let mut buses = BUSES.lock(); - let mut res = Vec::new(); - for bus in 0..2 { - for drive in 0..2 { - if let Some(buf) = buses[bus as usize].identify_drive(drive) { - let mut serial = String::new(); - for i in 10..20 { - for &b in &buf[i].to_be_bytes() { - serial.push(b as char); - } - } - serial = serial.trim().into(); - let mut model = String::new(); - for i in 27..47 { - for &b in &buf[i].to_be_bytes() { - model.push(b as char); - } - } - model = model.trim().into(); - let sectors = (buf[61] as u32) << 16 | (buf[60] as u32); - let (size, unit) = disk_size(sectors); - res.push((bus, drive, model, serial, size, unit, sectors)); - } - } - } - res -} - -/// Identify a specific drive on a bus, format: (bus, drive, model, serial. size, unit, sectors) -pub fn indentify_drive(bus: u8, drive: u8) -> Option<(u8, u8, String, String, u32, String, u32)> { - let mut buses = BUSES.lock(); - if let Some(buf) = buses[bus as usize].identify_drive(drive) { - let mut serial = String::new(); - for i in 10..20 { - for &b in &buf[i].to_be_bytes() { - serial.push(b as char); - } - } - serial = serial.trim().into(); - let mut model = String::new(); - for i in 27..47 { - for &b in &buf[i].to_be_bytes() { - model.push(b as char); - } - } - model = model.trim().into(); - let sectors = (buf[61] as u32) << 16 | (buf[60] as u32); - let (size, unit) = disk_size(sectors); - Some((bus, drive, model, serial, size, unit, sectors)) - } else { - None - } -} - -pub fn read(bus: u8, drive: u8, block: BlockIndex, buf: &mut [u8]) { - let mut buses = BUSES.lock(); - trace!("Reading Block 0x{:08X}\n", block); - buses[bus as usize].read(drive, block, buf); -} - -pub fn write(bus: u8, drive: u8, block: BlockIndex, buf: &[u8]) { - let mut buses = BUSES.lock(); - //log!("Writing Block 0x{:08X}\n", block); - buses[bus as usize].write(drive, block, buf); -} - -pub fn drive_is_present(bus: usize) -> bool { - unsafe { BUSES.lock()[bus].status_register.read() != 0xFF } -} - -pub fn init() -> Result<(), ()> { - { - let mut buses = BUSES.lock(); - buses.push(Bus::new(0, 0x1F0, 0x3F6, 14)); - buses.push(Bus::new(1, 0x170, 0x376, 15)); - } - Ok(()) -}