Revision a1f0cce2

b/hw/scsi-bus.c
154 154
    QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
155 155
}
156 156

  
157
void scsi_req_dequeue(SCSIRequest *req)
157
static void scsi_req_dequeue(SCSIRequest *req)
158 158
{
159 159
    trace_scsi_req_dequeue(req->dev->id, req->lun, req->tag);
160 160
    if (req->enqueued) {
......
391 391
    return 0;
392 392
}
393 393

  
394
/*
395
 * Predefined sense codes
396
 */
397

  
398
/* No sense data available */
399
const struct SCSISense sense_code_NO_SENSE = {
400
    .key = NO_SENSE , .asc = 0x00 , .ascq = 0x00
401
};
402

  
403
/* LUN not ready, Manual intervention required */
404
const struct SCSISense sense_code_LUN_NOT_READY = {
405
    .key = NOT_READY, .asc = 0x04, .ascq = 0x03
406
};
407

  
408
/* LUN not ready, Medium not present */
409
const struct SCSISense sense_code_NO_MEDIUM = {
410
    .key = NOT_READY, .asc = 0x3a, .ascq = 0x00
411
};
412

  
413
/* Hardware error, internal target failure */
414
const struct SCSISense sense_code_TARGET_FAILURE = {
415
    .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00
416
};
417

  
418
/* Illegal request, invalid command operation code */
419
const struct SCSISense sense_code_INVALID_OPCODE = {
420
    .key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00
421
};
422

  
423
/* Illegal request, LBA out of range */
424
const struct SCSISense sense_code_LBA_OUT_OF_RANGE = {
425
    .key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00
426
};
427

  
428
/* Illegal request, Invalid field in CDB */
429
const struct SCSISense sense_code_INVALID_FIELD = {
430
    .key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00
431
};
432

  
433
/* Illegal request, LUN not supported */
434
const struct SCSISense sense_code_LUN_NOT_SUPPORTED = {
435
    .key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00
436
};
437

  
438
/* Command aborted, I/O process terminated */
439
const struct SCSISense sense_code_IO_ERROR = {
440
    .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
441
};
442

  
443
/* Command aborted, I_T Nexus loss occurred */
444
const struct SCSISense sense_code_I_T_NEXUS_LOSS = {
445
    .key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07
446
};
447

  
448
/* Command aborted, Logical Unit failure */
449
const struct SCSISense sense_code_LUN_FAILURE = {
450
    .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
451
};
452

  
453
/*
454
 * scsi_build_sense
455
 *
456
 * Build a sense buffer
457
 */
458
int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed)
459
{
460
    if (!fixed && len < 8) {
461
        return 0;
462
    }
463

  
464
    memset(buf, 0, len);
465
    if (fixed) {
466
        /* Return fixed format sense buffer */
467
        buf[0] = 0xf0;
468
        buf[2] = sense.key;
469
        buf[7] = 7;
470
        buf[12] = sense.asc;
471
        buf[13] = sense.ascq;
472
        return MIN(len, 18);
473
    } else {
474
        /* Return descriptor format sense buffer */
475
        buf[0] = 0x72;
476
        buf[1] = sense.key;
477
        buf[2] = sense.asc;
478
        buf[3] = sense.ascq;
479
        return 8;
480
    }
481
}
482

  
394 483
static const char *scsi_command_name(uint8_t cmd)
395 484
{
396 485
    static const char *names[] = {
b/hw/scsi-disk.c
49 49

  
50 50
typedef struct SCSIDiskState SCSIDiskState;
51 51

  
52
typedef struct SCSISense {
53
    uint8_t key;
54
} SCSISense;
55

  
56 52
typedef struct SCSIDiskReq {
57 53
    SCSIRequest req;
58 54
    /* ??? We should probably keep track of whether the data transfer is
......
111 107
    memset(&s->sense, 0, sizeof(s->sense));
112 108
}
113 109

  
114
static void scsi_disk_set_sense(SCSIDiskState *s, uint8_t key)
115
{
116
    s->sense.key = key;
117
}
118

  
119
static void scsi_req_set_status(SCSIDiskReq *r, int status, int sense_code)
110
static void scsi_req_set_status(SCSIDiskReq *r, int status, SCSISense sense)
120 111
{
121 112
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
122 113

  
123 114
    r->req.status = status;
124
    scsi_disk_set_sense(s, sense_code);
115
    s->sense = sense;
125 116
}
126 117

  
127 118
/* Helper function for command completion.  */
128
static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
119
static void scsi_command_complete(SCSIDiskReq *r, int status, SCSISense sense)
129 120
{
130
    DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
131
            r->req.tag, status, sense);
121
    DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n",
122
            r->req.tag, status, sense.key, sense.asc, sense.ascq);
132 123
    scsi_req_set_status(r, status, sense);
133 124
    scsi_req_complete(&r->req);
134 125
}
......
182 173
    }
