41 |
41 |
#define SCSI_DMA_BUF_SIZE 131072
|
42 |
42 |
#define SCSI_MAX_INQUIRY_LEN 256
|
43 |
43 |
|
44 |
|
#define SCSI_REQ_STATUS_RETRY 0x01
|
|
44 |
#define SCSI_REQ_STATUS_RETRY 0x01
|
|
45 |
#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06
|
|
46 |
#define SCSI_REQ_STATUS_RETRY_READ 0x00
|
|
47 |
#define SCSI_REQ_STATUS_RETRY_WRITE 0x02
|
45 |
48 |
|
46 |
49 |
typedef struct SCSIDiskState SCSIDiskState;
|
47 |
50 |
|
... | ... | |
70 |
73 |
char *serial;
|
71 |
74 |
};
|
72 |
75 |
|
|
76 |
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
|
|
77 |
|
73 |
78 |
static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag,
|
74 |
79 |
uint32_t lun)
|
75 |
80 |
{
|
... | ... | |
127 |
132 |
static void scsi_read_complete(void * opaque, int ret)
|
128 |
133 |
{
|
129 |
134 |
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
|
|
135 |
int n;
|
130 |
136 |
|
131 |
137 |
r->req.aiocb = NULL;
|
132 |
138 |
|
133 |
139 |
if (ret) {
|
134 |
|
DPRINTF("IO error\n");
|
135 |
|
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
|
136 |
|
scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
|
137 |
|
return;
|
|
140 |
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
|
|
141 |
return;
|
|
142 |
}
|
138 |
143 |
}
|
|
144 |
|
139 |
145 |
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
|
140 |
146 |
|
|
147 |
n = r->iov.iov_len / 512;
|
|
148 |
r->sector += n;
|
|
149 |
r->sector_count -= n;
|
141 |
150 |
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
|
142 |
151 |
}
|
143 |
152 |
|
144 |
|
/* Read more data from scsi device into buffer. */
|
145 |
|
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
|
|
153 |
|
|
154 |
static void scsi_read_request(SCSIDiskReq *r)
|
146 |
155 |
{
|
147 |
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
|
148 |
|
SCSIDiskReq *r;
|
|
156 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
149 |
157 |
uint32_t n;
|
150 |
158 |
|
151 |
|
r = scsi_find_request(s, tag);
|
152 |
|
if (!r) {
|
153 |
|
BADF("Bad read tag 0x%x\n", tag);
|
154 |
|
/* ??? This is the wrong error. */
|
155 |
|
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
|
156 |
|
return;
|
157 |
|
}
|
158 |
159 |
if (r->sector_count == (uint32_t)-1) {
|
159 |
160 |
DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
|
160 |
161 |
r->sector_count = 0;
|
... | ... | |
177 |
178 |
scsi_read_complete, r);
|
178 |
179 |
if (r->req.aiocb == NULL)
|
179 |
180 |
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
|
180 |
|
r->sector += n;
|
181 |
|
r->sector_count -= n;
|
182 |
181 |
}
|
183 |
182 |
|
184 |
|
static int scsi_handle_write_error(SCSIDiskReq *r, int error)
|
|
183 |
/* Read more data from scsi device into buffer. */
|
|
184 |
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
|
185 |
185 |
{
|
|
186 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
|
|
187 |
SCSIDiskReq *r;
|
|
188 |
|
|
189 |
r = scsi_find_request(s, tag);
|
|
190 |
if (!r) {
|
|
191 |
BADF("Bad read tag 0x%x\n", tag);
|
|
192 |
/* ??? This is the wrong error. */
|
|
193 |
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
|
|
194 |
return;
|
|
195 |
}
|
|
196 |
|
|
197 |
/* No data transfer may already be in progress */
|
|
198 |
assert(r->req.aiocb == NULL);
|
|
199 |
|
|
200 |
scsi_read_request(r);
|
|
201 |
}
|
|
202 |
|
|
203 |
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
|
|
204 |
{
|
|
205 |
int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
|
186 |
206 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
187 |
|
BlockErrorAction action = bdrv_get_on_error(s->bs, 0);
|
|
207 |
BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
|
188 |
208 |
|
189 |
209 |
if (action == BLOCK_ERR_IGNORE) {
|
190 |
|
bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, 0);
|
|
210 |
bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
|
191 |
211 |
return 0;
|
192 |
212 |
}
|
193 |
213 |
|
194 |
214 |
if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
|
195 |
215 |
|| action == BLOCK_ERR_STOP_ANY) {
|
196 |
|
r->status |= SCSI_REQ_STATUS_RETRY;
|
197 |
|
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, 0);
|
|
216 |
|
|
217 |
type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
|
|
218 |
r->status |= SCSI_REQ_STATUS_RETRY | type;
|
|
219 |
|
|
220 |
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
198 |
221 |
vm_stop(0);
|
199 |
222 |
} else {
|
|
223 |
if (type == SCSI_REQ_STATUS_RETRY_READ) {
|
|
224 |
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
|
|
225 |
}
|
200 |
226 |
scsi_command_complete(r, CHECK_CONDITION,
|
201 |
227 |
HARDWARE_ERROR);
|
202 |
|
bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, 0);
|
|
228 |
bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
|
203 |
229 |
}
|
204 |
230 |
|
205 |
231 |
return 1;
|
... | ... | |
214 |
240 |
r->req.aiocb = NULL;
|
215 |
241 |
|
216 |
242 |
if (ret) {
|
217 |
|
if (scsi_handle_write_error(r, -ret))
|
|
243 |
if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
|
218 |
244 |
return;
|
|
245 |
}
|
219 |
246 |
}
|
220 |
247 |
|
221 |
248 |
n = r->iov.iov_len / 512;
|
... | ... | |
268 |
295 |
return 1;
|
269 |
296 |
}
|
270 |
297 |
|
271 |
|
if (r->req.aiocb)
|
272 |
|
BADF("Data transfer already in progress\n");
|
|
298 |
/* No data transfer may already be in progress */
|
|
299 |
assert(r->req.aiocb == NULL);
|
273 |
300 |
|
274 |
301 |
scsi_write_request(r);
|
275 |
302 |
|
... | ... | |
288 |
315 |
QTAILQ_FOREACH(req, &s->qdev.requests, next) {
|
289 |
316 |
r = DO_UPCAST(SCSIDiskReq, req, req);
|
290 |
317 |
if (r->status & SCSI_REQ_STATUS_RETRY) {
|
291 |
|
r->status &= ~SCSI_REQ_STATUS_RETRY;
|
292 |
|
scsi_write_request(r);
|
|
318 |
int status = r->status;
|
|
319 |
r->status &=
|
|
320 |
~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);
|
|
321 |
|
|
322 |
switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) {
|
|
323 |
case SCSI_REQ_STATUS_RETRY_READ:
|
|
324 |
scsi_read_request(r);
|
|
325 |
break;
|
|
326 |
case SCSI_REQ_STATUS_RETRY_WRITE:
|
|
327 |
scsi_write_request(r);
|
|
328 |
break;
|
|
329 |
}
|
293 |
330 |
}
|
294 |
331 |
}
|
295 |
332 |
}
|
... | ... | |
1152 |
1189 |
return -1;
|
1153 |
1190 |
}
|
1154 |
1191 |
|
1155 |
|
if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
|
1156 |
|
error_report("Device doesn't support drive option rerror");
|
1157 |
|
return -1;
|
1158 |
|
}
|
1159 |
|
|
1160 |
1192 |
if (!s->serial) {
|
1161 |
1193 |
/* try to fall back to value set with legacy -drive serial=... */
|
1162 |
1194 |
dinfo = drive_get_by_blockdev(s->bs);
|