Revision 2ec749cb

b/hw/scsi-bus.c
1 1
#include "hw.h"
2 2
#include "sysemu.h"
3 3
#include "scsi.h"
4
#include "scsi-defs.h"
4 5
#include "block.h"
5 6
#include "qdev.h"
6 7

  
......
142 143
    QTAILQ_REMOVE(&req->dev->requests, req, next);
143 144
    qemu_free(req);
144 145
}
146

  
147
static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
148
{
149
    switch (cmd[0] >> 5) {
150
    case 0:
151
        req->cmd.xfer = cmd[4];
152
        req->cmd.len = 6;
153
        /* length 0 means 256 blocks */
154
        if (req->cmd.xfer == 0)
155
            req->cmd.xfer = 256;
156
        break;
157
    case 1:
158
    case 2:
159
        req->cmd.xfer = cmd[8] | (cmd[7] << 8);
160
        req->cmd.len = 10;
161
        break;
162
    case 4:
163
        req->cmd.xfer = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
164
        req->cmd.len = 16;
165
        break;
166
    case 5:
167
        req->cmd.xfer = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
168
        req->cmd.len = 12;
169
        break;
170
    default:
171
        return -1;
172
    }
173

  
174
    switch(cmd[0]) {
175
    case TEST_UNIT_READY:
176
    case REZERO_UNIT:
177
    case START_STOP:
178
    case SEEK_6:
179
    case WRITE_FILEMARKS:
180
    case SPACE:
181
    case ERASE:
182
    case ALLOW_MEDIUM_REMOVAL:
183
    case VERIFY:
184
    case SEEK_10:
185
    case SYNCHRONIZE_CACHE:
186
    case LOCK_UNLOCK_CACHE:
187
    case LOAD_UNLOAD:
188
    case SET_CD_SPEED:
189
    case SET_LIMITS:
190
    case WRITE_LONG:
191
    case MOVE_MEDIUM:
192
    case UPDATE_BLOCK:
193
        req->cmd.xfer = 0;
194
        break;
195
    case MODE_SENSE:
196
        break;
197
    case WRITE_SAME:
198
        req->cmd.xfer = 1;
199
        break;
200
    case READ_CAPACITY:
201
        req->cmd.xfer = 8;
202
        break;
203
    case READ_BLOCK_LIMITS:
204
        req->cmd.xfer = 6;
205
        break;
206
    case READ_POSITION:
207
        req->cmd.xfer = 20;
208
        break;
209
    case SEND_VOLUME_TAG:
210
        req->cmd.xfer *= 40;
211
        break;
212
    case MEDIUM_SCAN:
213
        req->cmd.xfer *= 8;
214
        break;
215
    case WRITE_10:
216
    case WRITE_VERIFY:
217
    case WRITE_6:
218
    case WRITE_12:
219
    case WRITE_VERIFY_12:
220
        req->cmd.xfer *= req->dev->blocksize;
221
        break;
222
    case READ_10:
223
    case READ_6:
224
    case READ_REVERSE:
225
    case RECOVER_BUFFERED_DATA:
226
    case READ_12:
227
        req->cmd.xfer *= req->dev->blocksize;
228
        break;
229
    case INQUIRY:
230
        req->cmd.xfer = cmd[4] | (cmd[3] << 8);
231
        break;
232
    }
233
    return 0;
234
}
235

  
236
static int scsi_req_stream_length(SCSIRequest *req, uint8_t *cmd)
237
{
238
    switch(cmd[0]) {
239
    /* stream commands */
240
    case READ_6:
241
    case READ_REVERSE:
242
    case RECOVER_BUFFERED_DATA:
243
    case WRITE_6:
244
        req->cmd.len = 6;
245
        req->cmd.xfer = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
246
        if (cmd[1] & 0x01) /* fixed */
247
            req->cmd.xfer *= req->dev->blocksize;
248
        break;
249
    case REWIND:
250
    case START_STOP:
251
        req->cmd.len = 6;
252
        req->cmd.xfer = 0;
253
        break;
254
    /* generic commands */
255
    default:
256
        return scsi_req_length(req, cmd);
257
    }
258
    return 0;
259
}
260

  
261
static uint64_t scsi_req_lba(SCSIRequest *req)
262
{
263
    uint8_t *buf = req->cmd.buf;
264
    uint64_t lba;
265

  
266
    switch (buf[0] >> 5) {
267
    case 0:
268
        lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
269
              (((uint64_t) buf[1] & 0x1f) << 16);
270
        break;
271
    case 1:
272
    case 2:
273
        lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
274
              ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
275
        break;
276
    case 4:
277
        lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
278
              ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
279
              ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
280
              ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
281
        break;
282
    case 5:
283
        lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
284
              ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
285
        break;
286
    default:
287
        lba = -1;
288

  
289
    }
290
    return lba;
291
}
292

  
293
int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
294
{
295
    int rc;
296

  
297
    if (req->dev->type == TYPE_TAPE) {
298
        rc = scsi_req_stream_length(req, buf);
299
    } else {
300
        rc = scsi_req_length(req, buf);
301
    }
302
    if (rc != 0)
303
        return rc;
304

  
305
    memcpy(req->cmd.buf, buf, req->cmd.len);
306
    req->cmd.lba = scsi_req_lba(req);
307
    return 0;
308
}
b/hw/scsi-generic.c
288 288
    return r->buf;