183 174
    DPRINTF("Read sector_count=%d\n", r->sector_count);
184 175
    if (r->sector_count == 0) {
185
        scsi_command_complete(r, GOOD, NO_SENSE);
176
        scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
186 177
        return;
187 178
    }
188 179

  
......
225 216
        if (type == SCSI_REQ_STATUS_RETRY_READ) {
226 217
            scsi_req_data(&r->req, 0);
227 218
        }
228
        scsi_command_complete(r, CHECK_CONDITION,
229
                HARDWARE_ERROR);
219
        if (error == ENOMEM) {
220
            scsi_command_complete(r, CHECK_CONDITION,
221
                                  SENSE_CODE(TARGET_FAILURE));
222
        } else {
223
            scsi_command_complete(r, CHECK_CONDITION,
224
                                  SENSE_CODE(IO_ERROR));
225
        }
230 226
        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
231 227
    }
232 228

  
......
251 247
    r->sector += n;
252 248
    r->sector_count -= n;
253 249
    if (r->sector_count == 0) {
254
        scsi_command_complete(r, GOOD, NO_SENSE);
250
        scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
255 251
    } else {
256 252
        len = r->sector_count * 512;
257 253
        if (len > SCSI_DMA_BUF_SIZE) {
......
278 274
        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
279 275
                                   scsi_write_complete, r);
280 276
        if (r->req.aiocb == NULL) {
281
            scsi_write_complete(r, -EIO);
277
            scsi_write_complete(r, -ENOMEM);
282 278
        }
283 279
    } else {
284 280
        /* Invoke completion routine to fetch data from host.  */
......
316 312
            case SCSI_REQ_STATUS_RETRY_FLUSH:
317 313
                ret = scsi_disk_emulate_command(r, r->iov.iov_base);
318 314
                if (ret == 0) {
319
                    scsi_command_complete(r, GOOD, NO_SENSE);
315
                    scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
320 316
                }
321 317
            }
322 318
        }
......
815 811
    case REQUEST_SENSE:
816 812
        if (req->cmd.xfer < 4)
817 813
            goto illegal_request;
818
        memset(outbuf, 0, 4);
819
        buflen = 4;
820
        if (s->sense.key == NOT_READY && req->cmd.xfer >= 18) {
821
            memset(outbuf, 0, 18);
822
            buflen = 18;
823
            outbuf[7] = 10;
824
            /* asc 0x3a, ascq 0: Medium not present */
825
            outbuf[12] = 0x3a;
826
            outbuf[13] = 0;
827
        }
828
        outbuf[0] = 0xf0;
829
        outbuf[1] = 0;
830
        outbuf[2] = s->sense.key;
814
        buflen = scsi_build_sense(s->sense, outbuf, req->cmd.xfer,
815
                                  req->cmd.xfer > 13);
831 816
        scsi_disk_clear_sense(s);
832 817
        break;
833 818
    case INQUIRY:
......
965 950
        }
966 951
        break;
967 952
    default:
968
        goto illegal_request;
953
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
954
        return -1;
969 955
    }
970
    scsi_req_set_status(r, GOOD, NO_SENSE);
956
    scsi_req_set_status(r, GOOD, SENSE_CODE(NO_SENSE));
971 957
    return buflen;
972 958

  
973 959
not_ready:
974
    scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
