@@ -85,6 +85,9 @@ int AtaHardDisk::perform_command() {
85
85
switch (this ->r_command ) {
86
86
case NOP:
87
87
break ;
88
+ case ATAPI_SOFT_RESET: // for ATA devices, is a no-op
89
+ this ->r_status &= ~BSY;
90
+ break ;
88
91
case RECALIBRATE: // is optional in ATA-3; disappeared in >= ATA-4
89
92
// OF 3.1.1 won't boot off the drive that reports error for this command
90
93
this ->r_cylinder_hi = 0 ;
@@ -94,25 +97,48 @@ int AtaHardDisk::perform_command() {
94
97
this ->r_status &= ~BSY;
95
98
this ->update_intrq (1 );
96
99
break ;
100
+ case READ_MULTIPLE:
97
101
case READ_SECTOR:
98
102
case READ_SECTOR_NR: {
99
103
uint16_t sec_count = this ->r_sect_count ? this ->r_sect_count : 256 ;
100
104
int xfer_size = sec_count * ATA_HD_SEC_SIZE;
101
105
uint64_t offset = this ->get_lba () * ATA_HD_SEC_SIZE;
106
+ uint32_t ints_size = ATA_HD_SEC_SIZE;
107
+ if (this ->r_command == READ_MULTIPLE) {
108
+ if (this ->multiple_sector_count == 0 ) {
109
+ LOG_F (ERROR, " %s: READ MULTIPLE with SET MULTIPLE==0" , this ->name .c_str ());
110
+ this ->r_status |= ERR;
111
+ this ->r_status &= ~BSY;
112
+ break ;
113
+ }
114
+ ints_size *= this ->multiple_sector_count ;
115
+ }
102
116
hdd_img.read (buffer, offset, xfer_size);
103
117
this ->data_ptr = (uint16_t *)this ->buffer ;
104
118
// those commands should generate IRQ for each sector
105
- this ->prepare_xfer (xfer_size, ATA_HD_SEC_SIZE );
119
+ this ->prepare_xfer (xfer_size, ints_size );
106
120
this ->signal_data_ready ();
107
121
}
108
122
break ;
123
+ case WRITE_MULTIPLE:
109
124
case WRITE_SECTOR:
110
125
case WRITE_SECTOR_NR: {
111
126
uint16_t sec_count = this ->r_sect_count ? this ->r_sect_count : 256 ;
112
127
this ->cur_fpos = this ->get_lba () * ATA_HD_SEC_SIZE;
113
128
this ->data_ptr = (uint16_t *)this ->buffer ;
114
129
this ->cur_data_ptr = this ->data_ptr ;
115
- this ->prepare_xfer (sec_count * ATA_HD_SEC_SIZE, ATA_HD_SEC_SIZE);
130
+ uint32_t xfer_size = sec_count * ATA_HD_SEC_SIZE;
131
+ uint32_t ints_size = ATA_HD_SEC_SIZE;
132
+ if (this ->r_command == WRITE_MULTIPLE) {
133
+ if (this ->multiple_sector_count == 0 ) {
134
+ LOG_F (ERROR, " %s: WRITE MULTIPLE with SET MULTIPLE==0" , this ->name .c_str ());
135
+ this ->r_status |= ERR;
136
+ this ->r_status &= ~BSY;
137
+ break ;
138
+ }
139
+ ints_size *= this ->multiple_sector_count ;
140
+ }
141
+ this ->prepare_xfer (xfer_size, ints_size);
116
142
this ->post_xfer_action = [this ]() {
117
143
this ->hdd_img .write (this ->data_ptr , this ->cur_fpos , this ->chunk_size );
118
144
this ->cur_fpos += this ->chunk_size ;
@@ -127,6 +153,11 @@ int AtaHardDisk::perform_command() {
127
153
this ->r_status &= ~BSY;
128
154
this ->update_intrq (1 );
129
155
break ;
156
+ case READ_VERIFY:
157
+ // verify sectors are readable, just no-op
158
+ this ->r_status &= ~BSY;
159
+ this ->update_intrq (1 );
160
+ break ;
130
161
case INIT_DEV_PARAM:
131
162
// update fictive disk geometry with parameters from host
132
163
this ->sectors = this ->r_sect_count ;
0 commit comments