Overview   API Reference  

ata_command_block.hpp

00001 #if !defined(__ATA_COMMAND_BLOCK_HPP__)
00002 #define __ATA_COMMAND_BLOCK_HPP__
00003 
00004 //
00005 // local includes
00006 //
00007 #include "core/common.hpp"
00008 
00009 /*
00010  * ATA/ATAPI-7 feature sets:
00011  *
00012  *   PACKET Command feature set
00013  *   Power Management feature set
00014  *   Advanced Power Management feature set
00015  *   Security Mode feature set
00016  *   SMART (Self-monitoring, analysis, and reporting technology) feature set
00017  *   Host Protected Area feature set
00018  *   CompactFlash Association (CFA) feature set
00019  *   Removable Media Status Notification and Removable Media feature sets
00020  *   Power-Up In Standby feature set
00021  *   Automatic Acoustic Management (AAM) feature set
00022  *   48-bit Address feature set
00023  *   Device Configuration Overlay feature set
00024  *   Media Card Pass Through Command feature set
00025  *   Streaming feature set
00026  *   General Purpose Logging feature set
00027  *   Overlapped feature set
00028  *   Queued feature set
00029  *   Long Physical Sector Feature Set for Non-Packet Devices
00030  *   Long Logical Sector Feature Set for Non-Packet Devices
00031  */
00032 
00033 //
00034 // ATA/ATAPI command block (usually at 0x1f0/0x170)
00035 //
00036 struct __packed(ata_command_block) : public register_block<uint8_t, little_endian>
00037 {
00038     enum ata_commands
00039     {
00040         //
00041         // mandatory General Feature Set commands (for all devices capable of
00042         //     reading their media that do not implement the PACKET command feature set)
00043         //
00044         COMMAND_EXECUTE_DEVICE_DIAGNOSTIC    = 0x90,
00045         COMMAND_IDENTIFY_DEVICE              = 0xec,
00046         COMMAND_READ_DMA                     = 0xc8,
00047         COMMAND_READ_MULTIPLE                = 0xc4,
00048         COMMAND_READ_SECTORS                 = 0x20,
00049         COMMAND_READ_VERIFY_SECTORS          = 0x40,
00050         COMMAND_SET_FEATURES                 = 0xef,
00051         COMMAND_SET_MULTIPLE_MODE            = 0xc6,
00052 
00053         //
00054         // additional mandatory General Feature Set commands (for all devices capable of
00055         //     writing their media that do not implement the PACKET command feature set)
00056         //
00057         COMMAND_FLUSH_CACHE                  = 0xe7,
00058         COMMAND_WRITE_DMA                    = 0xca,
00059         COMMAND_WRITE_MULTIPLE               = 0xc5,
00060         COMMAND_WRITE_SECTORS                = 0x30,
00061 
00062         //
00063         // optional General Feature Set commands
00064         //     (for all devices not implementing the PACKET command feature set)
00065         //
00066         COMMAND_DOWNLOAD_MICROCODE           = 0x92,
00067         COMMAND_NOP                          = 0x00,
00068         COMMAND_READ_BUFFER                  = 0xe4,
00069         COMMAND_WRITE_BUFFER                 = 0xe8,
00070 
00071         //
00072         // mandatory Removable Media Status Notification Feature Set commands
00073         //     (for all devices that do not implement the PACKET command feature set)
00074         //
00075         COMMAND_GET_MEDIA_STATUS             = 0xda,
00076         COMMAND_MEDIA_EJECT                  = 0xed,
00077 
00078         //
00079         // optional Removable Media Status Notification Feature Set commands
00080         //     (for all devices that do not implement the PACKET command feature set)
00081         //
00082         COMMAND_MEDIA_LOCK                   = 0xde,
00083         COMMAND_MEDIA_UNLOCK                 = 0xdf,
00084         // ... and additionally COMMAND_SET_FEATURES (enable/disable media status notification)
00085 
00086         //
00087         // other relevant commands
00088         //
00089         COMMAND_INITIALIZE_DEVICE_PARAMETERS = 0x91,
00090         COMMAND_RECALL_INTERRUPT             = 0x10
00091     };
00092 
00093     enum atapi_commands
00094     {
00095         //
00096         // mandatory General Feature Set commands (for all devices capable of
00097         //     reading their media that implement the PACKET command feature set)
00098         //
00099         COMMAND_IDENTIFY_PACKET_DEVICE       = 0xa1,
00100         // ...
00101     };
00102 
00103     //
00104     // specific bits
00105     //
00106     static const uint8_t DEVICE_REGISTER_DEVICE_BIT = 4;
00107 
00108     //
00109     // data register at offset: 0x00
00110     //
00111     uint8_t data;
00112 
00113     //
00114     // error (read) / features (write) register at offset: 0x01
00115     //
00116     union
00117     {
00118         union
00119         {
00120             uint8_t raw;
00121 
00122             struct __packed()
00123             {
00124               #if LITTLE_ENDIAN_BITFIELD
00125                 unsigned bad_address_mark       : 1;    // bit 0
00126                 unsigned track0_not_found       : 1;    // bit 1
00127                 unsigned command_aborted        : 1;    // bit 2
00128                 unsigned media_change_requested : 1;    // bit 3
00129                 unsigned ID_field_not_found     : 1;    // bit 4
00130                 unsigned medium_changed         : 1;    // bit 5
00131                 unsigned write_protected        : 1;    // bit 6
00132                 unsigned CRC_error              : 1;    // bit 7
00133               #elif BIG_ENDIAN_BITFIELD
00134                 unsigned CRC_error              : 1;    // bit 7
00135                 unsigned write_protected        : 1;    // bit 6
00136                 unsigned medium_changed         : 1;    // bit 5
00137                 unsigned ID_field_not_found     : 1;    // bit 4
00138                 unsigned media_change_requested : 1;    // bit 3
00139                 unsigned command_aborted        : 1;    // bit 2
00140                 unsigned track0_not_found       : 1;    // bit 1
00141                 unsigned bad_address_mark       : 1;    // bit 0
00142               #else
00143                 #error unknown bitfield order. fix this.
00144               #endif
00145             };
00146 
00147             ACCESS_FUNCTORS(void, uint8_t, raw)
00148             NUMERIC_ACCESS_OPERATORS(void, uint8_t, raw)
00149             ANONYMOUS_INCREMENT_OPERATORS(raw)
00150         } error;
00151 
00152         uint8_t features;
00153     };
00154 
00155     //
00156     // sector count (ATA or ATAPI write) / interrupt reason (ATAPI read) at offset: 0x02
00157     //
00158     union
00159     {
00160         uint8_t sector_count,
00161                 interrupt_reason;
00162     };
00163 
00164     //
00165     // sector address at offsets: 0x03-0x05
00166     //
00167     union
00168     {
00169         //
00170         // ATA-7: LBA low, mid & high registers
00171         //
00172         struct __packed()
00173         {
00174             uint8_t low, mid, high;
00175         } LBA;
00176 
00177         //
00178         // ATAPI-7: LBA low & byte count low & high registers
00179         //
00180         struct __packed()
00181         {
00182             uint8_t dummy03;                            // placement dummy
00183 
00184             union
00185             {
00186                 le_uint16_t raw;
00187 
00188                 struct __packed()
00189                 {
00190                     uint8_t low, high;
00191                 };
00192 
00193                 ACCESS_FUNCTORS(void, uint16_t, raw)
00194                 NUMERIC_ACCESS_OPERATORS(void, uint16_t, raw)
00195                 NUMERIC_ACCESS_OPERATORS(void, le_uint16_t, raw)
00196                 ANONYMOUS_INCREMENT_OPERATORS(raw)
00197             } byte_count;
00198         };
00199     };
00200 
00201     //
00202     // device register at offset: 0x06
00203     //
00204     union device
00205     {
00206         uint8_t raw;
00207 
00208         struct __packed()
00209         {
00210           #if LITTLE_ENDIAN_BITFIELD
00211             unsigned bit0                       : 1;    // bit 0 (command dependent)
00212             unsigned bit1                       : 1;    // bit 1 (command dependent)
00213             unsigned bit2                       : 1;    // bit 2 (command dependent)
00214             unsigned bit3                       : 1;    // bit 3 (command dependent)
00215             unsigned dev                        : 1;    // bit 4 (0 = master, 1 = slave)
00216             unsigned obsolete5                  : 1;    // bit 5 (obsolete as of ATA/ATAPI-7)
00217             unsigned lba                        : 1;    // bit 6 (LBA addressing: 0 = off, 1 = on)
00218             unsigned obsolete7                  : 1;    // bit 7 (obsolete as of ATA/ATAPI-7)
00219           #elif BIG_ENDIAN_BITFIELD
00220             unsigned obsolete7                  : 1;    // bit 7 (obsolete as of ATA/ATAPI-7)
00221             unsigned lba                        : 1;    // bit 6 (LBA addressing: 0 = off, 1 = on)
00222             unsigned obsolete5                  : 1;    // bit 5 (obsolete as of ATA/ATAPI-7)
00223             unsigned dev                        : 1;    // bit 4 (0 = master, 1 = slave)
00224             unsigned bit3                       : 1;    // bit 3 (command dependent)
00225             unsigned bit2                       : 1;    // bit 2 (command dependent)
00226             unsigned bit1                       : 1;    // bit 1 (command dependent)
00227             unsigned bit0                       : 1;    // bit 0 (command dependent)
00228           #else
00229             #error unknown bitfield order. fix this.
00230           #endif
00231         };
00232 
00233         ACCESS_FUNCTORS(device&, uint8_t, raw)
00234         NUMERIC_ACCESS_OPERATORS(device&, uint8_t, raw)
00235         INCREMENT_OPERATORS(device, raw)
00236     } device;
00237 
00238     //
00239     // status (read) / command (write) register at offset: 0x07
00240     //
00241     union
00242     {
00243         union
00244         {
00245             uint8_t raw;
00246 
00247             struct __packed()
00248             {
00249               #if LITTLE_ENDIAN_BITFIELD
00250                 unsigned error                  : 1;    // bit 0
00251                 unsigned index                  : 1;    // bit 1 (obsolete as of ATA/ATAPI-7)
00252                 unsigned ECC_error_corrected    : 1;    // bit 2 (obsolete as of ATA/ATAPI-7)
00253                 unsigned data_requested         : 1;    // bit 3
00254                 unsigned seek                   : 1;    // bit 4 (command dependent)
00255                 unsigned device_fault           : 1;    // bit 5 (often called "write error")
00256                 unsigned device_ready           : 1;    // bit 6
00257                 unsigned busy                   : 1;    // bit 7
00258               #elif BIG_ENDIAN_BITFIELD
00259                 unsigned busy                   : 1;    // bit 7
00260                 unsigned device_ready           : 1;    // bit 6
00261                 unsigned device_fault           : 1;    // bit 5 (often called "write error")
00262                 unsigned seek                   : 1;    // bit 4 (command dependent)
00263                 unsigned data_requested         : 1;    // bit 3
00264                 unsigned ECC_error_corrected    : 1;    // bit 2 (obsolete as of ATA/ATAPI-7)
00265                 unsigned index                  : 1;    // bit 1 (obsolete as of ATA/ATAPI-7)
00266                 unsigned error                  : 1;    // bit 0
00267               #else
00268                 #error unknown bitfield order. fix this.
00269               #endif
00270             };
00271 
00272             ACCESS_FUNCTORS(void, uint8_t, raw)
00273             NUMERIC_ACCESS_OPERATORS(void, uint8_t, raw)
00274             ANONYMOUS_INCREMENT_OPERATORS(raw)
00275         } status;
00276 
00277         uint8_t command;
00278     };
00279 
00280     //
00281     // constructor
00282     //
00283     inline ata_command_block(void)
00284     {
00285         memset(this, 0, static_unsigned_min<sizeof(ata_command_block), 8>::value);
00286     }
00287 
00288     //
00289     // offset evaluation functions
00290     //
00291     static inline bool is_data(const offset_t offset)
00292     {
00293         return offset == 0x00;
00294     }
00295 
00296     static inline bool is_error_features(const offset_t offset)
00297     {
00298         return offset == 0x01;
00299     }
00300 
00301     static inline bool is_device(const offset_t offset)
00302     {
00303         return offset == 0x06;
00304     }
00305 
00306     static inline bool is_command(const offset_t offset)
00307     {
00308         return offset == 0x07;
00309     }
00310 
00311     static inline bool is_status(const offset_t offset)
00312     {
00313         return offset == 0x07;
00314     }
00315 
00316     //
00317     // status functions (affecting error & status register)
00318     //
00319     inline void status_ok(void)
00320     {
00321         error=0;
00322         status.device_fault=status.error=0;
00323         status.device_ready=status.seek=1;
00324         status.busy=status.data_requested=0;
00325     }
00326 
00327     inline void status_ok_busy(void)
00328     {
00329         status_ok();
00330         status.busy=1;
00331     }
00332 
00333     inline void status_ok_data_requested(void)
00334     {
00335         status_ok();
00336         status.data_requested=1;
00337     }
00338 
00339     inline void status_error(void)
00340     {
00341         status_ok();
00342         status.error=1;
00343     }
00344 
00345     inline void status_aborted(void)
00346     {
00347         status_error();
00348         error.command_aborted=1;
00349     }
00350 
00351     //
00352     // address functions
00353     //
00354     inline uint32_t lba28_sector_address(void) const
00355     {
00356         assertd(L4VMM_DEBUG_ATA, device.lba);
00357         return static_cast<uint32_t>(LBA.low) |
00358                    (static_cast<uint32_t>(LBA.mid) << 8) |
00359                    (static_cast<uint32_t>(LBA.high) << 16) |
00360                    (static_cast<uint32_t>(device & 0x0f) << 24);
00361     }
00362 
00363     inline void lba28_sector_address(const uint32_t address)
00364     {
00365         assertd(L4VMM_DEBUG_ATA, device.lba);
00366         LBA.low=address;
00367         LBA.mid=address >> 8;
00368         LBA.high=address >> 16;
00369         device=(device & 0xf0) | ((address >> 24) & 0x0f);
00370     }
00371 
00372     inline uint16_t lba28_sector_count(void) const
00373     {
00374         // 0 usually means 256 sectors
00375         return sector_count ? sector_count : 256;
00376     }
00377 
00378     //
00379     // signature functions
00380     //
00381     inline void ata_signature(const bool clear_device_bit=false)
00382     {
00383         sector_count=LBA.low=0x01;
00384         LBA.mid=LBA.high=0x00;
00385         device&=clear_device_bit ? 0x00 : 0x10;
00386     }
00387 
00388     inline void atapi_signature(const bool clear_device_bit=false)
00389     {
00390         interrupt_reason=LBA.low=0x01;
00391         byte_count.low=0x14;
00392         byte_count.high=0xeb;
00393         device&=clear_device_bit ? 0x00 : 0x10;
00394     }
00395 
00396     //
00397     // get descriptional register names
00398     //
00399     static inline const char *ata_register_name(const offset_t offset)
00400     {
00401         static const char *names[] = {"data", "error/features", "sector count", "LBA low",
00402                                       "LBA mid", "LBA high", "device", "status/command"};
00403         return names[offset & 0x07];
00404     }
00405 
00406     static inline const char *atapi_register_name(const offset_t offset)
00407     {
00408         static const char *names[] = {"data", "error/features", "interrupt reason", "LBA_low",
00409                                       "byte count low", "byte count high", "device select",
00410                                       "status/command"};
00411         return names[offset & 0x07];
00412     }
00413 };
00414 
00415 static_assert(sizeof(ata_command_block) == 8, "ata_command_block's size must be 8");
00416 
00417 #endif
00418 
00419 // ***** end of source ***** //
00420 

L4vmm Reference Manual, written by Mario Schwalbe  © 2006-2008