960
    if (!bdrv_is_inserted(s->bs)) {
961
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(NO_MEDIUM));
962
    } else {
963
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(LUN_NOT_READY));
964
    }
975 965
    return -1;
976 966

  
977 967
illegal_request:
978
    scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
968
    scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_FIELD));
979 969
    return -1;
980 970
}
981 971

  
......
1002 992

  
1003 993
    if (scsi_req_parse(&r->req, buf) != 0) {
1004 994
        BADF("Unsupported command length, command %x\n", command);
1005
        goto fail;
995
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
996
        return 0;
1006 997
    }
1007 998
#ifdef DEBUG_SCSI
1008 999
    {
......
1017 1008
    if (req->lun || buf[1] >> 5) {
1018 1009
        /* Only LUN 0 supported.  */
1019 1010
        DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : buf[1] >> 5);
1020
        if (command != REQUEST_SENSE && command != INQUIRY)
1021
            goto fail;
1011
        if (command != REQUEST_SENSE && command != INQUIRY) {
1012
            scsi_command_complete(r, CHECK_CONDITION,
1013
                                  SENSE_CODE(LUN_NOT_SUPPORTED));
1014
            return 0;
1015
        }
1022 1016
    }
1023 1017
    switch (command) {
1024 1018
    case TEST_UNIT_READY:
......
1126 1120
        break;
1127 1121
    default:
1128 1122
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1123
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
1124
        return 0;
1129 1125
    fail:
1130
        scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
1126
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_FIELD));
1131 1127
        return 0;
1132 1128
    illegal_lba:
1133
        scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
1129
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(LBA_OUT_OF_RANGE));
1134 1130
        return 0;
1135 1131
    }
1136 1132
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1137
        scsi_command_complete(r, GOOD, NO_SENSE);
1133
        scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
1138 1134
    }
1139 1135
    len = r->sector_count * 512 + r->iov.iov_len;