289 289
}
290 290

  
291
static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
291
static void scsi_req_fixup(SCSIRequest *req)
292 292
{
293
    switch (cmd[0] >> 5) {
294
    case 0:
295
        *len = cmd[4];
296
        *cmdlen = 6;
297
        /* length 0 means 256 blocks */
298
        if (*len == 0)
299
            *len = 256;
300
        break;
301
    case 1:
302
    case 2:
303
        *len = cmd[8] | (cmd[7] << 8);
304
        *cmdlen = 10;
305
        break;
306
    case 4:
307
        *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
308
        *cmdlen = 16;
309
        break;
310
    case 5:
311
        *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
312
        *cmdlen = 12;
313
        break;
314
    default:
315
        return -1;
316
    }
317

  
318
    switch(cmd[0]) {
319
    case TEST_UNIT_READY:
320
    case REZERO_UNIT:
321
    case START_STOP:
322
    case SEEK_6:
323
    case WRITE_FILEMARKS:
324
    case SPACE:
325
    case ERASE:
326
    case ALLOW_MEDIUM_REMOVAL:
327
    case VERIFY:
328
    case SEEK_10:
329
    case SYNCHRONIZE_CACHE:
330
    case LOCK_UNLOCK_CACHE:
331
    case LOAD_UNLOAD:
332
    case SET_CD_SPEED:
333
    case SET_LIMITS:
334
    case WRITE_LONG:
335
    case MOVE_MEDIUM:
336
    case UPDATE_BLOCK:
337
        *len = 0;
338
        break;
339
    case MODE_SENSE:
340
        break;
341
    case WRITE_SAME:
342
        *len = 1;
343
        break;
344
    case READ_CAPACITY:
345
        *len = 8;
346
        break;
347
    case READ_BLOCK_LIMITS:
348
        *len = 6;
349
        break;
350
    case READ_POSITION:
351
        *len = 20;
352
        break;
353
    case SEND_VOLUME_TAG:
354
        *len *= 40;
355
        break;
356
    case MEDIUM_SCAN:
357
        *len *= 8;
358
        break;
293
    switch(req->cmd.buf[0]) {
359 294
    case WRITE_10:
360
        cmd[1] &= ~0x08;	/* disable FUA */
361
    case WRITE_VERIFY:
362
    case WRITE_6:
363
    case WRITE_12:
364
    case WRITE_VERIFY_12:
365
        *len *= blocksize;
295
        req->cmd.buf[1] &= ~0x08;	/* disable FUA */
366 296
        break;
367 297
    case READ_10:
368
        cmd[1] &= ~0x08;	/* disable FUA */
369
    case READ_6:
370
    case READ_REVERSE:
371
    case RECOVER_BUFFERED_DATA:
372
    case READ_12:
373
        *len *= blocksize;
374
        break;
375
    case INQUIRY:
376
        *len = cmd[4] | (cmd[3] << 8);
377
        break;
378
    }
379
    return 0;
380
}
381

  
382
static int scsi_stream_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
383
{
384
    switch(cmd[0]) {
385
    /* stream commands */
386
    case READ_6:
387
    case READ_REVERSE:
388
    case RECOVER_BUFFERED_DATA:
389
    case WRITE_6:
390
        *cmdlen = 6;
391
        *len = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
392
        if (cmd[1] & 0x01) /* fixed */
393
            *len *= blocksize;
298
        req->cmd.buf[1] &= ~0x08;	/* disable FUA */
394 299
        break;
395 300
    case REWIND:
396 301
    case START_STOP:
397
        *cmdlen = 6;
398
        *len = 0;
399
        cmd[1] = 0x01;	/* force IMMED, otherwise qemu waits end of command */
302
        if (req->dev->type == TYPE_TAPE) {
303
            /* force IMMED, otherwise qemu waits end of command */
304
            req->cmd.buf[1] = 0x01;
305
        }
400 306
        break;
401
    /* generic commands */
402
    default:
403
        return scsi_length(cmd, blocksize, cmdlen, len);
404 307
    }
405
    return 0;
406 308
}
407 309

  
408 310
static int is_write(int command)
......
452 354
                                 uint8_t *cmd, int lun)
