started working on AHCI

This commit is contained in:
FantasyPvP
2024-11-21 16:59:52 +00:00
parent c68a0ecaa4
commit f8c942f6c8
5 changed files with 389 additions and 7 deletions
+6 -6
View File
@@ -46,8 +46,8 @@ lazy_static! {
Selectors {
code_selector,
data_selector,
// user_code_selector,
// user_data_selector,
user_code_selector,
user_data_selector,
tss_selector,
}
)
@@ -57,8 +57,8 @@ lazy_static! {
struct Selectors {
code_selector: SegmentSelector,
data_selector: SegmentSelector,
// user_code_selector: SegmentSelector,
// user_data_selector: SegmentSelector,
user_code_selector: SegmentSelector,
user_data_selector: SegmentSelector,
tss_selector: SegmentSelector,
}
@@ -72,8 +72,8 @@ pub fn init() {
load_tss(GDT.1.tss_selector);
// // Set up data segments
// DS::set_reg(GDT.1.data_selector);
// ES::set_reg(GDT.1.data_selector);
DS::set_reg(GDT.1.data_selector);
ES::set_reg(GDT.1.data_selector);
SS::set_reg(GDT.1.data_selector);
}
}
@@ -0,0 +1,59 @@
use x86_64::instructions::port::Port;
use crate::println_log;
use super::types::*;
pub fn probe_port(abar: &HbaMem) {
let pi = abar.pi;
for i in 0..32 {
if pi & 1 != 0 {
match check_type(&abar.ports[i]) {
PortSignature::Sata => {
println_log!("Found SATA port at {}", i);
},
PortSignature::Semb => {
println_log!("Found SEMB port at {}", i);
},
PortSignature::Pm => {
println_log!("Found PM port at {}", i);
},
PortSignature::Satapi => {
println_log!("Found SATAPI port at {}", i);
},
_ => {
println_log!("Unknown port type");
}
}
}
}
}
pub fn check_type(port: &HbaPort) -> PortSignature {
let ssts = port.ssts;
let ipm: u8 = ((ssts >> 8) & 0x0F) as u8;
let det: u8 = (ssts & 0x01) as u8;
if det != HBA_PORT_DET_PRESENT {
return PortSignature::Null;
}
if ipm != HBA_PORT_IPM_ACTIVE {
return PortSignature::Null;
}
return PortSignature::from(port.sig);
}
pub fn start_cmd(port: &mut HbaPort) {
while port.cmd & HBA_PXCMD_CR != 0 {};
port.cmd |= HBA_PXCMD_FRE;
port.cmd |= HBA_PXCMD_ST;
}
pub fn stop_cmd(port: &mut HbaPort) {
port.cmd &= !HBA_PXCMD_ST;
}
@@ -0,0 +1,3 @@
pub mod ahci;
mod types;
+319
View File
@@ -0,0 +1,319 @@
#[repr(u32)]
pub enum DeviceSignature {
Ata = 0x00000101,
Atapi = 0xEB140101,
Semb = 0xC33C0101,
Pm = 0x96690101,
Invalid = 0x00000000,
}
#[repr(u32)]
pub enum PortSignature {
Null = 0,
Sata = 1,
Semb = 2,
Pm = 3,
Satapi = 4,
}
impl From<u32> for PortSignature {
fn from(value: u32) -> Self {
match value {
0 => PortSignature::Null,
1 => PortSignature::Sata,
2 => PortSignature::Semb,
3 => PortSignature::Pm,
4 => PortSignature::Satapi,
_ => PortSignature::Null,
}
}
}
// useful constants
pub const HBA_PORT_IPM_ACTIVE: u8 = 1;
pub const HBA_PORT_DET_PRESENT: u8 = 3;
pub const HBA_PXCMD_ST: u32 = 0x0001;
pub const HBA_PXCMD_FRE: u32 = 0x0010;
pub const HBA_PXCMD_FR: u32 = 0x4000;
pub const HBA_PXCMD_CR: u32 = 0x8000;
// Following code defines different kinds of FIS specified in Serial ATA Revision 3.0.
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
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
}
// A host to device register FIS is used by the host to send command or control to a device.
// It contains IDE registers such as command, LBA, device, feature, count and control.
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct FisRegH2D {
// DWORD 0
pub fis_type: u8, // FIS_TYPE_REG_H2D
pub pmport_c: u8, // Port multiplier [7:4], Reserved [3:1], Command[0]
pub command: u8, // Command register
pub featurel: u8, // Feature register, 7:0
// DWORD 1
pub lba0: u8, // LBA low register, 7:0
pub lba1: u8, // LBA mid register, 15:8
pub lba2: u8, // LBA high register, 23:16
pub device: u8, // Device register
// DWORD 2
pub lba3: u8, // LBA register, 31:24
pub lba4: u8, // LBA register, 39:32
pub lba5: u8, // LBA register, 47:40
pub featureh: u8, // Feature register, 15:8
// DWORD 3
pub countl: u8, // Count register, 7:0
pub counth: u8, // Count register, 15:8
pub icc: u8, // Isochronous command completion
pub control: u8, // Control register
// DWORD 4
pub rsv1: [u8; 4], // Reserved
}
// A device to host register FIS is used by the device to notify the host
// that some ATA register has changed.
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct FisRegD2H {
// DWORD 0
pub fis_type: u8, // FIS_TYPE_REG_D2H
pub pmport_i: u8, // Port multiplier [7:4], Reserved [3:2], Interrupt [1], Reserved [0]
pub status: u8, // Status register
pub error: u8, // Error register
// DWORD 1
pub lba0: u8, // LBA low register, 7:0
pub lba1: u8, // LBA mid register, 15:8
pub lba2: u8, // LBA high register, 23:16
pub device: u8, // Device register
// DWORD 2
pub lba3: u8, // LBA register, 31:24
pub lba4: u8, // LBA register, 39:32
pub lba5: u8, // LBA register, 47:40
pub rsv2: u8, // Reserved
// DWORD 3
pub countl: u8, // Count register, 7:0
pub counth: u8, // Count register, 15:8
pub rsv3: [u8; 2], // Reserved
// DWORD 4
pub rsv4: [u8; 4], // Reserved
}
// This FIS is used by the host or device to send data payload.
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct FisData {
// DWORD 0
pub fis_type: u8, // FIS_TYPE_DATA
pub pmport: u8, // Port multiplier [7:4], Reserved [3:0]
pub rsv1: [u8; 2], // Reserved
// DWORD 1 ~ N
pub data: [u32; 1], // Payload
}
// This FIS is used by the device to tell the host that it's about to send
// or ready to receive a PIO data payload.
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct FisPioSetup {
// DWORD 0
pub fis_type: u8, // FIS_TYPE_PIO_SETUP
pub pmport_flags: u8, // Port multiplier [7:4], Reserved [3], Data transfer direction [2], Interrupt [1], Reserved [0]
pub status: u8, // Status register
pub error: u8, // Error register
// DWORD 1
pub lba0: u8, // LBA low register, 7:0
pub lba1: u8, // LBA mid register, 15:8
pub lba2: u8, // LBA high register, 23:16
pub device: u8, // Device register
// DWORD 2
pub lba3: u8, // LBA register, 31:24
pub lba4: u8, // LBA register, 39:32
pub lba5: u8, // LBA register, 47:40
pub rsv2: u8, // Reserved
// DWORD 3
pub countl: u8, // Count register, 7:0
pub counth: u8, // Count register, 15:8
pub rsv3: u8, // Reserved
pub e_status: u8, // New value of status register
// DWORD 4
pub tc: u16, // Transfer count
pub rsv4: [u8; 2], // Reserved
}
// DMA Setup - Device to Host
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct FisDmaSetup {
// DWORD 0
pub fis_type: u8, // FIS_TYPE_DMA_SETUP
pub pmport_flags: u8, // Port multiplier [7:4], Reserved [3], Data transfer direction [2], Interrupt [1], Auto-activate [0]
pub rsved: [u8; 2], // Reserved
// DWORD 1&2
pub dma_buffer_id: u64, // DMA Buffer Identifier
// DWORD 3
pub rsvd: u32, // More reserved
// DWORD 4
pub dma_buf_offset: u32, // Byte offset into buffer. First 2 bits must be 0
// DWORD 5
pub transfer_count: u32, // Number of bytes to transfer. Bit 0 must be 0
// DWORD 6
pub resvd: u32, // Reserved
}
// HBA Memory Registers Structure
#[repr(C)]
#[derive(Debug)]
pub struct HbaMem {
// 0x00 - 0x2B, Generic Host Control
pub cap: u32, // 0x00, Host capability
pub ghc: u32, // 0x04, Global host control
pub is: u32, // 0x08, Interrupt status
pub pi: u32, // 0x0C, Port implemented
pub vs: u32, // 0x10, Version
pub ccc_ctl: u32, // 0x14, Command completion coalescing control
pub ccc_pts: u32, // 0x18, Command completion coalescing ports
pub em_loc: u32, // 0x1C, Enclosure management location
pub em_ctl: u32, // 0x20, Enclosure management control
pub cap2: u32, // 0x24, Host capabilities extended
pub bohc: u32, // 0x28, BIOS/OS handoff control and status
// 0x2C - 0x9F, Reserved
pub rsv: [u8; 0xA0-0x2C],
// 0xA0 - 0xFF, Vendor specific registers
pub vendor: [u8; 0x100-0xA0],
// 0x100 - 0x10FF, Port control registers
pub ports: [HbaPort; 1], // 1 ~ 32
}
// HBA Port Structure
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct HbaPort {
pub clb: u32, // 0x00, command list base address, 1K-byte aligned
pub clbu: u32, // 0x04, command list base address upper 32 bits
pub fb: u32, // 0x08, FIS base address, 256-byte aligned
pub fbu: u32, // 0x0C, FIS base address upper 32 bits
pub is: u32, // 0x10, interrupt status
pub ie: u32, // 0x14, interrupt enable
pub cmd: u32, // 0x18, command and status
pub rsv0: u32, // 0x1C, Reserved
pub tfd: u32, // 0x20, task file data
pub sig: u32, // 0x24, signature
pub ssts: u32, // 0x28, SATA status (SCR0:SStatus)
pub sctl: u32, // 0x2C, SATA control (SCR2:SControl)
pub serr: u32, // 0x30, SATA error (SCR1:SError)
pub sact: u32, // 0x34, SATA active (SCR3:SActive)
pub ci: u32, // 0x38, command issue
pub sntf: u32, // 0x3C, SATA notification (SCR4:SNotification)
pub fbs: u32, // 0x40, FIS-based switch control
pub rsv1: [u32; 11], // 0x44 ~ 0x6F, Reserved
pub vendor: [u32; 4], // 0x70 ~ 0x7F, vendor specific
}
// HBA FIS Structure
#[repr(C)]
#[derive(Debug)]
pub struct HbaFis {
// 0x00
pub dsfis: FisDmaSetup, // DMA Setup FIS
pub pad0: [u8; 4],
// 0x20
pub psfis: FisPioSetup, // PIO Setup FIS
pub pad1: [u8; 12],
// 0x40
pub rfis: FisRegD2H, // Register Device to Host FIS
pub pad2: [u8; 4],
// 0x58
pub sdbfis: [u8; 8], // Set Device Bit FIS
// 0x60
pub ufis: [u8; 64],
// 0xA0
pub rsv: [u8; 0x100-0xA0],
}
// Command List Structure
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct HbaCmdHeader {
// DW0
pub flags: u16, // Command FIS length and flags
pub prdtl: u16, // Physical region descriptor table length in entries
// DW1
pub prdbc: u32, // Physical region descriptor byte count transferred
// DW2, 3
pub ctba: u32, // Command table descriptor base address
pub ctbau: u32, // Command table descriptor base address upper 32 bits
// DW4 - 7
pub rsv1: [u32; 4], // Reserved
}
// Command Table Structure
#[repr(C)]
#[derive(Debug)]
pub struct HbaCmdTbl {
// 0x00
pub cfis: [u8; 64], // Command FIS
// 0x40
pub acmd: [u8; 16], // ATAPI command, 12 or 16 bytes
// 0x50
pub rsv: [u8; 48], // Reserved
// 0x80
pub prdt_entry: [HbaPrdtEntry; 1], // Physical region descriptor table entries, 0 ~ 65535
}
// Physical Region Descriptor Table Entry
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct HbaPrdtEntry {
pub dba: u32, // Data base address
pub dbau: u32, // Data base address upper 32 bits
pub rsv0: u32, // Reserved
// DW3
pub dbc_and_flags: u32, // Byte count and flags
}
+2 -1
View File
@@ -1,2 +1,3 @@
pub mod framebuffer;
pub mod serial;
pub mod serial;
pub mod ahci;