Revision a1f0cce2 hw/scsi-disk.c

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) {

Also available in: Unified diff