@@ -106,7 +106,7 @@ int AtaHardDisk::perform_command() {
106
106
uint32_t ints_size = ATA_HD_SEC_SIZE;
107
107
if (this ->r_command == READ_MULTIPLE) {
108
108
if (this ->sec_per_block == 0 ) {
109
- LOG_F (ERROR, " %s: READ MULTIPLE with SET MULTIPLE==0 " , this ->name .c_str ());
109
+ LOG_F (ERROR, " %s: cannot do a READ_MULTIPLE with unset sec_per_block " , this ->name .c_str ());
110
110
this ->r_status |= ERR;
111
111
this ->r_status &= ~BSY;
112
112
break ;
@@ -131,7 +131,7 @@ int AtaHardDisk::perform_command() {
131
131
uint32_t ints_size = ATA_HD_SEC_SIZE;
132
132
if (this ->r_command == WRITE_MULTIPLE) {
133
133
if (this ->sec_per_block == 0 ) {
134
- LOG_F (ERROR, " %s: WRITE MULTIPLE with SET MULTIPLE==0 " , this ->name .c_str ());
134
+ LOG_F (ERROR, " %s: cannot do a WRITE_MULTIPLE with unset sec_per_block " , this ->name .c_str ());
135
135
this ->r_status |= ERR;
136
136
this ->r_status &= ~BSY;
137
137
break ;
@@ -140,8 +140,9 @@ int AtaHardDisk::perform_command() {
140
140
}
141
141
this ->prepare_xfer (xfer_size, ints_size);
142
142
this ->post_xfer_action = [this ]() {
143
- this ->hdd_img .write (this ->data_ptr , this ->cur_fpos , this ->chunk_size );
144
- this ->cur_fpos += this ->chunk_size ;
143
+ uint64_t write_len = (this ->cur_data_ptr - this ->data_ptr ) * sizeof (this ->data_ptr [0 ]);
144
+ this ->hdd_img .write (this ->data_ptr , this ->cur_fpos , write_len);
145
+ this ->cur_fpos += write_len;
145
146
};
146
147
this ->r_status |= DRQ;
147
148
this ->r_status &= ~BSY;
@@ -168,10 +169,12 @@ int AtaHardDisk::perform_command() {
168
169
case SET_MULTIPLE_MODE: // this command is mandatory for ATA devices
169
170
if (!this ->r_sect_count || this ->r_sect_count > 128 ||
170
171
std::bitset<8 >(this ->r_sect_count ).count () != 1 ) { // power of two?
172
+ LOG_F (ERROR, " %s: SET_MULTIPLE_MODE not suported, invalid r_sect_count (%d)" , this ->name .c_str (), this ->r_sect_count );
171
173
this ->multiple_enabled = false ;
172
174
this ->r_error |= ABRT;
173
175
this ->r_status |= ERR;
174
176
} else {
177
+ LOG_F (INFO, " %s: SET_MULTIPLE_MODE, r_sect_count=%d" , this ->name .c_str (), this ->r_sect_count );
175
178
this ->sec_per_block = this ->r_sect_count ;
176
179
this ->multiple_enabled = true ;
177
180
}
@@ -235,9 +238,21 @@ void AtaHardDisk::prepare_identify_info() {
235
238
std::memset (this ->data_buf , 0 , sizeof (this ->data_buf ));
236
239
237
240
buf_ptr[ 0 ] = 0x0040 ; // ATA device, non-removable media, non-removable drive
238
- buf_ptr[47 ] = this ->sec_per_block ; // block size of READ_MULTIPLE/WRITE_MULTIPLE
239
241
buf_ptr[49 ] = 0x0200 ; // report LBA support
240
242
243
+ // Maximum number of logical sectors per data block that the device supports
244
+ // for READ_MULTIPLE/WRITE_MULTIPLE commands.
245
+ const int max_sec_per_block = 8 ;
246
+ if (max_sec_per_block > 1 ) {
247
+ buf_ptr[47 ] = 0x8000 | max_sec_per_block;
248
+ }
249
+ // If bit 8 of word 59 is set to one, then bits 7:0 indicate the number of
250
+ // logical sectors that shall be transferred per data block for
251
+ // READ_MULTIPLE/WRITE_MULTIPLE commands.
252
+ if (this ->sec_per_block ) {
253
+ buf_ptr[59 ] = 0x100 | this ->sec_per_block ;
254
+ }
255
+
241
256
buf_ptr[ 1 ] = this ->cylinders ;
242
257
buf_ptr[ 3 ] = this ->heads ;
243
258
buf_ptr[ 6 ] = this ->sectors ;
0 commit comments