1140 1136
    if (is_write) {
b/hw/scsi-generic.c
66 66
    uint8_t senselen;
67 67
};
68 68

  
69
static void scsi_set_sense(SCSIGenericState *s, SCSISense sense)
70
{
71
    s->senselen = scsi_build_sense(sense, s->sensebuf, SCSI_SENSE_BUF_SIZE, 0);
72
    s->driver_status = SG_ERR_DRIVER_SENSE;
73
}
74

  
75
static void scsi_clear_sense(SCSIGenericState *s)
76
{
77
    memset(s->sensebuf, 0, SCSI_SENSE_BUF_SIZE);
78
    s->senselen = 0;
79
    s->driver_status = 0;
80
}
81

  
69 82
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
70 83
{
71 84
    SCSIRequest *req;
......
92 105
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
93 106
        s->senselen = r->io_header.sb_len_wr;
94 107

  
95
    if (ret != 0)
96
        r->req.status = BUSY;
97
    else {
108
    if (ret != 0) {
109
        switch (ret) {
110
        case -EINVAL:
111
            r->req.status = CHECK_CONDITION;
112
            scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
113
            break;
114
        case -ENOMEM:
115
            r->req.status = CHECK_CONDITION;
116
            scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
117
            break;
118
        default:
119
            r->req.status = CHECK_CONDITION;
120
            scsi_set_sense(s, SENSE_CODE(IO_ERROR));
121
            break;
122
        }
123
    } else {
98 124
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
99 125
            r->req.status = BUSY;
100 126
            BADF("Driver Timeout\n");
......
144 170
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
145 171
    if (r->req.aiocb == NULL) {
146 172
        BADF("execute_command: read failed !\n");
147
        return -1;
173
        return -ENOMEM;
148 174
    }
149 175

  
150 176
    return 0;
......
198 224
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
199 225
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
200 226
        scsi_req_data(&r->req, s->senselen);
227
        /* Clear sensebuf after REQUEST_SENSE */
228
        scsi_clear_sense(s);
201 229
        return;
202 230
    }
203 231

  
204 232
    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
205
    if (ret == -1) {
206
        scsi_command_complete(r, -EINVAL);
233
    if (ret < 0) {
234
        scsi_command_complete(r, ret);
207 235
        return;
208 236
    }
209 237
}
......
246 274
    }
247 275

  
248 276
    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
249
    if (ret == -1) {
250
        scsi_command_complete(r, -EINVAL);
277
    if (ret < 0) {
278
        scsi_command_complete(r, ret);
251 279
        return 1;
252 280
    }
253 281

  
......
296 324
    if (cmd[0] != REQUEST_SENSE &&
297 325
        (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
298 326
        DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
299

  
300
        s->sensebuf[0] = 0x70;
301
        s->sensebuf[1] = 0x00;
302
        s->sensebuf[2] = ILLEGAL_REQUEST;
303
        s->sensebuf[3] = 0x00;
304
        s->sensebuf[4] = 0x00;
305
        s->sensebuf[5] = 0x00;
306
        s->sensebuf[6] = 0x00;
307
        s->senselen = 7;
308
        s->driver_status = SG_ERR_DRIVER_SENSE;
327
        scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
309 328
        r->req.status = CHECK_CONDITION;
310 329
        scsi_req_complete(&r->req);
311 330
        return 0;
......
313 332

  
314 333
    if (-1 == scsi_req_parse(&r->req, cmd)) {
315 334
        BADF("Unsupported command length, command %x\n", cmd[0]);
316
        scsi_req_dequeue(&r->req);
317
        scsi_req_unref(&r->req);
335
        scsi_command_complete(r, -EINVAL);
318 336
        return 0;
319 337
    }
320 338
    scsi_req_fixup(&r->req);
......
338 356
        r->buflen = 0;
339 357
        r->buf = NULL;
340 358
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
341
        if (ret == -1) {
342
            scsi_command_complete(r, -EINVAL);
359
        if (ret < 0) {
360
            scsi_command_complete(r, ret);
361
            return 0;
343 362
        }
344 363
        return 0;
345 364
    }
b/hw/scsi.h
27 27
    SCSI_XFER_TO_DEV,    /*  WRITE, MODE_SELECT, ...         */
28 28
};
29 29

  
30
typedef struct SCSISense {
31
    uint8_t key;
32
    uint8_t asc;
33
    uint8_t ascq;
34
} SCSISense;
35

  
30 36
struct SCSIRequest {
31 37
    SCSIBus           *bus;
32 38
    SCSIDevice        *dev;
......
104 110
                                      int unit, bool removable);
105 111
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
106 112

  
113
/*
114
 * Predefined sense codes
115
 */
116

  
117
/* No sense data available */
118
extern const struct SCSISense sense_code_NO_SENSE;
119
/* LUN not ready, Manual intervention required */
120
extern const struct SCSISense sense_code_LUN_NOT_READY;
121
/* LUN not ready, Medium not present */
122
extern const struct SCSISense sense_code_NO_MEDIUM;
123
/* Hardware error, internal target failure */
124
extern const struct SCSISense sense_code_TARGET_FAILURE;
125
/* Illegal request, invalid command operation code */
126
extern const struct SCSISense sense_code_INVALID_OPCODE;
127
/* Illegal request, LBA out of range */
128
extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
129
/* Illegal request, Invalid field in CDB */
130
extern const struct SCSISense sense_code_INVALID_FIELD;
131
/* Illegal request, LUN not supported */
132
extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
133
/* Command aborted, I/O process terminated */
134
extern const struct SCSISense sense_code_IO_ERROR;
135
/* Command aborted, I_T Nexus loss occurred */
136
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
137
/* Command aborted, Logical Unit failure */
138
extern const struct SCSISense sense_code_LUN_FAILURE;
139

  
140
#define SENSE_CODE(x) sense_code_ ## x
141

  
142
int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
143
int scsi_sense_valid(SCSISense sense);
144

  
107 145
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
108 146
void scsi_req_enqueue(SCSIRequest *req);
109 147
void scsi_req_free(SCSIRequest *req);
110
void scsi_req_dequeue(SCSIRequest *req);
111 148
SCSIRequest *scsi_req_ref(SCSIRequest *req);
112 149
void scsi_req_unref(SCSIRequest *req);
113 150

  

Also available in: Unified diff