1use crate::sys;
2use crate::api::fs::{FileIO, IO};
3
4use alloc::string::String;
5use alloc::vec::Vec;
6use bit_field::BitField;
7use core::convert::TryInto;
8use core::fmt;
9use core::hint::spin_loop;
10use lazy_static::lazy_static;
11use spin::Mutex;
12use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};
13
14pub const BLOCK_SIZE: usize = 512;
19
20pub static LAST_SELECTED: Mutex<Option<(u8, u8)>> = Mutex::new(None);
22
23#[repr(u16)]
24#[derive(Debug, Clone, Copy)]
25enum Command {
26 Read = 0x20,
27 Write = 0x30,
28 Identify = 0xEC,
29}
30
31enum IdentifyResponse {
32 Ata([u16; 256]),
33 Atapi,
34 Sata,
35 None,
36}
37
38#[allow(dead_code)]
39#[repr(usize)]
40#[derive(Debug, Clone, Copy)]
41enum Status {
42 ERR = 0, IDX = 1, CORR = 2, DRQ = 3, DSC = 4, DF = 5, DRDY = 6, BSY = 7, }
51
52#[allow(dead_code)]
53#[derive(Debug, Clone)]
54pub struct Bus {
55 id: u8,
56 irq: u8,
57
58 data_register: Port<u16>,
59 error_register: PortReadOnly<u8>,
60 features_register: PortWriteOnly<u8>,
61 sector_count_register: Port<u8>,
62 lba0_register: Port<u8>,
63 lba1_register: Port<u8>,
64 lba2_register: Port<u8>,
65 drive_register: Port<u8>,
66 status_register: PortReadOnly<u8>,
67 command_register: PortWriteOnly<u8>,
68
69 alternate_status_register: PortReadOnly<u8>,
70 control_register: PortWriteOnly<u8>,
71 drive_blockess_register: PortReadOnly<u8>,
72}
73
74impl Bus {
75 pub fn new(id: u8, io_base: u16, ctrl_base: u16, irq: u8) -> Self {
76 Self {
77 id,
78 irq,
79 data_register: Port::new(io_base + 0),
80 error_register: PortReadOnly::new(io_base + 1),
81 features_register: PortWriteOnly::new(io_base + 1),
82 sector_count_register: Port::new(io_base + 2),
83 lba0_register: Port::new(io_base + 3),
84 lba1_register: Port::new(io_base + 4),
85 lba2_register: Port::new(io_base + 5),
86 drive_register: Port::new(io_base + 6),
87 status_register: PortReadOnly::new(io_base + 7),
88 command_register: PortWriteOnly::new(io_base + 7),
89 alternate_status_register: PortReadOnly::new(ctrl_base + 0),
90 control_register: PortWriteOnly::new(ctrl_base + 0),
91 drive_blockess_register: PortReadOnly::new(ctrl_base + 1),
92 }
93 }
94
95 fn check_floating_bus(&mut self) -> Result<(), ()> {
96 match self.status() {
97 0xFF | 0x7F => Err(()),
98 _ => Ok(()),
99 }
100 }
101
102 fn wait(&mut self, ns: u64) {
103 sys::clk::wait(ns);
104 }
105
106 fn clear_interrupt(&mut self) -> u8 {
107 unsafe { self.status_register.read() }
108 }
109
110 fn status(&mut self) -> u8 {
111 unsafe { self.alternate_status_register.read() }
112 }
113
114 fn lba1(&mut self) -> u8 {
115 unsafe { self.lba1_register.read() }
116 }
117
118 fn lba2(&mut self) -> u8 {
119 unsafe { self.lba2_register.read() }
120 }
121
122 fn read_data(&mut self) -> u16 {
123 unsafe { self.data_register.read() }
124 }
125
126 fn write_data(&mut self, data: u16) {
127 unsafe { self.data_register.write(data) }
128 }
129
130 fn is_error(&mut self) -> bool {
131 self.status().get_bit(Status::ERR as usize)
132 }
133
134 fn poll(&mut self, bit: Status, val: bool) -> Result<(), ()> {
135 let start = sys::clk::boot_time();
136 while self.status().get_bit(bit as usize) != val {
137 if sys::clk::boot_time() - start > 1.0 {
138 debug!(
139 "ATA hanged while polling {:?} bit in status register",
140 bit
141 );
142 self.debug();
143 return Err(());
144 }
145 spin_loop();
146 }
147 Ok(())
148 }
149
150 fn select_drive(&mut self, drive: u8) -> Result<(), ()> {
151 self.poll(Status::BSY, false)?;
152 self.poll(Status::DRQ, false)?;
153
154 if *LAST_SELECTED.lock() == Some((self.id, drive)) {
156 return Ok(());
157 } else {
158 *LAST_SELECTED.lock() = Some((self.id, drive));
159 }
160
161 unsafe {
162 self.drive_register.write(0xA0 | (drive << 4))
166 }
167 sys::clk::wait(400); self.poll(Status::BSY, false)?;
169 self.poll(Status::DRQ, false)?;
170 Ok(())
171 }
172
173 fn write_command_params(
174 &mut self,
175 drive: u8,
176 block: u32
177 ) -> Result<(), ()> {
178 let lba = true;
179 let mut bytes = block.to_le_bytes();
180 bytes[3].set_bit(4, drive > 0);
181 bytes[3].set_bit(5, true);
182 bytes[3].set_bit(6, lba);
183 bytes[3].set_bit(7, true);
184 unsafe {
185 self.sector_count_register.write(1);
186 self.lba0_register.write(bytes[0]);
187 self.lba1_register.write(bytes[1]);
188 self.lba2_register.write(bytes[2]);
189 self.drive_register.write(bytes[3]);
190 }
191 Ok(())
192 }
193
194 fn write_command(&mut self, cmd: Command) -> Result<(), ()> {
195 unsafe { self.command_register.write(cmd as u8) }
196 self.wait(400); self.status(); self.clear_interrupt();
199 if self.status() == 0 { return Err(());
201 }
202 if self.is_error() {
203 return Err(());
206 }
207 self.poll(Status::BSY, false)?;
208 self.poll(Status::DRQ, true)?;
209 Ok(())
210 }
211
212 fn setup_pio(&mut self, drive: u8, block: u32) -> Result<(), ()> {
213 self.select_drive(drive)?;
214 self.write_command_params(drive, block)?;
215 Ok(())
216 }
217
218 fn read(
219 &mut self,
220 drive: u8,
221 block: u32,
222 buf: &mut [u8]
223 ) -> Result<(), ()> {
224 debug_assert!(buf.len() == BLOCK_SIZE);
225 self.setup_pio(drive, block)?;
226 self.write_command(Command::Read)?;
227 for chunk in buf.chunks_mut(2) {
228 let data = self.read_data().to_le_bytes();
229 chunk.clone_from_slice(&data);
230 }
231 if self.is_error() {
232 debug!("ATA read: data error");
233 self.debug();
234 Err(())
235 } else {
236 Ok(())
237 }
238 }
239
240 fn write(&mut self, drive: u8, block: u32, buf: &[u8]) -> Result<(), ()> {
241 debug_assert!(buf.len() == BLOCK_SIZE);
242 self.setup_pio(drive, block)?;
243 self.write_command(Command::Write)?;
244 for chunk in buf.chunks(2) {
245 let data = u16::from_le_bytes(chunk.try_into().unwrap());
246 self.write_data(data);
247 }
248 if self.is_error() {
249 debug!("ATA write: data error");
250 self.debug();
251 Err(())
252 } else {
253 Ok(())
254 }
255 }
256
257 fn identify_drive(&mut self, drive: u8) -> Result<IdentifyResponse, ()> {
258 if self.check_floating_bus().is_err() {
259 return Ok(IdentifyResponse::None);
260 }
261 self.select_drive(drive)?;
262 self.write_command_params(drive, 0)?;
263 if self.write_command(Command::Identify).is_err() {
264 if self.status() == 0 {
265 return Ok(IdentifyResponse::None);
266 } else {
267 return Err(());
268 }
269 }
270 match (self.lba1(), self.lba2()) {
271 (0x00, 0x00) => {
272 Ok(IdentifyResponse::Ata([(); 256].map(|_| self.read_data())))
273 }
274 (0x14, 0xEB) => Ok(IdentifyResponse::Atapi),
275 (0x3C, 0xC3) => Ok(IdentifyResponse::Sata),
276 (_, _) => Err(()),
277 }
278 }
279
280 #[allow(dead_code)]
281 fn reset(&mut self) {
282 unsafe {
283 self.control_register.write(4); self.wait(5); self.control_register.write(0); self.wait(2000); }
288 }
289
290 #[allow(dead_code)]
291 fn debug(&mut self) {
292 unsafe {
293 debug!(
294 "ATA status register: 0b{:08b} <BSY|DRDY|#|#|DRQ|#|#|ERR>",
295 self.alternate_status_register.read()
296 );
297 debug!(
298 "ATA error register: 0b{:08b} <#|#|#|#|#|ABRT|#|#>",
299 self.error_register.read()
300 );
301 }
302 }
303}
304
305lazy_static! {
306 pub static ref BUSES: Mutex<Vec<Bus>> = Mutex::new(Vec::new());
307}
308
309pub fn init() {
310 {
311 let mut buses = BUSES.lock();
312 buses.push(Bus::new(0, 0x1F0, 0x3F6, 14));
313 buses.push(Bus::new(1, 0x170, 0x376, 15));
314 }
315
316 for drive in list() {
317 log!("ATA {}:{} {}", drive.bus, drive.dsk, drive);
318 }
319}
320
321#[derive(Clone, Debug)]
322pub struct Drive {
323 pub bus: u8,
324 pub dsk: u8,
325 model: String,
326 serial: String,
327 block_count: u32,
328 block_index: u32,
329}
330
331impl Drive {
332 pub fn size() -> usize {
333 BLOCK_SIZE
334 }
335
336 pub fn open(bus: u8, dsk: u8) -> Option<Self> {
337 let mut buses = BUSES.lock();
338 let res = buses[bus as usize].identify_drive(dsk);
339 if let Ok(IdentifyResponse::Ata(res)) = res {
340 let buf = res.map(u16::to_be_bytes).concat();
341 let model = String::from_utf8_lossy(&buf[54..94]).trim().into();
342 let serial = String::from_utf8_lossy(&buf[20..40]).trim().into();
343 let block_count = u32::from_be_bytes(
344 buf[120..124].try_into().unwrap()
345 ).rotate_left(16);
346 let block_index = 0;
347
348 Some(Self {
349 bus,
350 dsk,
351 model,
352 serial,
353 block_count,
354 block_index,
355 })
356 } else {
357 None
358 }
359 }
360
361 pub const fn block_size(&self) -> u32 {
362 BLOCK_SIZE as u32
363 }
364
365 pub fn block_count(&self) -> u32 {
366 self.block_count
367 }
368
369 fn humanized_size(&self) -> (usize, String) {
370 let size = self.block_size() as usize;
371 let count = self.block_count() as usize;
372 let bytes = size * count;
373 if bytes >> 20 < 1000 {
374 (bytes >> 20, String::from("MB"))
375 } else {
376 (bytes >> 30, String::from("GB"))
377 }
378 }
379}
380
381impl FileIO for Drive {
382 fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
383 if self.block_index == self.block_count {
384 return Ok(0);
385 }
386
387 let mut buses = BUSES.lock();
388 let bus = &mut buses[self.bus as usize];
389 bus.read(self.dsk, self.block_index, buf)?;
390 self.block_index += 1;
391 Ok(buf.len())
392 }
393
394 fn write(&mut self, buf: &[u8]) -> Result<usize, ()> {
395 let mut buses = BUSES.lock();
396 let bus = &mut buses[self.bus as usize];
397
398 let mut count = 0;
399 for chunk in buf.chunks(BLOCK_SIZE) {
400 if self.block_index == self.block_count {
401 return Err(());
402 }
403 let n = chunk.len();
404 if n == BLOCK_SIZE {
405 bus.write(self.dsk, self.block_index, chunk)?;
406 } else {
407 let mut block = [0; BLOCK_SIZE];
408 block[0..n].clone_from_slice(chunk);
409 bus.write(self.dsk, self.block_index, &block)?;
410 }
411 self.block_index += 1;
412 count += chunk.len();
413 }
414 Ok(count)
415 }
416
417 fn close(&mut self) {
418 }
419
420 fn poll(&mut self, event: IO) -> bool {
421 match event {
422 IO::Read => true,
423 IO::Write => true,
424 }
425 }
426}
427
428impl fmt::Display for Drive {
429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430 let (size, unit) = self.humanized_size();
431 write!(f, "{} {} ({} {})", self.model, self.serial, size, unit)
432 }
433}
434
435pub fn list() -> Vec<Drive> {
436 let mut res = Vec::new();
437 for bus in 0..2 {
438 for dsk in 0..2 {
439 if let Some(drive) = Drive::open(bus, dsk) {
440 res.push(drive)
441 }
442 }
443 }
444 res
445}
446
447pub fn read(bus: u8, drive: u8, block: u32, buf: &mut [u8]) -> Result<(), ()> {
448 let mut buses = BUSES.lock();
449 buses[bus as usize].read(drive, block, buf)
450}
451
452pub fn write(bus: u8, drive: u8, block: u32, buf: &[u8]) -> Result<(), ()> {
453 let mut buses = BUSES.lock();
454 buses[bus as usize].write(drive, block, buf)
455}