453 355
{
454 356
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
455
    uint32_t len=0;
456
    int cmdlen=0;
457 357
    SCSIGenericReq *r;
458 358
    SCSIBus *bus;
459 359
    int ret;
460 360

  
461
    if (s->qdev.type == TYPE_TAPE) {
462
        if (scsi_stream_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
463
            BADF("Unsupported command length, command %x\n", cmd[0]);
464
            return 0;
465
        }
466
     } else {
467
        if (scsi_length(cmd, s->qdev.blocksize, &cmdlen, &len) == -1) {
468
            BADF("Unsupported command length, command %x\n", cmd[0]);
469
            return 0;
470
        }
471
    }
472

  
473
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
474
            cmd[0], len);
475

  
476 361
    if (cmd[0] != REQUEST_SENSE &&
477 362
        (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
478 363
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
......
498 383
    }
499 384
    r = scsi_new_request(d, tag, lun);
500 385

  
501
    memcpy(r->req.cmd.buf, cmd, cmdlen);
502
    r->req.cmd.len = cmdlen;
386
    if (-1 == scsi_req_parse(&r->req, cmd)) {
387
        BADF("Unsupported command length, command %x\n", cmd[0]);
388
        scsi_remove_request(r);
389
        return 0;
390
    }
391
    scsi_req_fixup(&r->req);
392

  
393
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
394
            cmd[0], r->req.cmd.xfer);
503 395

  
504
    if (len == 0) {
396
    if (r->req.cmd.xfer == 0) {
505 397
        if (r->buf != NULL)
506 398
            qemu_free(r->buf);
507 399
        r->buflen = 0;
......
514 406
        return 0;
515 407
    }
516 408

  
517
    if (r->buflen != len) {
409
    if (r->buflen != r->req.cmd.xfer) {
518 410
        if (r->buf != NULL)
519 411
            qemu_free(r->buf);
520
        r->buf = qemu_malloc(len);
521
        r->buflen = len;
412
        r->buf = qemu_malloc(r->req.cmd.xfer);
413
        r->buflen = r->req.cmd.xfer;
522 414
    }
523 415

  
524 416
    memset(r->buf, 0, r->buflen);
525
    r->len = len;
417
    r->len = r->req.cmd.xfer;
526 418
    if (is_write(cmd[0])) {
527 419
        r->len = 0;
528
        return -len;
420
        return -r->req.cmd.xfer;
529 421
    }
530 422

  
531
    return len;
423
    return r->req.cmd.xfer;
532 424
}
533 425

  
534 426
static int get_blocksize(BlockDriverState *bdrv)
b/hw/scsi.h
26 26
    struct {
27 27
        uint8_t buf[SCSI_CMD_BUF_SIZE];
28 28
        int len;
29
        size_t xfer;
30
        uint64_t lba;
29 31
    } cmd;
30 32
    BlockDriverAIOCB  *aiocb;
31 33
    QTAILQ_ENTRY(SCSIRequest) next;
......
86 88
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
87 89
SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
88 90
void scsi_req_free(SCSIRequest *req);
91
int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
89 92

  
90 93
#endif

Also available in: Unified diff