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 for j in 0..2 {
35 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 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 *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 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 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 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 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 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 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 pub fn read_error(&self) -> u8 {
235 self.read_command_block(ata::ERROR)
236 }
237
238 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 return Err(self.read_error());
265 }
266
267 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 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 return Err(self.read_error());
290 }
291
292 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 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, 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 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 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, dma: AtapiDmaDirection::None,
411 lba: 0xFFFF00, 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 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 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 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 return Err(io_port.read_sense_key());
486 }
487
488 let mut param_count = self.params_index;
490 if param_count & 1 == 1 {
492 param_count += 1;
493 }
494 for ¶m in unsafe { self.params[..param_count].align_to::<u16>().1 } {
496 io_port.write_data(param);
497 }
498 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 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 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 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 ((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 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 self.logical_sector_size * 2
660 } else {
661 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 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 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 if lbalo == 0x1 && lbamid == 0x14 && lbahi == 0xEB {
845 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 } 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 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 return None;
880 }
881
882 if !identify_data.is_dma_supported() {
883 master_io = None;
885 }
886 if !identify_data.is_lba_supported() {
887 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 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 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 let command = AtapiPacketCommand::new(ata::PACKET_CMD_READ_10)
971 .with_second_drive(self.second_device_select)
972 .push_param(0) .push_param_u32(start_sector as u32) .push_param(0) .push_param_u16(len_sectors as u16) .push_param(0); 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 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 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 command |= pci_cfg::CMD_BUS_MASTER;
1015 }
1016 config.write_command(command);
1017 let command = config.read_command();
1018 if command & pci_cfg::CMD_IO_SPACE == 0 {
1020 return None;
1021 }
1022
1023 let io_port = if extra.args[0] == 0 {
1025 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 if prog_if & pci_cfg::PROG_IF_PRIMARY_PROGRAMMABLE != 0 {
1033 let (bar0, bar1) = pci_cfg::DEFAULT_PRIMARY_IO;
1035 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 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 if prog_if & pci_cfg::PROG_IF_SECONDARY_PROGRAMMABLE != 0 {
1054 let (bar2, bar3) = pci_cfg::DEFAULT_SECONDARY_IO;
1056 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 panic!("DMA is supported but the IO ports are not set")
1074 }
1075 } else {
1076 None
1077 };
1078
1079 if !INTERRUPTS_SETUP.swap(true, core::sync::atomic::Ordering::SeqCst) {
1081 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}