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