Revision efb9ee02 hw/scsi-disk.c
b/hw/scsi-disk.c | ||
---|---|---|
51 | 51 |
|
52 | 52 |
typedef struct SCSIDiskReq { |
53 | 53 |
SCSIRequest req; |
54 |
/* ??? We should probably keep track of whether the data transfer is |
|
55 |
a read or a write. Currently we rely on the host getting it right. */ |
|
56 | 54 |
/* Both sector and sector_count are in terms of qemu 512 byte blocks. */ |
57 | 55 |
uint64_t sector; |
58 | 56 |
uint32_t sector_count; |
... | ... | |
180 | 178 |
/* No data transfer may already be in progress */ |
181 | 179 |
assert(r->req.aiocb == NULL); |
182 | 180 |
|
181 |
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { |
|
182 |
DPRINTF("Data transfer direction invalid\n"); |
|
183 |
scsi_read_complete(r, -EINVAL); |
|
184 |
return; |
|
185 |
} |
|
186 |
|
|
183 | 187 |
n = r->sector_count; |
184 | 188 |
if (n > SCSI_DMA_BUF_SIZE / 512) |
185 | 189 |
n = SCSI_DMA_BUF_SIZE / 512; |
... | ... | |
216 | 220 |
if (type == SCSI_REQ_STATUS_RETRY_READ) { |
217 | 221 |
scsi_req_data(&r->req, 0); |
218 | 222 |
} |
219 |
if (error == ENOMEM) { |
|
223 |
switch (error) { |
|
224 |
case ENOMEM: |
|
220 | 225 |
scsi_command_complete(r, CHECK_CONDITION, |
221 | 226 |
SENSE_CODE(TARGET_FAILURE)); |
222 |
} else { |
|
227 |
break; |
|
228 |
case EINVAL: |
|
229 |
scsi_command_complete(r, CHECK_CONDITION, |
|
230 |
SENSE_CODE(INVALID_FIELD)); |
|
231 |
break; |
|
232 |
default: |
|
223 | 233 |
scsi_command_complete(r, CHECK_CONDITION, |
224 | 234 |
SENSE_CODE(IO_ERROR)); |
235 |
break; |
|
225 | 236 |
} |
226 | 237 |
bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read); |
227 | 238 |
} |
228 |
|
|
229 | 239 |
return 1; |
230 | 240 |
} |
231 | 241 |
|
... | ... | |
268 | 278 |
/* No data transfer may already be in progress */ |
269 | 279 |
assert(r->req.aiocb == NULL); |
270 | 280 |
|
281 |
if (r->req.cmd.mode != SCSI_XFER_TO_DEV) { |
|
282 |
DPRINTF("Data transfer direction invalid\n"); |
|
283 |
scsi_write_complete(r, -EINVAL); |
|
284 |
return 0; |
|
285 |
} |
|
286 |
|
|
271 | 287 |
n = r->iov.iov_len / 512; |
272 | 288 |
if (n) { |
273 | 289 |
qemu_iovec_init_external(&r->qiov, &r->iov, 1); |
... | ... | |
987 | 1003 |
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); |
988 | 1004 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); |
989 | 1005 |
int32_t len; |
990 |
int is_write; |
|
991 | 1006 |
uint8_t command; |
992 | 1007 |
uint8_t *outbuf; |
993 | 1008 |
int rc; |
994 | 1009 |
|
995 | 1010 |
command = buf[0]; |
996 | 1011 |
outbuf = (uint8_t *)r->iov.iov_base; |
997 |
is_write = 0; |
|
998 | 1012 |
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]); |
999 | 1013 |
|
1000 | 1014 |
if (scsi_req_parse(&r->req, buf) != 0) { |
... | ... | |
1074 | 1088 |
goto illegal_lba; |
1075 | 1089 |
r->sector = r->req.cmd.lba * s->cluster_size; |
1076 | 1090 |
r->sector_count = len * s->cluster_size; |
1077 |
is_write = 1; |
|
1078 | 1091 |
break; |
1079 | 1092 |
case MODE_SELECT: |
1080 | 1093 |
DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer); |
... | ... | |
1140 | 1153 |
scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE)); |
1141 | 1154 |
} |
1142 | 1155 |
len = r->sector_count * 512 + r->iov.iov_len; |
1143 |
if (is_write) {
|
|
1144 |
len = -len;
|
|
1156 |
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
|
|
1157 |
return -len;
|
|
1145 | 1158 |
} else { |
1146 | 1159 |
if (!r->sector_count) |
1147 | 1160 |
r->sector_count = -1; |
1161 |
return len; |
|
1148 | 1162 |
} |
1149 |
return len; |
|
1150 | 1163 |
} |
1151 | 1164 |
|
1152 | 1165 |
static void scsi_disk_reset(DeviceState *dev) |
Also available in: Unified diff