From c35911b79d224d3e5cd83501e52f3895951d839f Mon Sep 17 00:00:00 2001 From: shibedrill Date: Thu, 17 Jul 2025 22:51:26 -0400 Subject: [PATCH] License: add license --- .gitignore | 1 + Cargo.lock | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 +++++ LICENSE | 18 +++++++++ src/achi/mod.rs | 16 ++++++++ src/ata/mod.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +++ src/sata/fis.rs | 89 ++++++++++++++++++++++++++++++++++++++++ src/sata/hba.rs | 61 ++++++++++++++++++++++++++++ src/sata/mod.rs | 4 ++ 10 files changed, 406 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 src/achi/mod.rs create mode 100644 src/ata/mod.rs create mode 100644 src/lib.rs create mode 100644 src/sata/fis.rs create mode 100644 src/sata/hba.rs create mode 100644 src/sata/mod.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2df4539 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,105 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahci" +version = "0.1.0" +dependencies = [ + "bitfields", + "bitflags", + "num-derive", +] + +[[package]] +name = "bitfields" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdbce6688e3ab66aff2ab413b762ccde9f37990e27bba0bb38a4b2ad1b5d877" +dependencies = [ + "bitfields-impl", +] + +[[package]] +name = "bitfields-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57413e4b276d883b77fb368b7b33ae6a5eb97692852d49a5394d4f72ba961827" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "thiserror", +] + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1d2d76f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ahci" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitfields = "1.0.0" +bitflags = "2.9.1" +num-derive = "0.4.2" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..156c8e6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ + +# GNU Public License v3 + +ahci - A Rust library for AHCI related data structures and functions. +Copyright (C) 2025 shibedrill + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/src/achi/mod.rs b/src/achi/mod.rs new file mode 100644 index 0000000..27a75d1 --- /dev/null +++ b/src/achi/mod.rs @@ -0,0 +1,16 @@ +#[repr(u32)] +pub enum SataSignature { + Ata = 0x000000101, + Atapi = 0xEB140101, + Semb = 0xC33C0101, + Pm = 0x96690101, +} + +#[repr(u8)] +pub enum AchiDevice { + Null = 0, + Sata = 1, + Semb = 2, + Pm = 3, + Satapi = 4, +} diff --git a/src/ata/mod.rs b/src/ata/mod.rs new file mode 100644 index 0000000..092bc8c --- /dev/null +++ b/src/ata/mod.rs @@ -0,0 +1,98 @@ +#[repr(u8)] +#[non_exhaustive] +pub enum AtaCommand { + Nop(u8) = 0x0, // No-op + CfaReqXErr(u8) = 0x3, + DataSetMgmt(u16) = 0x6, + DataSetMgmtXL(u16) = 0x7, + ReqSenseDataX(u16) = 0xB, + GetPhysElemStatus(u16) = 0x12, + ReadSector(u8) = 0x20, // Read sectors + ReadSectorX(u16) = 0x24, // Read sectors (ext) + ReadDmaX(u16) = 0x25, + ReadStreamDmaX(u16) = 0x2A, + ReadStreamX(u16) = 0x2B, + ReadLogX(u16) = 0x2F, + WriteSector(u8) = 0x30, // Write sectors + WriteSectorX(u16) = 0x34, // Write sectors (ext) + WriteDmaX(u16) = 0x35, + CfaWriteSectorWOErase(u16) = 0x38, + WriteStreamDmaX(u16) = 0x3A, + WriteStreamX(u16) = 0x3B, + WriteDmaFuaX(u16) = 0x3D, + WriteLogX(u16) = 0x3F, + ReadVerifySector(u8) = 0x40, + ReadVerifySectorX(u16) = 0x42, + ZeroX(u16) = 0x44, + WriteUnCorrX(u16) = 0x45, + ReadLogDmaX(u16) = 0x47, + ZacMgmtIn(u16) = 0x4A, + CfgStream(u16) = 0x51, + WriteLogDmaX(u16) = 0x57, + TrustedNonData(u8) = 0x5B, + TrustedRecv(u8) = 0x5C, + TrustedRecvDma(u8) = 0x5D, + TrustedSend(u8) = 0x5E, + TrustedSendDma(u8) = 0x5F, + ReadFpdmaQueued(u16) = 0x60, + WriteFpdmaQueued(u16) = 0x61, + NcqNonData(u16) = 0x63, + SendFpdmaQueued(u16) = 0x64, + RecvFpdmaQueued(u16) = 0x65, + SetTimeDateX(u16) = 0x77, + AccMaxAddrCfg(u16) = 0x78, + RemElemTrunc(u16) = 0x7C, + RestElemRebuild(u16) = 0x7D, + RemElemModZones(u16) = 0x7E, + CfaTranslateSector(u8) = 0x87, + ExecDevDiag(u8) = 0x90, + InitDevParams(u8) = 0x91, + DlUcode(u8) = 0x92, + DlUcodeDma(u8) = 0x93, + MutateX(u16) = 0x96, + ZacMgmtOut(u16) = 0x9F, + Smart(u8) = 0xB0, + SetSectorCfgX(u16) = 0xB2, + SanDev(u16) = 0xB4, + ReadDma(u8) = 0xC8, + WriteDma(u8) = 0xCA, + CfaWriteMultWOErase(u8) = 0xCD, + StandbyImm(u8) = 0xE0, + IdleImm(u8) = 0xE1, + Standby(u8) = 0xE2, + Idle(u8) = 0xE3, + ReadBuf(u8) = 0xE4, + CheckPowerMode(u8) = 0xE5, + Sleep(u8) = 0xE6, + FLushCache(u8) = 0xE7, + WriteBuf(u8) = 0xE8, + ReadBufDma(u8) = 0xE9, + FlushCacheX(u8) = 0xEA, + WriteBufDma(u8) = 0xEB, + IdentifyDev(u8) = 0xEC, // Identify + IdentifyDevDma(u8) = 0xEE, + SetFeatures(u8) = 0xEF, + SecSetPwd(u8) = 0xF1, + SecUnlock(u8) = 0xF2, + SecErasePrep(u8) = 0xF3, + SecEraseUnit(u8) = 0xF4, + SecFreezeLock(u8) = 0xF5, + SecDisablePwd(u8) = 0xF6, + ReadNativeMaxAddr(u8) = 0xF8, + SetMaxAddr(u8) = 0xF9, +} + +pub struct AtaIdentity { + device: u16, // Device bitfields + num_cylinders: u16, + spec_config: u16, + num_heads: u16, + _reserved_0: [u16; 2], + sectors_per_track: u16, + vendor: [u16; 3], + serial_number: [char; 20], + _reserved_1: [u16; 3], + firmware_rev: [char; 8], + model_num: [char; 40], + _pad: [char; 256], +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..76bbf76 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +#![feature(default_field_values)] + +pub mod achi; +pub mod ata; +pub mod sata; diff --git a/src/sata/fis.rs b/src/sata/fis.rs new file mode 100644 index 0000000..6954deb --- /dev/null +++ b/src/sata/fis.rs @@ -0,0 +1,89 @@ +/// Types of Frame Information Structure. +#[repr(u8)] +pub enum FisType { + RegH2d = 0x27, // Register FIS - host to device + RegD2h = 0x34, // Register FIS - device to host + DmaAct = 0x39, // DMA activate FIS - device to host + DmaSetup = 0x41, // DMA setup FIS - bidirectional + Data = 0x46, // Data FIS - bidirectional + Bist = 0x58, // BIST activate FIS - bidirectional + PioSetup = 0x5F, // PIO setup FIS - device to host + DevBits = 0xA1, // Set device bits FIS - device to host +} + +pub struct RegH2d { + fis_type: FisType = FisType::RegH2d, + port: u8, // Port information + command: u8, // Command register + feature_low: u8, // Feature register, 7:0 + lba_0: u8, // LBA low register, 7:0 + lba_1: u8, // LBA mid register, 15:8 + lba_2: u8, // LBA high register, 23:16 + device: u8, // Device register + lba_3: u8, // LBA register, 31:24 + lba_4: u8, // LBA register, 39:32 + lba_5: u8, // LBA register, 47:40 + feature_high: u8, // Feature register, 15:8 + count_low: u8, // Count register low + count_high: u8, // Count register high + icc: u8, // Isochronous command completion + control: u8, // Control register + _reserved_0: [u8;4] = [0;4] // Reserved +} + +pub struct RegD2h { + fis_type: FisType = FisType::RegD2h, + port: u8, // Port information + status: u8, // Status register + error: u8, // Error register + lba_0: u8, // LBA low register, 7:0 + lba_1: u8, // LBA mid register, 15:8 + lba_2: u8, // LBA high register, 23:16 + device: u8, // Device register + lba_3: u8, // LBA register, 31:24 + lba_4: u8, // LBA register, 39:32 + lba_5: u8, // LBA register, 47:40 + _reserved_0: u8, // Reserved + count_low: u8, // Count register, 7:0 + count_high: u8, // Count register, 15:8 + _reserved_1: [u8;6] = [0;6], +} + +pub struct Data { + fis_type: FisType = FisType::Data, + port: u8, // Port information + _reserved_0: [u8;2] = [0;2], // Reserved + data: [u32;2048], // Payload +} + +pub struct PioSetup { + fis_type: FisType = FisType::PioSetup, + port: u8, // Port information + status: u8, + error: u8, + lba_0: u8, + lba_1: u8, + lba_2: u8, + device: u8, + lba_3: u8, + lba_4: u8, + lba_5: u8, + _reserved_0: u8, + count_low: u8, + count_high: u8, + _reserved_1: u8, + new_status: u8, + transfer_count: u16, + _reserved_2: [u8;2], +} + +pub struct DmaSetup { + fis_type: FisType = FisType::DmaSetup, + port: u8, // Port information + _reserved_0: [u8;2], + dma_buffer_id: u64, + _reserved_1: [u8;4], + dmu_buffer_offset: u32, + transfer_count: u32, + _reserved_2: [u8;4], +} diff --git a/src/sata/hba.rs b/src/sata/hba.rs new file mode 100644 index 0000000..004793f --- /dev/null +++ b/src/sata/hba.rs @@ -0,0 +1,61 @@ +use crate::sata::fis; +pub struct CommandHeader { + fis_data: u8, + port: u8, + prdtl: u16, // Physical region descriptor table length in entries + prdbc: u32, // Physical region descriptor byte count transferred + ctba_lower: u32, // Command table descriptor base address + ctba_upper: u32, // Command table descriptor base address upper 32 bits + _reserved_0: [u32; 4], +} + +pub struct Port { + clb_lower: u32, // 0x00, command list base address, 1K-byte aligned + clb_upper: u32, // 0x04, command list base address upper 32 bits + fis_lower: u32, // 0x08, FIS base address, 256-byte aligned + fis_upper: u32, // 0x0C, FIS base address upper 32 bits + interrupt_status: u32, // 0x10, interrupt status + interrupt_enable: u32, // 0x14, interrupt enable + command_status: u32, // 0x18, command and status + _reserved_0: u32, // 0x1C, Reserved + task_file_data: u32, // 0x20, task file data + signature: u32, // 0x24, signature + sata_status: u32, // 0x28, SATA status (SCR0:SStatus) + sata_control: u32, // 0x2C, SATA control (SCR2:SControl) + sata_error: u32, // 0x30, SATA error (SCR1:SError) + sata_active: u32, // 0x34, SATA active (SCR3:SActive) + command_issue: u32, // 0x38, command issue + sata_notif: u32, // 0x3C, SATA notification (SCR4:SNotification) + fis_switch_control: u32, // 0x40, FIS-based switch control + _reserved_1: [u32;11] = [0;11], // 0x44 ~ 0x6F, Reserved + vendor_specific: [u32;4], // 0x70 ~ 0x7F, vendor specific +} + +pub struct Memory { + capabilities: u32, // 0x00, Host capability + global_host_control: u32, // 0x04, Global host control + interrupt_status: u32, // 0x08, Interrupt status + port_implemented: u32, // 0x0C, Port implemented + version: u32, // 0x10, Version + ccc_control: u32, // 0x14, Command completion coalescing control + ccc_ports: u32, // 0x18, Command completion coalescing ports + em_location: u32, // 0x1C, Enclosure management location + em_control: u32, // 0x20, Enclosure management control + capabilities_ext: u32, // 0x24, Host capabilities extended + handoff_control_status: u32, // 0x28, BIOS/OS handoff control and status + _reserved_0: [u8; 0xA0 - 0x2C], + vendor_specific: [u8; 0x100 - 0xA0], + ports: [Port; 32], +} + +pub struct Fis { + dma_setup_fis: fis::DmaSetup, + _reserved_0: [u8;4] = [0;4], + pio_setup_fis: fis::PioSetup, + _reserved_1: [u8;12] = [0;12], + reg_d2h_fis: fis::RegD2h, + _reserved_2: [u8;4] = [0;4], + set_bits_fis: u32, + ufis: [u8;64], + _reserved_3: [u8;0x100 - 0xA0], +} diff --git a/src/sata/mod.rs b/src/sata/mod.rs new file mode 100644 index 0000000..cf1daa4 --- /dev/null +++ b/src/sata/mod.rs @@ -0,0 +1,4 @@ +#![allow(dead_code)] + +mod fis; +mod hba;