00001 #if !defined(__ATA_COMMAND_BLOCK_HPP__)
00002 #define __ATA_COMMAND_BLOCK_HPP__
00003
00004
00005
00006
00007 #include "core/common.hpp"
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 struct __packed(ata_command_block) : public register_block<uint8_t, little_endian>
00037 {
00038 enum ata_commands
00039 {
00040
00041
00042
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
00055
00056
00057 COMMAND_FLUSH_CACHE = 0xe7,
00058 COMMAND_WRITE_DMA = 0xca,
00059 COMMAND_WRITE_MULTIPLE = 0xc5,
00060 COMMAND_WRITE_SECTORS = 0x30,
00061
00062
00063
00064
00065
00066 COMMAND_DOWNLOAD_MICROCODE = 0x92,
00067 COMMAND_NOP = 0x00,
00068 COMMAND_READ_BUFFER = 0xe4,
00069 COMMAND_WRITE_BUFFER = 0xe8,
00070
00071
00072
00073
00074
00075 COMMAND_GET_MEDIA_STATUS = 0xda,
00076 COMMAND_MEDIA_EJECT = 0xed,
00077
00078
00079
00080
00081
00082 COMMAND_MEDIA_LOCK = 0xde,
00083 COMMAND_MEDIA_UNLOCK = 0xdf,
00084
00085
00086
00087
00088
00089 COMMAND_INITIALIZE_DEVICE_PARAMETERS = 0x91,
00090 COMMAND_RECALL_INTERRUPT = 0x10
00091 };
00092
00093 enum atapi_commands
00094 {
00095
00096
00097
00098
00099 COMMAND_IDENTIFY_PACKET_DEVICE = 0xa1,
00100
00101 };
00102
00103
00104
00105
00106 static const uint8_t DEVICE_REGISTER_DEVICE_BIT = 4;
00107
00108
00109
00110
00111 uint8_t data;
00112
00113
00114
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;
00126 unsigned track0_not_found : 1;
00127 unsigned command_aborted : 1;
00128 unsigned media_change_requested : 1;
00129 unsigned ID_field_not_found : 1;
00130 unsigned medium_changed : 1;
00131 unsigned write_protected : 1;
00132 unsigned CRC_error : 1;
00133 #elif BIG_ENDIAN_BITFIELD
00134 unsigned CRC_error : 1;
00135 unsigned write_protected : 1;
00136 unsigned medium_changed : 1;
00137 unsigned ID_field_not_found : 1;
00138 unsigned media_change_requested : 1;
00139 unsigned command_aborted : 1;
00140 unsigned track0_not_found : 1;
00141 unsigned bad_address_mark : 1;
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
00157
00158 union
00159 {
00160 uint8_t sector_count,
00161 interrupt_reason;
00162 };
00163
00164
00165
00166
00167 union
00168 {
00169
00170
00171
00172 struct __packed()
00173 {
00174 uint8_t low, mid, high;
00175 } LBA;
00176
00177
00178
00179
00180 struct __packed()
00181 {
00182 uint8_t dummy03;
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
00203
00204 union device
00205 {
00206 uint8_t raw;
00207
00208 struct __packed()
00209 {
00210 #if LITTLE_ENDIAN_BITFIELD
00211 unsigned bit0 : 1;
00212 unsigned bit1 : 1;
00213 unsigned bit2 : 1;
00214 unsigned bit3 : 1;
00215 unsigned dev : 1;
00216 unsigned obsolete5 : 1;
00217 unsigned lba : 1;
00218 unsigned obsolete7 : 1;
00219 #elif BIG_ENDIAN_BITFIELD
00220 unsigned obsolete7 : 1;
00221 unsigned lba : 1;
00222 unsigned obsolete5 : 1;
00223 unsigned dev : 1;
00224 unsigned bit3 : 1;
00225 unsigned bit2 : 1;
00226 unsigned bit1 : 1;
00227 unsigned bit0 : 1;
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
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;
00251 unsigned index : 1;
00252 unsigned ECC_error_corrected : 1;
00253 unsigned data_requested : 1;
00254 unsigned seek : 1;
00255 unsigned device_fault : 1;
00256 unsigned device_ready : 1;
00257 unsigned busy : 1;
00258 #elif BIG_ENDIAN_BITFIELD
00259 unsigned busy : 1;
00260 unsigned device_ready : 1;
00261 unsigned device_fault : 1;
00262 unsigned seek : 1;
00263 unsigned data_requested : 1;
00264 unsigned ECC_error_corrected : 1;
00265 unsigned index : 1;
00266 unsigned error : 1;
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
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
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
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
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
00375 return sector_count ? sector_count : 256;
00376 }
00377
00378
00379
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
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
00420