kernel/devices/
ide.rs

1use core::{
2    fmt, hint, mem,
3    ptr::{addr_of, addr_of_mut},
4    sync::atomic::AtomicBool,
5};
6
7use alloc::sync::Arc;
8use tracing::{error, info};
9
10use crate::{
11    cpu::{
12        self,
13        idt::{BasicInterruptHandler, InterruptStackFrame64},
14        interrupts::apic,
15    },
16    memory_management::memory_layout::MemSize,
17    sync::spin::mutex::Mutex,
18};
19
20use super::pci::{self, PciDevice, PciDeviceConfig, PciDeviceType, ProbeExtra};
21
22static mut IDE_DEVICES: [Option<Arc<IdeDevice>>; 4] = [None, None, None, None];
23static INTERRUPTS_SETUP: AtomicBool = AtomicBool::new(false);
24
25pub fn try_register_ide_device(pci_device: &PciDeviceConfig) -> bool {
26    let PciDeviceType::MassStorageController(..) = pci_device.device_type else {
27        return false;
28    };
29
30    let mut found_device = false;
31    for i in 0..2 {
32        // i = 0 => primary
33        // i = 1 => secondary
34        for j in 0..2 {
35            // j = 0 => master
36            // j = 1 => slave
37            let extra = ProbeExtra { args: [i, j, 0, 0] };
38            let Some(ide_device) = IdeDevice::probe_init(pci_device, extra) else {
39                continue;
40            };
41
42            // SAFETY: we are muting only to add elements, and we are not accessing the old elements or changing them
43            let ide_devices = unsafe { addr_of_mut!(IDE_DEVICES).as_mut().unwrap() };
44            let slot = ide_devices.iter_mut().find(|x| x.is_none());
45
46            if let Some(slot) = slot {
47                // must be done after initializing the heap, i.e. after virtual memory
48                *slot = Some(Arc::new(ide_device));
49                found_device = true;
50            } else {
51                panic!("No more IDE devices can be registered!");
52            }
53        }
54    }
55
56    found_device
57}
58
59#[repr(u8)]
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub enum IdeDeviceType {
62    Ata,
63    Atapi,
64}
65
66#[derive(Debug, Clone, Copy)]
67pub struct IdeDeviceIndex {
68    pub ty: IdeDeviceType,
69    pub index: usize,
70}
71
72pub fn get_ide_device(index: IdeDeviceIndex) -> Option<Arc<IdeDevice>> {
73    let ide_devices = unsafe { addr_of!(IDE_DEVICES).as_ref().unwrap() };
74    let mut passed = 0;
75    if index.index < ide_devices.len() {
76        for ide_device in ide_devices.iter().filter_map(Option::as_ref) {
77            if ide_device.device_type == index.ty {
78                if passed == index.index {
79                    return Some(ide_device.clone());
80                }
81                passed += 1;
82            }
83        }
84    }
85    None
86}
87
88#[allow(dead_code)]
89mod pci_cfg {
90    // program interface
91    pub const PROG_IF_PRIMARY: u8 = 1 << 0;
92    pub const PROG_IF_PRIMARY_PROGRAMMABLE: u8 = 1 << 1;
93    pub const PROG_IF_SECONDARY: u8 = 1 << 2;
94    pub const PROG_IF_SECONDARY_PROGRAMMABLE: u8 = 1 << 3;
95    pub const PROG_IF_MASTER: u8 = 1 << 7;
96
97    pub const DEFAULT_PRIMARY_IO: (u16, u16) = (0x1F0, 0x3F6);
98    pub const DEFAULT_SECONDARY_IO: (u16, u16) = (0x170, 0x376);
99
100    // commands
101    pub const CMD_IO_SPACE: u16 = 1 << 0;
102    pub const CMD_MEM_SPACE: u16 = 1 << 1;
103    pub const CMD_BUS_MASTER: u16 = 1 << 2;
104    pub const CMD_INT_DISABLE: u16 = 1 << 10;
105
106    // interrupts
107    pub const CFG_CONTROL_REG: u8 = 0x40;
108    pub const DEFAULT_PRIMARY_INTERRUPT: u8 = 14;
109    pub const DEFAULT_SECONDARY_INTERRUPT: u8 = 15;
110}
111
112#[allow(dead_code)]
113mod ata {
114    pub const DATA: u16 = 0x0;
115
116    pub const ERROR: u16 = 0x1;
117    pub const FEATURES: u16 = 0x1;
118
119    pub const SECTOR_COUNT: u16 = 0x2;
120    pub const LBA_LO: u16 = 0x3;
121    pub const LBA_MID: u16 = 0x4;
122    pub const LBA_HI: u16 = 0x5;
123
124    pub const DRIVE: u16 = 0x6;
125
126    pub const COMMAND: u16 = 0x7;
127    pub const STATUS: u16 = 0x7;
128
129    pub const ALT_STATUS: u16 = 0x0;
130    pub const DEV_CONTROL: u16 = 0x0;
131
132    pub const ERROR_ILL_LENGTH: u8 = 1 << 0;
133    pub const ERROR_END_OF_MEDIA: u8 = 1 << 1;
134    pub const ERROR_ABORTED: u8 = 1 << 2;
135    pub const ERROR_ID_NOT_FOUND: u8 = 1 << 4;
136    pub const ERROR_UNCORRECTABLE: u8 = 1 << 6;
137    pub const ERROR_BAD_BLOCK: u8 = 1 << 7;
138    // specific to SCSI
139    pub const ERROR_SENSE_KEY: u8 = 0xF << 4;
140
141    pub const SENSE_OK: u8 = 0x0;
142    pub const SENSE_RECOVERED_ERROR: u8 = 0x1;
143    pub const SENSE_NOT_READY: u8 = 0x2;
144    pub const SENSE_MEDIUM_ERROR: u8 = 0x3;
145    pub const SENSE_HARDWARE_ERROR: u8 = 0x4;
146    pub const SENSE_ILLEGAL_REQUEST: u8 = 0x5;
147    pub const SENSE_UNIT_ATTENTION: u8 = 0x6;
148    pub const SENSE_DATA_PROTECT: u8 = 0x7;
149    pub const SENSE_BLANK_CHECK: u8 = 0x8;
150    pub const SENSE_VENDOR_SPECIFIC: u8 = 0x9;
151    pub const SENSE_COPY_ABORTED: u8 = 0xA;
152    pub const SENSE_ABORTED_COMMAND: u8 = 0xB;
153    pub const SENSE_VOLUME_OVERFLOW: u8 = 0xD;
154    pub const SENSE_MISCOMPARE: u8 = 0xE;
155
156    pub const STATUS_ERR: u8 = 1 << 0;
157    pub const STATUS_SENSE_DATA: u8 = 1 << 1;
158    pub const STATUS_ALIGN_ERR: u8 = 1 << 2;
159    pub const STATUS_DATA_REQUEST: u8 = 1 << 3;
160    pub const STATUS_DEFERRED_WRITE_ERR: u8 = 1 << 4;
161    pub const STATUS_DRIVE_FAULT: u8 = 1 << 5;
162    pub const STATUS_READY: u8 = 1 << 6;
163    pub const STATUS_BUSY: u8 = 1 << 7;
164
165    pub const COMMAND_IDENTIFY: u8 = 0xEC;
166    pub const COMMAND_PACKET_IDENTIFY: u8 = 0xA1;
167    pub const COMMAND_READ_SECTORS: u8 = 0x20;
168    pub const COMMAND_WRITE_SECTORS: u8 = 0x30;
169    pub const COMMAND_DEVICE_RESET: u8 = 0x08;
170    pub const COMMAND_PACKET: u8 = 0xA0;
171
172    pub const PACKET_FEAT_DMA: u8 = 1 << 0;
173    pub const PACKET_FEAT_DMA_DIR_FROM_DEVICE: u8 = 1 << 2;
174
175    pub const PACKET_CMD_READ_10: u8 = 0x28;
176    pub const PACKET_CMD_INQUIRY: u8 = 0x12;
177    pub const PACKET_CMD_TEST_UNIT_READY: u8 = 0x00;
178    pub const PACKET_CMD_READ_CAPACITY: u8 = 0x25;
179
180    pub const PACKET_INQUIRY_VITAL_DATA: u8 = 0x1;
181    pub const PACKET_VITAL_PAGE_SUPPORTED_PAGES: u8 = 0x00;
182    pub const PACKET_VITAL_PAGE_DEVICE_IDENTIFY: u8 = 0x83;
183    pub const PACKET_VITAL_PAGE_BLOCK_LIMITS: u8 = 0xB0;
184    pub const PACKET_VITAL_PAGE_BLOCK_LIMITS_SIZE: u16 = 64;
185
186    // size of a sector in bytes
187    pub const DEFAULT_SECTOR_SIZE: u32 = 512;
188}
189
190#[derive(Debug, Clone, Copy)]
191pub struct IdeIo {
192    pub command_block: u16,
193    pub control_block: u16,
194}
195
196impl IdeIo {
197    // until not busy
198    pub fn wait_until_free(&self) {
199        let mut status = self.read_status();
200        while status & ata::STATUS_BUSY != 0 {
201            hint::spin_loop();
202            status = self.read_status();
203        }
204    }
205
206    pub fn wait_until_can_command(&self) -> Result<(), u8> {
207        self.wait_until_free();
208
209        let mut status = self.read_status();
210        while status & (ata::STATUS_BUSY | ata::STATUS_DATA_REQUEST) != 0 {
211            if status & ata::STATUS_ERR != 0 {
212                return Err(self.read_error());
213            }
214            hint::spin_loop();
215            status = self.read_status();
216        }
217        Ok(())
218    }
219
220    pub fn read_data(&self) -> u16 {
221        unsafe { cpu::io_in(self.command_block + ata::DATA) }
222    }
223
224    pub fn write_data(&self, value: u16) {
225        unsafe { cpu::io_out(self.command_block + ata::DATA, value) }
226    }
227
228    pub fn read_status(&self) -> u8 {
229        self.read_command_block(ata::STATUS)
230    }
231
232    /// Note that this is only valid if the device is not busy
233    /// and has the `ERROR` status bit set
234    pub fn read_error(&self) -> u8 {
235        self.read_command_block(ata::ERROR)
236    }
237
238    // ATAPI only
239    pub fn read_sense_key(&self) -> u8 {
240        self.read_error() >> 4
241    }
242
243    pub fn read_command_block(&self, offset: u16) -> u8 {
244        unsafe { cpu::io_in(self.command_block + offset) }
245    }
246
247    pub fn write_command_block(&self, offset: u16, value: u8) {
248        unsafe { cpu::io_out(self.command_block + offset, value) }
249    }
250
251    #[allow(dead_code)]
252    pub fn read_control_block(&self, offset: u16) -> u8 {
253        unsafe { cpu::io_in(self.control_block + offset) }
254    }
255
256    #[allow(dead_code)]
257    pub fn write_control_block(&self, offset: u16, value: u8) {
258        unsafe { cpu::io_out(self.control_block + offset, value) }
259    }
260
261    pub fn read_data_block(&self, data: &mut [u8]) -> Result<(), u8> {
262        if self.read_status() & ata::STATUS_ERR != 0 {
263            // error
264            return Err(self.read_error());
265        }
266
267        // read data
268        for i in 0..data.len() / 2 {
269            if i.is_multiple_of(256) {
270                self.wait_until_free();
271            }
272
273            let word = self.read_data();
274            data[i * 2] = (word & 0xFF) as u8;
275            data[i * 2 + 1] = ((word >> 8) & 0xFF) as u8;
276        }
277
278        self.wait_until_free();
279
280        // TODO: replace with error
281        assert_eq!(self.read_status() & ata::STATUS_DATA_REQUEST, 0);
282
283        Ok(())
284    }
285
286    pub fn write_data_block(&self, data: &[u8]) -> Result<(), u8> {
287        if self.read_status() & ata::STATUS_ERR != 0 {
288            // error
289            return Err(self.read_error());
290        }
291
292        // write data
293        for i in 0..data.len() / 2 {
294            if i.is_multiple_of(256) {
295                self.wait_until_free();
296            }
297
298            let word = (data[i * 2] as u16) | ((data[i * 2 + 1] as u16) << 8);
299
300            self.write_data(word);
301        }
302
303        self.wait_until_free();
304
305        // TODO: replace with error
306        assert_eq!(self.read_status() & ata::STATUS_DATA_REQUEST, 0);
307
308        Ok(())
309    }
310}
311
312#[derive(Debug, Clone, Copy)]
313struct AtaCommand {
314    command: u8,
315    drive: u8,
316    lba: u64,
317    sector_count: u8,
318    features: u8,
319}
320
321impl AtaCommand {
322    pub fn new(command: u8) -> Self {
323        Self {
324            command,
325            drive: 0x40, // always have the 6th bit set (LBA mode)
326            lba: 0,
327            sector_count: 0,
328            features: 0,
329        }
330    }
331
332    #[allow(dead_code)]
333    pub fn with_features(mut self, features: u8) -> Self {
334        self.features = features;
335        self
336    }
337
338    pub fn with_second_drive(mut self, is_second: bool) -> Self {
339        if is_second {
340            self.drive |= 1 << 4;
341        } else {
342            self.drive &= !(1 << 4);
343        }
344        self
345    }
346
347    pub fn with_lba(mut self, lba: u64) -> Self {
348        self.lba = lba;
349        self
350    }
351
352    pub fn with_sector_count(mut self, sector_count: u8) -> Self {
353        self.sector_count = sector_count;
354        self
355    }
356
357    pub fn write(&self, io_port: &IdeIo) {
358        io_port.write_command_block(ata::FEATURES, self.features);
359        io_port.write_command_block(ata::SECTOR_COUNT, self.sector_count);
360        io_port.write_command_block(ata::LBA_LO, (self.lba & 0xFF) as u8);
361        io_port.write_command_block(ata::LBA_MID, ((self.lba >> 8) & 0xFF) as u8);
362        io_port.write_command_block(ata::LBA_HI, ((self.lba >> 16) & 0xFF) as u8);
363        io_port.write_command_block(ata::DRIVE, self.drive);
364        io_port.write_command_block(ata::COMMAND, self.command);
365    }
366
367    pub fn execute_read(&self, io_port: &IdeIo, data: &mut [u8]) -> Result<(), u8> {
368        // must be even since we are receiving 16 bit words
369        assert_eq!(data.len() % 2, 0);
370        io_port.wait_until_can_command()?;
371        self.write(io_port);
372
373        io_port.read_data_block(data)
374    }
375
376    pub fn execute_write(&self, io_port: &IdeIo, data: &[u8]) -> Result<(), u8> {
377        // must be even since we are sending 16 bit words
378        assert_eq!(data.len() % 2, 0);
379        io_port.wait_until_can_command()?;
380        self.write(io_port);
381
382        io_port.write_data_block(data)
383    }
384}
385
386#[derive(Debug, Clone, Copy)]
387#[allow(dead_code)]
388enum AtapiDmaDirection {
389    FromDevice,
390    ToDevice,
391    None,
392}
393
394#[derive(Debug, Clone, Copy)]
395struct AtapiPacketCommand {
396    drive: u8,
397    dma: AtapiDmaDirection,
398    lba: u64,
399    params: [u8; 32],
400
401    params_index: usize,
402}
403
404impl AtapiPacketCommand {
405    pub fn new(command: u8) -> Self {
406        let mut params = [0; 32];
407        params[0] = command;
408        Self {
409            drive: 0x40, // always have the 6th bit set (LBA mode)
410            dma: AtapiDmaDirection::None,
411            lba: 0xFFFF00, // byte count limit of 0xFFFF (should be ignored if not needed)
412            params,
413            params_index: 1,
414        }
415    }
416
417    #[allow(dead_code)]
418    pub fn with_dma(mut self, dma: AtapiDmaDirection) -> Self {
419        self.dma = dma;
420        self
421    }
422
423    pub fn with_second_drive(mut self, is_second: bool) -> Self {
424        if is_second {
425            self.drive |= 1 << 4;
426        } else {
427            self.drive &= !(1 << 4);
428        }
429        self
430    }
431
432    #[allow(dead_code)]
433    pub fn with_byte_count_limit(mut self, byte_count_limit: u16) -> Self {
434        self.lba = (byte_count_limit as u64) << 8;
435        self
436    }
437
438    pub fn push_param(mut self, param: u8) -> Self {
439        self.params[self.params_index] = param;
440        self.params_index += 1;
441        self
442    }
443
444    // msb first, lsb last
445    pub fn push_param_u16(self, param: u16) -> Self {
446        self.push_param((param >> 8) as u8)
447            .push_param((param & 0xFF) as u8)
448    }
449
450    // msb first, lsb last
451    pub fn push_param_u32(self, param: u32) -> Self {
452        self.push_param((param >> 24) as u8)
453            .push_param((param >> 16) as u8)
454            .push_param((param >> 8) as u8)
455            .push_param((param & 0xFF) as u8)
456    }
457
458    pub fn write_packet_command(&self, io_port: &IdeIo) {
459        let features = match self.dma {
460            AtapiDmaDirection::FromDevice => {
461                ata::PACKET_FEAT_DMA | ata::PACKET_FEAT_DMA_DIR_FROM_DEVICE
462            }
463            AtapiDmaDirection::ToDevice => ata::PACKET_FEAT_DMA,
464            AtapiDmaDirection::None => 0,
465        };
466
467        io_port.write_command_block(ata::FEATURES, features);
468        io_port.write_command_block(ata::SECTOR_COUNT, 0);
469        io_port.write_command_block(ata::LBA_LO, (self.lba & 0xFF) as u8);
470        io_port.write_command_block(ata::LBA_MID, ((self.lba >> 8) & 0xFF) as u8);
471        io_port.write_command_block(ata::LBA_HI, ((self.lba >> 16) & 0xFF) as u8);
472        io_port.write_command_block(ata::DRIVE, self.drive);
473        io_port.write_command_block(ata::COMMAND, ata::COMMAND_PACKET);
474    }
475
476    pub fn execute(&self, io_port: &IdeIo, data: &mut [u8]) -> Result<(), u8> {
477        // must be even since we are receiving 16 bit words
478        assert_eq!(data.len() % 2, 0);
479        io_port.wait_until_can_command()?;
480        self.write_packet_command(io_port);
481        io_port.wait_until_free();
482
483        if io_port.read_status() & ata::STATUS_ERR != 0 {
484            // ATAPI uses SENSE key
485            return Err(io_port.read_sense_key());
486        }
487
488        // write command
489        let mut param_count = self.params_index;
490        // make sure its even
491        if param_count & 1 == 1 {
492            param_count += 1;
493        }
494        // SAFETY: we are sure that the params are aligned to u16
495        for &param in unsafe { self.params[..param_count].align_to::<u16>().1 } {
496            io_port.write_data(param);
497        }
498        // if for some reason it expects more data
499        // push until satisfied
500        // since `DATA_REQUEST` is also used to denote that there is data present
501        // we might miss that the device is sending us data and not waiting for more data from us,
502        // we should break if that's the case
503        let mut max = 32;
504        while io_port.read_status() & ata::STATUS_DATA_REQUEST != 0 {
505            io_port.write_data(0);
506            max -= 1;
507            if max == 0 {
508                break;
509            }
510        }
511
512        // convert error to sense key
513        io_port.read_data_block(data).map_err(|e| e >> 4)
514    }
515}
516
517#[repr(C, packed(2))]
518#[derive(Debug)]
519struct CommandIdentifyDataRaw {
520    general_config: u16,
521    obsolete1: u16,
522    specific_config: u16,
523    obsolete2: [u16; 4],
524    reserved_cfa1: [u16; 2],
525    obsolete3: u16,
526    serial_number: [u8; 20],
527    obsolete4: [u16; 3],
528    firmware_revision: [u8; 8],
529    model_number: [u8; 40],
530    // Bits 7:0 of this word define the maximum number of logical sectors
531    // per DRQ data block that the device supports for READ MULTIPLE
532    // commands (see 7.26), READ MULTIPLE EXT commands (see 7.27),
533    // WRITE MULTIPLE commands (see 7.64), WRITE MULTIPLE EXT
534    // commands (see 7.65), and WRITE MULTIPLE EXT FUA commands (see 7.66).
535    //
536    // For SATA devices, bits 7:0 shall be set to 16 or less.
537    max_sectors_per_multiple_commands: u16,
538    trusted_computing_features: u16,
539    capabilities: [u16; 2],
540    obsolete6: [u16; 2],
541    unk_53: u16,
542    obsolete7: [u16; 5],
543    unk_59: u16,
544    user_addressable_sectors_28_mode: u32,
545    obsolete8: u16,
546    unk_63: u16,
547    unk_64: u16,
548    min_multiword_dma_transfer_cycle_time: u16,
549    recommended_multiword_dma_transfer_cycle_time: u16,
550    min_pio_transfer_cycle_time_no_flow_control: u16,
551    min_pio_transfer_cycle_time_with_ioready: u16,
552    additional_supported: u16,
553    reserved: u16,
554    // reserved fir IDENTIFY PACKET DEVICE command
555    reserved2: [u16; 4],
556    queue_depth: u16,
557    serial_ata_capabilities: [u16; 2],
558    serial_ata_features_supported: u16,
559    serial_ata_features_enabled: u16,
560    major_version: u16,
561    minor_version: u16,
562    command_set_supported_or_enabled: [u16; 6],
563    ultra_dma_modes: u16,
564    unk_89: u16,
565    unk_90: u16,
566    current_apm_level: u16,
567    master_password_id: u16,
568    hardware_reset_result: u16,
569    obsolete9: u16,
570    stream_min_request_size: u16,
571    stream_dma_time: u16,
572    stream_access_latency: u16,
573    stream_performance_granularity: u32,
574    user_addressable_sectors: u64,
575    streaming_transfer_time: u16,
576    max_blocks_per_data_set_management: u16,
577    physical_logical_sector_size: u16,
578    interseek_delay_for_iso_7779: u16,
579    world_wide_name: [u16; 4],
580    reserved3: [u16; 4],
581    obsolete10: u16,
582    logical_sector_size: u32,
583    command_set_supported_or_enabled2: [u16; 2],
584    reserved4: [u16; 4],
585    atapi_byte_count_behavior: u16,
586    reserved5: u16,
587    obsolete11: u16,
588    security_status: u16,
589    vendor_specific: [u16; 31],
590    reserved_cfa2: [u16; 8],
591    device_nominal_form_factor: u16,
592    data_set_management_trim_support: u16,
593    additional_product_id: [u16; 4],
594    reserved6: [u16; 2],
595    current_media_serial_number: [u16; 30],
596    sct_command_transport: u16,
597    reserved7: [u16; 2],
598    logical_sectors_alignment: u16,
599    write_read_verify_sector_count_mode3: u32,
600    write_read_verify_sector_count_mode2: u32,
601    obsolete12: [u16; 3],
602    nominal_media_rotation_rate: u16,
603    reserved8: u16,
604    obsolete13: u16,
605    write_read_verify_feature_set_current_mode: u16,
606    reserved9: u16,
607    transport_major_version: u16,
608    transport_minor_version: u16,
609    reserved10: [u16; 6],
610    extended_user_addressable_sectors: u64,
611    min_blocks_per_download_microcode: u16,
612    max_blocks_per_download_microcode: u16,
613    reserved11: [u16; 19],
614    integrity_word: u16,
615}
616
617impl CommandIdentifyDataRaw {
618    fn is_valid(&self) -> bool {
619        // check the `general_config` is valid
620        // check that the serial number is not empty
621        // and not all is 0xFF
622        ((self.general_config >> 8) != 0xFF && (self.general_config >> 8) != 0x7F)
623            && self.serial_number.iter().any(|x| *x != 0)
624            && self.serial_number.iter().any(|x| *x != 0xFF)
625    }
626
627    fn is_dma_supported(&self) -> bool {
628        self.capabilities[0] & (1 << 8) != 0
629    }
630
631    fn is_lba_supported(&self) -> bool {
632        self.capabilities[0] & (1 << 9) != 0
633    }
634
635    fn is_lba48_supported(&self) -> bool {
636        self.command_set_supported_or_enabled[1] & (1 << 10) != 0
637    }
638
639    fn user_addressable_sectors(&self) -> u64 {
640        if self.is_lba48_supported() {
641            let extended_number_of_sectors_supported = self.additional_supported & (1 << 3) != 0;
642
643            if extended_number_of_sectors_supported {
644                self.extended_user_addressable_sectors
645            } else {
646                self.user_addressable_sectors
647            }
648        } else {
649            self.user_addressable_sectors_28_mode as u64
650        }
651    }
652
653    // Return the size of the logical sector in bytes
654    fn sector_size(&self) -> u32 {
655        let large_logical_sector_supported = self.physical_logical_sector_size & (1 << 12) != 0;
656        if large_logical_sector_supported && self.logical_sector_size != 0 {
657            assert!(self.logical_sector_size >= 256);
658            // the value here is in bytes
659            self.logical_sector_size * 2
660        } else {
661            // default value
662            ata::DEFAULT_SECTOR_SIZE
663        }
664    }
665}
666
667#[derive(Debug, Clone, Copy)]
668pub enum IdeError {
669    DeviceError(u8),
670    UnalignedSize,
671    BoundsExceeded,
672}
673
674impl fmt::Display for IdeError {
675    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
676        match self {
677            IdeError::DeviceError(err) => write!(f, "IDE device error: {err}"),
678            IdeError::UnalignedSize => write!(f, "unaligned size"),
679            IdeError::BoundsExceeded => write!(f, "bounds exceeded"),
680        }
681    }
682}
683
684#[allow(dead_code)]
685#[derive(Debug)]
686pub struct IdeDevice {
687    device_impl: Mutex<IdeDeviceImpl>,
688    device_type: IdeDeviceType,
689    number_of_sectors: u64,
690    sector_size: u32,
691
692    second_device_select: bool,
693}
694
695impl IdeDevice {
696    fn init_new(
697        master_io: Option<u16>,
698        io: IdeIo,
699        pci_device: &PciDeviceConfig,
700        second_device_select: bool,
701    ) -> Option<Self> {
702        IdeDeviceImpl::init_new(master_io, io, pci_device, second_device_select)
703    }
704
705    pub fn interrupt(&self) {
706        self.device_impl.lock().interrupt();
707    }
708
709    pub fn is_primary(&self) -> bool {
710        !self.second_device_select
711    }
712
713    pub fn is_secondary(&self) -> bool {
714        self.second_device_select
715    }
716
717    #[allow(dead_code)]
718    pub fn number_of_sectors(&self) -> u64 {
719        self.number_of_sectors
720    }
721
722    pub fn sector_size(&self) -> u32 {
723        self.sector_size
724    }
725
726    pub fn read_sync(&self, mut start_sector: u64, mut data: &mut [u8]) -> Result<(), IdeError> {
727        let sector_size = self.sector_size as u64;
728        let buffer_len = data.len() as u64;
729
730        if !buffer_len.is_multiple_of(sector_size) {
731            return Err(IdeError::UnalignedSize);
732        }
733        let mut number_of_sectors = buffer_len / sector_size;
734
735        if start_sector
736            .checked_add(number_of_sectors)
737            .ok_or(IdeError::BoundsExceeded)?
738            >= self.number_of_sectors
739        {
740            return Err(IdeError::BoundsExceeded);
741        }
742
743        if self.device_type == IdeDeviceType::Ata {
744            let mut device = self.device_impl.lock();
745
746            while number_of_sectors != 0 {
747                let num_now = number_of_sectors.min(255);
748                assert!(number_of_sectors >= num_now);
749                number_of_sectors -= num_now;
750
751                let (now_data, afterward) = data.split_at_mut((num_now * sector_size) as usize);
752
753                device
754                    .read_sync_ata(start_sector, num_now, now_data)
755                    .map_err(IdeError::DeviceError)?;
756
757                start_sector += num_now;
758                data = afterward;
759            }
760
761            Ok(())
762        } else {
763            self.device_impl
764                .lock()
765                .read_sync_atapi(start_sector, number_of_sectors, data)
766                .map_err(IdeError::DeviceError)
767        }
768    }
769
770    pub fn write_sync(&self, mut start_sector: u64, mut data: &[u8]) -> Result<(), IdeError> {
771        let sector_size = self.sector_size as u64;
772        let buffer_len = data.len() as u64;
773
774        if !buffer_len.is_multiple_of(sector_size) {
775            return Err(IdeError::UnalignedSize);
776        }
777        let mut number_of_sectors = buffer_len / sector_size;
778
779        if start_sector
780            .checked_add(number_of_sectors)
781            .ok_or(IdeError::BoundsExceeded)?
782            >= self.number_of_sectors
783        {
784            return Err(IdeError::BoundsExceeded);
785        }
786
787        if self.device_type == IdeDeviceType::Ata {
788            let mut device = self.device_impl.lock();
789
790            while number_of_sectors != 0 {
791                let num_now = number_of_sectors.min(255);
792                assert!(number_of_sectors >= num_now);
793                number_of_sectors -= num_now;
794
795                let (now_data, afterward) = data.split_at((num_now * sector_size) as usize);
796
797                device
798                    .write_sync_ata(start_sector, num_now, now_data)
799                    .map_err(IdeError::DeviceError)?;
800
801                start_sector += num_now;
802                data = afterward;
803            }
804
805            Ok(())
806        } else {
807            todo!("write_sync for ATAPI");
808        }
809    }
810}
811
812#[allow(dead_code)]
813#[derive(Debug)]
814struct IdeDeviceImpl {
815    // if this is None, then DMA is not supported
816    master_io: Option<u16>,
817    io: IdeIo,
818    pci_device: PciDeviceConfig,
819    identify_data: CommandIdentifyDataRaw,
820    second_device_select: bool,
821}
822
823impl IdeDeviceImpl {
824    fn init_new(
825        mut master_io: Option<u16>,
826        io: IdeIo,
827        pci_device: &PciDeviceConfig,
828        second_device_select: bool,
829    ) -> Option<IdeDevice> {
830        // identify device
831        let mut identify_data = [0u8; 512];
832        let command =
833            AtaCommand::new(ata::COMMAND_IDENTIFY).with_second_drive(second_device_select);
834
835        let mut device_type = IdeDeviceType::Ata;
836
837        if let Err(err) = command.execute_read(&io, &mut identify_data) {
838            assert_ne!(err & ata::ERROR_ABORTED, 0);
839            let lbalo = io.read_command_block(ata::LBA_LO);
840            let lbamid = io.read_command_block(ata::LBA_MID);
841            let lbahi = io.read_command_block(ata::LBA_HI);
842
843            // ATAPI
844            if lbalo == 0x1 && lbamid == 0x14 && lbahi == 0xEB {
845                // check that the device is running
846                let command = AtapiPacketCommand::new(ata::PACKET_CMD_TEST_UNIT_READY)
847                    .with_second_drive(second_device_select);
848                if let Err(err) = command.execute(&io, &mut []) {
849                    if err == ata::SENSE_NOT_READY {
850                        // device not ready (i.e. not present)
851                    } else {
852                        error!("unknown ATAPI device error: Err={err:02x}");
853                    }
854                    return None;
855                }
856            } else {
857                error!("unknown IDE device aborted: LBA={lbalo:02x}:{lbamid:02x}:{lbahi:02x}",);
858                return None;
859            }
860
861            // here we know we are running an ATAPI device
862            let command = AtaCommand::new(ata::COMMAND_PACKET_IDENTIFY)
863                .with_second_drive(second_device_select);
864            if let Err(err) = command.execute_read(&io, &mut identify_data) {
865                error!("unknown ATAPI device aborted: Err={err:02x}",);
866                return None;
867            }
868            device_type = IdeDeviceType::Atapi;
869        }
870
871        assert_eq!(
872            mem::size_of::<CommandIdentifyDataRaw>(),
873            identify_data.len()
874        );
875        let identify_data: CommandIdentifyDataRaw = unsafe { mem::transmute(identify_data) };
876
877        if !identify_data.is_valid() {
878            // device is not valid
879            return None;
880        }
881
882        if !identify_data.is_dma_supported() {
883            // DMA is not supported
884            master_io = None;
885        }
886        if !identify_data.is_lba_supported() {
887            // panic so that it's easier to catch
888            panic!("IDE device does not support LBA mode");
889        }
890
891        let number_of_sectors;
892        let sector_size;
893        match device_type {
894            IdeDeviceType::Ata => {
895                number_of_sectors = identify_data.user_addressable_sectors();
896                sector_size = identify_data.sector_size();
897            }
898            IdeDeviceType::Atapi => {
899                let mut capacity_data = [0u8; 8];
900                let command = AtapiPacketCommand::new(ata::PACKET_CMD_READ_CAPACITY)
901                    .with_second_drive(second_device_select);
902                command.execute(&io, &mut capacity_data).unwrap();
903
904                // data returned is in big endian
905
906                // the number of sectors is the last 4 bytes
907                // this denotes the maximum addressable sector, so we add 1
908                number_of_sectors = u32::from_be_bytes([
909                    capacity_data[0],
910                    capacity_data[1],
911                    capacity_data[2],
912                    capacity_data[3],
913                ]) as u64
914                    + 1;
915
916                sector_size = u32::from_be_bytes([
917                    capacity_data[4],
918                    capacity_data[5],
919                    capacity_data[6],
920                    capacity_data[7],
921                ]);
922            }
923        }
924
925        info!(
926            "Initialized IDE device({device_type:?}): size={} ({number_of_sectors} x {sector_size})",
927            MemSize(number_of_sectors * sector_size as u64),
928        );
929
930        Some(IdeDevice {
931            device_impl: Mutex::new(Self {
932                master_io,
933                io,
934                pci_device: pci_device.clone(),
935                identify_data,
936                second_device_select,
937            }),
938            device_type,
939            number_of_sectors,
940            sector_size,
941            second_device_select,
942        })
943    }
944
945    fn read_sync_ata(
946        &mut self,
947        start_sector: u64,
948        len_sectors: u64,
949        data: &mut [u8],
950    ) -> Result<(), u8> {
951        assert!(len_sectors <= u8::MAX as u64);
952        // the buffer is enough to hold the data (see read_sync)
953        let command = AtaCommand::new(ata::COMMAND_READ_SECTORS)
954            .with_lba(start_sector)
955            .with_sector_count(len_sectors as u8)
956            .with_second_drive(self.second_device_select);
957
958        command.execute_read(&self.io, data)
959    }
960
961    fn read_sync_atapi(
962        &mut self,
963        start_sector: u64,
964        len_sectors: u64,
965        data: &mut [u8],
966    ) -> Result<(), u8> {
967        assert!(len_sectors <= u16::MAX as u64);
968        assert!(start_sector <= u32::MAX as u64);
969        // the buffer is enough to hold the data (see read_sync)
970        let command = AtapiPacketCommand::new(ata::PACKET_CMD_READ_10)
971            .with_second_drive(self.second_device_select)
972            .push_param(0) // flags
973            .push_param_u32(start_sector as u32) // lba
974            .push_param(0) // group number
975            .push_param_u16(len_sectors as u16) // transfer length
976            .push_param(0); // control
977
978        command.execute(&self.io, data)
979    }
980
981    fn write_sync_ata(
982        &mut self,
983        start_sector: u64,
984        len_sectors: u64,
985        data: &[u8],
986    ) -> Result<(), u8> {
987        assert!(len_sectors <= u8::MAX as u64);
988        // the buffer is enough to hold the data (see write_sync)
989        let command = AtaCommand::new(ata::COMMAND_WRITE_SECTORS)
990            .with_lba(start_sector)
991            .with_sector_count(len_sectors as u8)
992            .with_second_drive(self.second_device_select);
993
994        command.execute_write(&self.io, data)
995    }
996
997    fn interrupt(&mut self) {
998        // acknowledge interrupt
999        self.io.read_status();
1000    }
1001}
1002
1003impl PciDevice for IdeDevice {
1004    fn probe_init(config: &PciDeviceConfig, extra: ProbeExtra) -> Option<Self>
1005    where
1006        Self: Sized,
1007    {
1008        if let PciDeviceType::MassStorageController(0x1, prog_if, ..) = config.device_type {
1009            let support_dma = prog_if & pci_cfg::PROG_IF_MASTER != 0;
1010            let mut command = config.read_command();
1011            command |= pci_cfg::CMD_IO_SPACE;
1012            if support_dma {
1013                // enable bus master
1014                command |= pci_cfg::CMD_BUS_MASTER;
1015            }
1016            config.write_command(command);
1017            let command = config.read_command();
1018            // make sure we have at least IO space enabled
1019            if command & pci_cfg::CMD_IO_SPACE == 0 {
1020                return None;
1021            }
1022
1023            // get the IO ports to use
1024            let io_port = if extra.args[0] == 0 {
1025                // primary
1026                if prog_if & pci_cfg::PROG_IF_PRIMARY != 0 {
1027                    if let Some(primary_io) = config.base_address[0].get_io() {
1028                        let control_block_io = config.base_address[1].get_io().unwrap().0;
1029                        (primary_io.0, control_block_io)
1030                    } else {
1031                        // the IO ports are not set
1032                        if prog_if & pci_cfg::PROG_IF_PRIMARY_PROGRAMMABLE != 0 {
1033                            // we can program them to the default
1034                            let (bar0, bar1) = pci_cfg::DEFAULT_PRIMARY_IO;
1035                            // 1 means IO space
1036                            // FIXME: this makes the `config` has inconsistent state
1037                            config.write_config(pci::reg::BAR0, bar0 | 1);
1038                            config.write_config(pci::reg::BAR1, bar1 | 1);
1039                        }
1040                        pci_cfg::DEFAULT_PRIMARY_IO
1041                    }
1042                } else {
1043                    pci_cfg::DEFAULT_PRIMARY_IO
1044                }
1045            } else {
1046                // secondary
1047                if prog_if & pci_cfg::PROG_IF_SECONDARY != 0 {
1048                    if let Some(secondary_io) = config.base_address[2].get_io() {
1049                        let control_block_io = config.base_address[3].get_io().unwrap().0;
1050                        (secondary_io.0, control_block_io)
1051                    } else {
1052                        // the IO ports are not set
1053                        if prog_if & pci_cfg::PROG_IF_SECONDARY_PROGRAMMABLE != 0 {
1054                            // we can program them to the default
1055                            let (bar2, bar3) = pci_cfg::DEFAULT_SECONDARY_IO;
1056                            // 1 means IO space
1057                            // FIXME: this makes the `config` has inconsistent state
1058                            config.write_config(pci::reg::BAR2, bar2 | 1);
1059                            config.write_config(pci::reg::BAR3, bar3 | 1);
1060                        }
1061                        pci_cfg::DEFAULT_SECONDARY_IO
1062                    }
1063                } else {
1064                    pci_cfg::DEFAULT_SECONDARY_IO
1065                }
1066            };
1067
1068            let master_io = if support_dma {
1069                if let Some(master_io) = config.base_address[4].get_io() {
1070                    Some(master_io.0)
1071                } else {
1072                    // the IO ports are not set
1073                    panic!("DMA is supported but the IO ports are not set")
1074                }
1075            } else {
1076                None
1077            };
1078
1079            // setup interrupts if not already done
1080            if !INTERRUPTS_SETUP.swap(true, core::sync::atomic::Ordering::SeqCst) {
1081                // setup ide interrupt
1082                // TODO: we are assuming that this is the interrupt address.
1083                //       at least, can't find a specific place on all specs for to know for sure if its using
1084                //       legacy interrupts or something else
1085                apic::assign_io_irq(
1086                    ide_interrupt_primary as BasicInterruptHandler,
1087                    pci_cfg::DEFAULT_PRIMARY_INTERRUPT,
1088                    cpu::cpu(),
1089                );
1090                apic::assign_io_irq(
1091                    ide_interrupt_secondary as BasicInterruptHandler,
1092                    pci_cfg::DEFAULT_SECONDARY_INTERRUPT,
1093                    cpu::cpu(),
1094                );
1095            }
1096
1097            let io_port = IdeIo {
1098                command_block: io_port.0,
1099                control_block: io_port.1,
1100            };
1101
1102            let is_secondary = extra.args[1] == 1;
1103            IdeDevice::init_new(master_io, io_port, config, is_secondary)
1104        } else {
1105            None
1106        }
1107    }
1108
1109    fn device_name(&self) -> &'static str {
1110        "IDE"
1111    }
1112}
1113
1114extern "x86-interrupt" fn ide_interrupt_primary(_stack_frame: InterruptStackFrame64) {
1115    let ide_devices = unsafe { addr_of!(IDE_DEVICES).as_ref().unwrap() };
1116    for ide_device in ide_devices.iter().filter_map(Option::as_ref) {
1117        if ide_device.is_primary() {
1118            ide_device.interrupt()
1119        }
1120    }
1121    apic::return_from_interrupt();
1122}
1123
1124extern "x86-interrupt" fn ide_interrupt_secondary(_stack_frame: InterruptStackFrame64) {
1125    let ide_devices = unsafe { addr_of!(IDE_DEVICES).as_ref().unwrap() };
1126    for ide_device in ide_devices.iter().filter_map(Option::as_ref) {
1127        if ide_device.is_secondary() {
1128            ide_device.interrupt()
1129        }
1130    }
1131    apic::return_from_interrupt();
1132}