The Pedigree Project 0.1
ata-common.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef _ATA_COMMON_H
21#define _ATA_COMMON_H
22#include "pedigree/kernel/Log.h"
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/processor/IoBase.h"
25#include "pedigree/kernel/processor/Processor.h"
26#include "pedigree/kernel/processor/types.h"
27#include "pedigree/kernel/time/Time.h"
28
29#include <config.h>
30
31typedef union {
34 struct {
35 uint32_t err : 1;
36 uint32_t obs1 : 1;
37 uint32_t obs2 : 1;
38 uint32_t drq : 1;
39 uint32_t rsvd1 : 1;
40 uint32_t df : 1;
41 uint32_t drdy : 1;
42 uint32_t bsy : 1;
43 } PACKED reg;
44
47} AtaStatus;
48
49typedef union {
50 struct {
51 // Word 0: General Configuration
52 struct {
53 uint8_t packet_sz : 2; // Only valid for PACKET devices.
54 uint8_t : 5;
55 uint8_t is_removable : 1;
56 uint8_t packet_cmdset : 6;
57 uint8_t : 1;
58 uint8_t not_ata : 1;
59 } PACKED general_config;
60
61 // Word 1: Obsolete
62 uint16_t : 16;
63
64 // Word 2: 'Specific Configuration'
65 uint16_t : 16;
66
67 // Word 3: Obsolete
68 uint16_t : 16;
69
70 // Words 4-5: Retired
71 uint32_t : 32;
72
73 // Word 6: Obsolete
74 uint16_t : 16;
75
76 // Words 7-8: Reserved for CompactFlash
77 uint32_t : 32;
78
79 // Word 9: Retired
80 uint16_t : 16;
81
82 // Words 10-19: Serial number
83 uint16_t serial_number[10];
84
85 // Words 20-21: Retired
86 uint32_t : 32;
87
88 // Word 22: Obsolete
89 uint16_t : 16;
90
91 // Words 23-26: Firmware revision
92 uint16_t firmware_revision[4];
93
94 // Words 27-46: Model number
95 uint16_t model_number[20];
96
97 // Word 47: Misc data.
98 uint8_t always_80h;
99 uint8_t max_sectors_per_irq; // Max sectors per IRQ on READ/WRITE MULT.
100
101 // Word 48: Reserved
102 uint16_t : 16;
103
104 // Word 49: 'Capabilities'
105 struct {
106 // Reserved
107 uint8_t : 8;
108 // DMA supported
109 uint8_t dma : 1;
110 // LBA supported
111 uint8_t lba : 1;
112 // IORDY may be disabled
113 uint8_t iordy_disabled : 1;
114 // IORD supported
115 uint8_t iordy_supported : 1;
116 // Reserved for IDENTIFY PACKET DEVICE
117 uint8_t : 1;
118 // Standby timer values in standard are supported
119 uint8_t std_standby : 1;
120 // Reserved for IDENTIFY PACKET DEVICE
121 uint8_t : 2;
122 } PACKED caps;
123
124 // Word 50: 'Capabilities'
125 uint16_t : 16; // We ignore this field.
126
127 // Words 51-52: Obsolete
128 uint32_t : 32;
129
130 // Word 53: 'Field Validity'
131 struct {
132 uint8_t : 1;
133 uint8_t multiword_dma_valid : 1;
134 uint8_t ultra_dma_valid : 1;
135 uint16_t : 13;
136 } PACKED validity;
137
138 // Words 54-58: Obsolete
139 uint64_t : 64;
140 uint16_t : 16;
141
142 // Word 59: R/W MULTIPLE data
143 struct {
144 uint8_t curr_sectors_per_irq : 8;
145 uint8_t is_valid : 1;
146 uint8_t : 7;
147 } PACKED rwmultiple;
148
149 // Words 60-61: LBA28 Addressable Sectors
150 uint32_t sector_count;
151
152 // Word 62: Obsolete
153 uint16_t : 16;
154
155 // Word 63: Multiword DMA information
156 struct {
157 uint8_t mode0 : 1;
158 uint8_t mode1 : 1;
159 uint8_t mode2 : 1;
160 uint8_t : 5;
161 uint8_t sel_mode0 : 1;
162 uint8_t sel_mode1 : 1;
163 uint8_t sel_mode2 : 1;
164 uint8_t : 5;
165 } PACKED multiword_dma;
166
167 // Word 64: PIO mode support
168 uint8_t pio_modes_supported;
169 uint8_t : 8; // Reserved
170
171 // Word 65: Minimum Multiword DMA transfer cycle time per word
172 uint16_t minimum_multiword_dma_cycle; // Nanoseconds
173
174 // Word 66: Recommended Multiword DMA transfer cycle time
175 uint16_t recommended_multiword_dma_cycle; // Nanoseconds
176
177 // Word 67: Minimum PIO transfer cycle time without flow control
178 uint16_t minimum_pio_cycle;
179
180 // Word 68: Minimum PIO transfer cycle time with IORDY flow control
181 uint16_t minimum_pio_cycle_iordy;
182
183 // Words 69-70: Reserved
184 uint32_t : 32;
185
186 // Words 71-74: Reserved for IDENTIFY PACKET DEVICE
187 uint64_t : 64;
188
189 // Word 75: 'Queue Depth'
190 uint8_t max_queue_depth : 5;
191 uint16_t : 11;
192
193 // Words 76-79: Reserved for Serial ATA
194 uint64_t : 64;
195
196 // Word 80: Major version number
197 struct {
198 uint8_t : 4;
199 uint8_t ata4 : 1;
200 uint8_t ata5 : 1;
201 uint8_t ata6 : 1;
202 uint8_t ata7 : 1;
203 // Reserved for future use (ATA/ATAPI-7 latest at time of writing)
204 uint8_t : 8;
205 } PACKED major_version;
206
207 // Word 81: Minor version number
208 uint16_t : 16;
209
210 // Word 82: 'Command Set Supported'
211 struct {
212 uint8_t smart : 1;
213 uint8_t security : 1;
214 uint8_t removable : 1;
215 uint8_t power : 1;
216 uint8_t packet : 1;
217 uint8_t cache : 1;
218 uint8_t lookahead : 1;
219 uint8_t release_int : 1;
220 uint8_t service_int : 1;
221 uint8_t device_reset : 1;
222 uint8_t is_protected : 1;
223 uint8_t : 1;
224 uint8_t write_buffer : 1;
225 uint8_t read_buffer : 1;
226 uint8_t nop : 1;
227 uint8_t : 1;
228 } PACKED command_set_support;
229
230 // Word 83: 'Command Sets Supported'
231 struct {
232 uint8_t microcode : 1;
233 uint8_t rw_dma_queued : 1;
234 uint8_t cfa : 1;
235 uint8_t adv_power : 1;
236 uint8_t removable_notify : 1;
237 uint8_t powerup_standby : 1;
238 uint8_t set_features_spinup : 1;
239 uint8_t : 1;
240 uint8_t set_max : 1;
241 uint8_t acoustic : 1;
242 uint8_t address48 : 1;
243 uint8_t config_overlay : 1;
244 uint8_t flush_cache : 1;
245 uint8_t flush_cache_ext : 1;
246 uint8_t one : 1;
247 uint8_t zero : 1;
248 } PACKED command_sets_support;
249
250 // Word 84: 'Command Set/Feature Supported Extension'
251 struct {
252 uint8_t smart_logging : 1;
253 uint8_t smart_selftest : 1;
254 uint8_t media_serial : 1;
255 uint8_t media_passthrough : 1;
256 uint8_t streaming : 1;
257 uint8_t logging : 1;
258 uint8_t write_mult_fua_ext : 1;
259 uint8_t write_dma_fua_ext : 1;
260 uint8_t wwn_64 : 1;
261 uint8_t read_dma_ext_urg : 1;
262 uint8_t write_dma_ext_urg : 1;
263 uint8_t : 2;
264 uint8_t idle_immediate : 1;
265 uint8_t one : 1;
266 uint8_t zero : 1;
267 } PACKED command_set_ext_support;
268
269 // Word 85: 'Command Set Enabled'
270 struct {
271 uint8_t smart : 1;
272 uint8_t security : 1;
273 uint8_t removable : 1;
274 uint8_t power : 1;
275 uint8_t packet : 1;
276 uint8_t cache : 1;
277 uint8_t lookahead : 1;
278 uint8_t release_int : 1;
279 uint8_t service_int : 1;
280 uint8_t device_reset : 1;
281 uint8_t is_protected : 1;
282 uint8_t : 1;
283 uint8_t write_buffer : 1;
284 uint8_t read_buffer : 1;
285 uint8_t nop : 1;
286 uint8_t : 1;
287 } PACKED command_set_enabled;
288
289 // Word 86: 'Command Sets Enabled'
290 struct {
291 uint8_t microcode : 1;
292 uint8_t rw_dma_queued : 1;
293 uint8_t cfa : 1;
294 uint8_t adv_power : 1;
295 uint8_t removable_notify : 1;
296 uint8_t powerup_standby : 1;
297 uint8_t set_features_spinup : 1;
298 uint8_t : 1;
299 uint8_t set_max : 1;
300 uint8_t acoustic : 1;
301 uint8_t address48 : 1;
302 uint8_t config_overlay : 1;
303 uint8_t flush_cache : 1;
304 uint8_t flush_cache_ext : 1;
305 uint8_t one : 1;
306 uint8_t zero : 1;
307 } PACKED command_sets_enabled;
308
309 // Word 87: 'Command Set/Feature Default'
310 struct {
311 uint8_t smart_logging : 1;
312 uint8_t smart_selftest : 1;
313 uint8_t media_serial : 1;
314 uint8_t media_passthrough : 1;
315 uint8_t streaming : 1;
316 uint8_t logging : 1;
317 uint8_t write_mult_fua_ext : 1;
318 uint8_t write_dma_fua_ext : 1;
319 uint8_t wwn_64 : 1;
320 uint8_t read_dma_ext_urg : 1;
321 uint8_t write_dma_ext_urg : 1;
322 uint8_t : 2;
323 uint8_t idle_immediate : 1;
324 uint8_t one : 1;
325 uint8_t zero : 1;
326 } PACKED command_set_ext_default;
327
328 // Word 88: Ultra DMA.
329 struct {
330 uint8_t supp_mode0 : 1;
331 uint8_t supp_mode1 : 1;
332 uint8_t supp_mode2 : 1;
333 uint8_t supp_mode3 : 1;
334 uint8_t supp_mode4 : 1;
335 uint8_t supp_mode5 : 1;
336 uint8_t supp_mode6 : 1;
337 uint8_t : 1;
338 uint8_t sel_mode0 : 1;
339 uint8_t sel_mode1 : 1;
340 uint8_t sel_mode2 : 1;
341 uint8_t sel_mode3 : 1;
342 uint8_t sel_mode4 : 1;
343 uint8_t sel_mode5 : 1;
344 uint8_t sel_mode6 : 1;
345 uint8_t : 1;
346 } PACKED ultra_dma;
347
348 // Word 89: 'Time for security erase unit completion'
349 uint16_t secure_erase_time;
350
351 // Word 90: 'Time for enhanced security erase completion'
352 uint16_t enhanced_secure_erase_time;
353
354 // Word 91: 'Current Advanced Power Management Value'
355 uint16_t curr_adv_power;
356
357 // Word 92: 'Master Password Revision'
358 uint16_t master_password_revision;
359
360 // Word 93: 'Hardware reset result'
361 struct {
362 // Device 0
363 struct {
364 uint8_t one : 1;
365 // 00 = reserved, 01 = jumper, 10 = CSEL, 11 = unknown
366 uint8_t method : 2;
367 uint8_t diagnostics : 1;
368 uint8_t pdiag_assert : 1;
369 uint8_t dasp_assert : 1;
370 // Responds when device 1 is selected.
371 uint8_t responds_to_other : 1;
372 uint8_t : 1;
373 } PACKED device0;
374
375 // Device 1
376 uint8_t one1 : 1;
377 // 00 = reserved, 01 = jumper, 10 = CSEL, 11 = unknown
378 uint8_t d1_method : 2;
379 uint8_t d1_pdiag_assert : 1;
380 uint8_t : 1;
381
382 // General results
383 uint8_t cbild_level : 1;
384 uint8_t one2 : 1;
385 uint8_t zero : 1;
386 } PACKED hardware_reset;
387
388 // Word 94: Vendor recommended and current acoustic management values.
389 uint8_t current_acoustic;
390 uint8_t vendor_acoustic;
391
392 // Word 95: 'Stream Minimum Request Size'
393 uint16_t stream_min_size;
394
395 // Word 96: 'Streaming Transfer Time - DMA'
396 uint16_t dma_streaming_time;
397
398 // Word 97: 'Streaming Access Latency - DMA and PIO'
399 uint16_t streaming_latency;
400
401 // Words 98-99: 'Streaming Performance Granularity'
402 uint32_t streaming_granularity;
403
404 // Words 100-103: 'Maximum user LBA for 48-bit Address Feature set'
405 uint64_t max_user_lba48;
406
407 // Word 104: 'Streaming Transfer Time - PIO'
408 uint16_t pio_streaming_time;
409
410 // Word 105: Reserved
411 uint16_t : 16;
412
413 // Word 106: 'Physical Sector Size / Logical Sector Size'
414 struct {
415 // 2^X logical sectors per physical sector
416 uint8_t logical_per_physical : 4;
417 uint8_t : 8;
418 uint8_t logical_larger_than_512b : 1;
419 uint8_t multiple_logical_per_physical : 1;
420 uint8_t one : 1;
421 uint8_t zero : 1;
422 } PACKED sector_size;
423
424 // Word 107: 'Inter-seek Delay for ISO-9779 acoustic testing'
425 uint16_t iso9779_delay;
426
427 // Words 108-111: Identification
428 struct {
429 uint16_t oui1 : 12;
430 uint8_t naa : 4;
431 uint8_t uid2 : 4;
432 uint16_t oui0 : 12;
433 uint16_t uid1;
434 uint16_t uid0;
435 } PACKED ident;
436
437 // Words 112-115: Reserved for WWN extension to 128 bits.
438 uint64_t : 64;
439
440 // Word 116: Reserved.
441 uint16_t : 16;
442
443 // Word 117-118: 'Words per Logical Sector'
444 uint32_t words_per_logical;
445
446 // Words 119-126: Reserved
447 uint64_t : 64;
448 uint64_t : 64;
449
450 // Word 127: 'Removable Media Status Notification Feature set support'
451 uint16_t removable_notify_support;
452
453 // Word 128: 'Security Status'
454 struct {
455 uint8_t supported : 1;
456 uint8_t enabled : 1;
457 uint8_t locked : 1;
458 uint8_t frozen : 1;
459 uint8_t count_expired : 1;
460 uint8_t ehanced_erase_support : 1;
461 uint8_t : 2;
462 uint8_t level : 1;
463 uint8_t : 7;
464 } PACKED security;
465
466 // Words 129-159: 'Vendor Specific'
467 uint16_t vendor[31];
468
469 // Word 160: 'CFA Power Mode 1'
470 uint16_t cfa_power_mode1;
471
472 // Words 161-175: Reserved
473 uint16_t rsvd[15];
474
475 // Words 176-205: 'Current Media Serial Number'
476 char media_serial[60];
477
478 // Words 206-254: Reserved
479 uint16_t rsvd2[49];
480
481 // Word 255: 'Integrity Word'
482 uint8_t signature;
483 uint8_t checksum;
484 } PACKED data;
485
486 uint16_t __raw[256];
488
490inline void ataLoadSwapped(char* out, const uint16_t* in16, size_t N) {
491 for (size_t i = 0; i < N; ++i) {
492 EMIT_IF(TARGET_IS_LITTLE_ENDIAN) {
493 out[i * 2] = in16[i] >> 8;
494 out[(i * 2) + 1] = in16[i] & 0xFF;
495 }
496 else {
497 out[i * 2] = in16[i] & 0xFF;
498 out[(i * 2) + 1] = in16[i] >> 8;
499 }
500 }
501}
502
504inline AtaStatus ataWait(IoBase* pBase, IoBase* pControl) {
505 const Time::Timestamp started = Time::getTicks();
506 const Time::Timestamp timeout = 10 * Time::Multiplier::Second;
507 const size_t maximumPolls = 10000000;
508 size_t polls = 0;
509
510 // Wait 400ns before reading the status register.
511 if (pControl) {
512 for (size_t i = 0; i < 4; ++i)
513 pControl->read8(2); // Alternate status register.
514 }
515
516 // Grab the status register first (of course)
517 AtaStatus ret;
518 uint8_t status = pBase->read8(7);
519 if (status == 0) {
520 ret.__reg_contents = status;
521 return ret;
522 }
523
524 // Wait for BSY to be unset. Until BSY is unset, no other bits in the
525 // register are considered valid.
526 while (status & 0x80) {
527 if (++polls >= maximumPolls || (Time::getTicks() - started) >= timeout) {
528 ERROR("ATA: timed out waiting for BSY to clear, status=" << status);
529 status |= 0x01;
530 break;
531 }
533 status = pBase->read8(7);
534 }
535
536 // We no longer check DRQ as some commands depend on DRQ being set.
537 // For example, a data transfer uses DRQ to say data is available for
538 // reading.
539
540 // And now verify that DRDY or ERR are asserted (or both!), but only
541 // if DRQ is not set. DRDY will never be set if DRQ is set, and ERR
542 // will come out in the return value even if DRQ is set.
543 if (!(status & 0x8)) {
544 while (!(status & 0x41)) {
545 if (++polls >= maximumPolls || (Time::getTicks() - started) >= timeout) {
546 ERROR("ATA: timed out waiting for DRQ, DRDY, or ERR, status=" << status);
547 status |= 0x01;
548 break;
549 }
551 status = pBase->read8(7);
552
553 // If for some reason the original check for zero gave back
554 // something set, we check again here so we don't infinitely loop
555 // waiting for the bits that'll never be set. Essentially an escape
556 // for devices that aren't present.
557 if (!status)
558 break;
559 }
560 }
561
562 // Okay, BSY is unset now. The drive is no longer busy, it is up to the
563 // caller to read the status and verify further bits (eg, ERR)
564 ret.__reg_contents = status;
565 return ret;
566}
567
569 Time::Timestamp started;
570 Time::Timestamp timeout;
571 size_t polls;
572 size_t maximumPolls;
573};
574
575MUST_USE_RESULT inline bool ataPollPioWriteStatus(IoBase* commandRegs, IoBase* controlRegs,
576 AtaPioPollBudget& budget, AtaStatus& status,
577 bool dataPhase) {
578 if (!commandRegs || budget.polls >= budget.maximumPolls ||
579 (Time::getTicks() - budget.started) >= budget.timeout) {
580 return false;
581 }
582
583 // Each data phase and the final completion phase need the ATA 400 ns
584 // settling interval, but they share one deadline for the whole command.
585 if (controlRegs) {
586 for (size_t i = 0; i < 4; ++i) {
587 controlRegs->read8(2);
588 }
589 }
590
591 while (budget.polls < budget.maximumPolls &&
592 (Time::getTicks() - budget.started) < budget.timeout) {
593 status.__reg_contents = commandRegs->read8(7);
594 ++budget.polls;
595
596 if (status.reg.bsy) {
597 // ATA defines every other status bit as stale while BSY is asserted.
599 continue;
600 }
601
602 if (!status.__reg_contents || status.reg.err || status.reg.df) {
603 return false;
604 }
605
606 // Once BSY clears, the device has committed to this command phase.
607 // WRITE SECTOR(S) needs DRQ for data and DRDY without DRQ for its
608 // command-specific terminal state; a different phase is not progress.
609 return dataPhase ? status.reg.drq : (!status.reg.drq && status.reg.drdy);
610 }
611
612 return false;
613}
614
615MUST_USE_RESULT inline bool ataPioWrite512ByteSectors(IoBase* commandRegs, IoBase* controlRegs,
616 const uint16_t* source, size_t sectorCount,
617 AtaPioPollBudget& budget,
618 AtaStatus& finalStatus) {
619 finalStatus.__reg_contents = 0;
620 if (!commandRegs || !source || !sectorCount) {
621 return false;
622 }
623
624 for (size_t sector = 0; sector < sectorCount; ++sector) {
625 if (!ataPollPioWriteStatus(commandRegs, controlRegs, budget, finalStatus, true)) {
626 return false;
627 }
628
629 for (size_t word = 0; word < 256; ++word) {
630 commandRegs->write16(source[(sector * 256) + word], 0);
631 }
632 }
633
634 return ataPollPioWriteStatus(commandRegs, controlRegs, budget, finalStatus, false);
635}
636
637MUST_USE_RESULT inline bool ataPioRead512ByteSectors(IoBase* commandRegs, IoBase* controlRegs,
638 uint16_t* target, size_t sectorCount,
639 AtaPioPollBudget& budget,
640 AtaStatus& finalStatus) {
641 finalStatus.__reg_contents = 0;
642 if (!commandRegs || !target || !sectorCount)
643 return false;
644 for (size_t sector = 0; sector < sectorCount; ++sector) {
645 if (!ataPollPioWriteStatus(commandRegs, controlRegs, budget, finalStatus, true))
646 return false;
647 for (size_t word = 0; word < 256; ++word)
648 target[sector * 256 + word] = commandRegs->read16(0);
649 }
650 return ataPollPioWriteStatus(commandRegs, controlRegs, budget, finalStatus, false);
651}
652
654inline void logAtaStatus(AtaStatus& status) {
656 s.clear();
657 s.append("ATA: v=");
658 s.append(status.__reg_contents);
659 s.append(" err=");
660 s.append(status.reg.err);
661 s.append(" drq=");
662 s.append(status.reg.drq);
663 s.append(" drdy=");
664 s.append(status.reg.drdy);
665 s.append(" bsy=");
666 s.append(status.reg.bsy);
667 NOTICE(static_cast<const char*>(s));
668}
669
670#endif
Abstrace base class for hardware I/O capabilities.
Definition IoBase.h:32
virtual uint8_t read8(size_t offset=0)=0
virtual void write16(uint16_t value, size_t offset=0)=0
virtual uint16_t read16(size_t offset=0)=0
static void pause()
uint8_t __reg_contents
"Hidden" integer which contains the actual register contents
Definition ata-common.h:46