Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ 35f1df84

History | View | Annotate | Download (16 kB)

1
/*
2
 * SCSI Device emulation
3
 *
4
 * Copyright (c) 2006 CodeSourcery.
5
 * Based on code by Fabrice Bellard
6
 *
7
 * Written by Paul Brook
8
 *
9
 * This code is licenced under the LGPL.
10
 */
11

    
12
//#define DEBUG_SCSI
13

    
14
#ifdef DEBUG_SCSI
15
#define DPRINTF(fmt, args...) \
16
do { printf("scsi-disk: " fmt , ##args); } while (0)
17
#else
18
#define DPRINTF(fmt, args...) do {} while(0)
19
#endif
20

    
21
#define BADF(fmt, args...) \
22
do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
23

    
24
#include "vl.h"
25

    
26
#define SENSE_NO_SENSE        0
27
#define SENSE_NOT_READY       2
28
#define SENSE_HARDWARE_ERROR  4
29
#define SENSE_ILLEGAL_REQUEST 5
30

    
31
struct SCSIDevice
32
{
33
    int command;
34
    uint32_t tag;
35
    BlockDriverState *bdrv;
36
    /* The qemu block layer uses a fixed 512 byte sector size.
37
       This is the number of 512 byte blocks in a single scsi sector.  */
38
    int cluster_size;
39
    /* When transfering data buf_pos and buf_len contain a partially
40
       transferred block of data (or response to a command), and
41
       sector/sector_count identify any remaining sectors.
42
       Both sector and sector_count are in terms of qemu 512 byte blocks.  */
43
    /* ??? We should probably keep track of whether the data trasfer is
44
       a read or a write.  Currently we rely on the host getting it right.  */
45
    int sector;
46
    int sector_count;
47
    int buf_pos;
48
    int buf_len;
49
    int sense;
50
    BlockDriverAIOCB *aiocb;
51
    /* Data still to be transfered after this request completes.  */
52
    uint8_t *aiodata;
53
    uint32_t aiolen;
54
    char buf[512];
55
    /* Completion functions may be called from either scsi_{read,write}_data
56
       or from the AIO completion routines.  */
57
    scsi_completionfn completion;
58
    void *opaque;
59
};
60

    
61
static void scsi_command_complete(SCSIDevice *s, int sense)
62
{
63
    s->sense = sense;
64
    s->completion(s->opaque, SCSI_REASON_DONE, sense);
65
}
66

    
67
static void scsi_transfer_complete(SCSIDevice *s)
68
{
69
    s->completion(s->opaque, SCSI_REASON_DATA, 0);
70
    s->aiocb = NULL;
71
}
72

    
73
static void scsi_read_complete(void * opaque, int ret)
74
{
75
    SCSIDevice *s = (SCSIDevice *)opaque;
76

    
77
    if (ret) {
78
        DPRINTF("IO error\n");
79
        scsi_command_complete(s, SENSE_HARDWARE_ERROR);
80
    }
81

    
82
    if (s->aiolen) {
83
        /* Read the remaining data.  Full and partial sectors are transferred
84
           separately.  */
85
        scsi_read_data(s, s->aiodata, s->aiolen);
86
    } else {
87
        if (s->buf_len == 0 && s->sector_count == 0)
88
            scsi_command_complete(s, SENSE_NO_SENSE);
89
        else
90
            scsi_transfer_complete(s);
91
    }
92
}
93

    
94
/* Cancel a pending data transfer.  */
95
void scsi_cancel_io(SCSIDevice *s)
96
{
97
    if (!s->aiocb) {
98
        BADF("Cancel with no pending IO\n");
99
        return;
100
    }
101
    bdrv_aio_cancel(s->aiocb);
102
    s->aiocb = NULL;
103
}
104

    
105
/* Read data from a scsi device.  Returns nonzero on failure.
106
   The transfer may complete asynchronously.  */
107
int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
108
{
109
    uint32_t n;
110

    
111
    DPRINTF("Read %d (%d/%d)\n", len, s->buf_len, s->sector_count);
112
    if (s->buf_len == 0 && s->sector_count == 0)
113
        return 1;
114

    
115
    if (s->buf_len) {
116
        n = s->buf_len;
117
        if (n > len)
118
            n = len;
119
        memcpy(data, s->buf + s->buf_pos, n);
120
        s->buf_pos += n;
121
        s->buf_len -= n;
122
        data += n;
123
        len -= n;
124
        if (s->buf_len == 0)
125
            s->buf_pos = 0;
126
    }
127

    
128
    n = len / 512;
129
    if (n > s->sector_count)
130
      n = s->sector_count;
131

    
132
    if (n != 0) {
133
        s->aiolen = len - n * 512;
134
        s->aiodata = data + n * 512;
135
        s->aiocb = bdrv_aio_read(s->bdrv, s->sector, data, n,
136
                                 scsi_read_complete, s);
137
        if (s->aiocb == NULL)
138
            scsi_command_complete(s, SENSE_HARDWARE_ERROR);
139
        s->sector += n;
140
        s->sector_count -= n;
141
        return 0;
142
    }
143

    
144
    if (len && s->sector_count) {
145
        /* TODO: Make this use AIO.  */
146
        bdrv_read(s->bdrv, s->sector, s->buf, 1);
147
        s->sector++;
148
        s->sector_count--;
149
        s->buf_pos = 0;
150
        s->buf_len = 512;
151
        /* Recurse to complete the partial read.  */
152
        return scsi_read_data(s, data, len);
153
    }
154

    
155
    if (len != 0)
156
        return 1;
157

    
158
    if (s->buf_len == 0 && s->sector_count == 0)
159
        scsi_command_complete(s, SENSE_NO_SENSE);
160
    else
161
        scsi_transfer_complete(s);
162

    
163
    return 0;
164
}
165

    
166
static void scsi_write_complete(void * opaque, int ret)
167
{
168
    SCSIDevice *s = (SCSIDevice *)opaque;
169

    
170
    if (ret) {
171
        fprintf(stderr, "scsi-disc: IO write error\n");
172
        exit(1);
173
    }
174

    
175
    if (s->sector_count == 0)
176
        scsi_command_complete(s, SENSE_NO_SENSE);
177
    else
178
        scsi_transfer_complete(s);
179
}
180

    
181
static uint32_t scsi_write_partial_sector(SCSIDevice *s, uint8_t *data,
182
                                          uint32_t len)
183
{
184
    int n;
185

    
186
    n = 512 - s->buf_len;
187
    if (n > len)
188
        n = len;
189

    
190
    memcpy(s->buf + s->buf_len, data, n);
191
    data += n;
192
    s->buf_len += n;
193
    len -= n;
194
    if (s->buf_len == 512) {
195
        /* A full sector has been accumulated. Write it to disk.  */
196
        /* TODO: Make this use async IO.  */
197
        bdrv_write(s->bdrv, s->sector, s->buf, 1);
198
        s->buf_len = 0;
199
        s->sector++;
200
        s->sector_count--;
201
    }
202
    return n;
203
}
204

    
205
/* Write data to a scsi device.  Returns nonzero on failure.
206
   The transfer may complete asynchronously.  */
207
int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
208
{
209
    uint32_t n;
210

    
211
    DPRINTF("Write %d (%d/%d)\n", len, s->buf_len, s->sector_count);
212
    if (s->buf_pos != 0) {
213
        BADF("Bad state on write\n");
214
        return 1;
215
    }
216

    
217
    if (s->sector_count == 0)
218
        return 1;
219

    
220
    if (s->buf_len != 0 || len < 512) {
221
        n = scsi_write_partial_sector(s, data, len);
222
        len -= n;
223
        data += n;
224
    }
225

    
226
    n = len / 512;
227
    if (n > s->sector_count)
228
        return 1;
229

    
230
    if (n != 0) {
231
        s->aiocb = bdrv_aio_write(s->bdrv, s->sector, data, n,
232
                                   scsi_write_complete, s);
233
        if (s->aiocb == NULL)
234
            scsi_command_complete(s, SENSE_HARDWARE_ERROR);
235
        data += n * 512;
236
        len -= n * 512;
237
        s->sector += n;
238
        s->sector_count -= n;
239
    }
240

    
241
    if (len) {
242
        if (s->sector_count == 0)
243
            return 1;
244
        /* Complete a partial write.  */
245
        scsi_write_partial_sector(s, data, len);
246
    }
247
    if (n == 0) {
248
        /* Transfer completes immediately.  */
249
        if (s->sector_count == 0)
250
            scsi_command_complete(s, SENSE_NO_SENSE);
251
        else
252
            scsi_transfer_complete(s);
253
    }
254

    
255
    return 0;
256
}
257

    
258
/* Execute a scsi command.  Returns the length of the data expected by the
259
   command.  This will be Positive for data transfers from the device
260
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
261
   and zero if the command does not transfer any data.  */
262

    
263
int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
264
{
265
    int64_t nb_sectors;
266
    uint32_t lba;
267
    uint32_t len;
268
    int cmdlen;
269
    int is_write;
270

    
271
    s->command = buf[0];
272
    s->tag = tag;
273
    s->sector_count = 0;
274
    s->buf_pos = 0;
275
    s->buf_len = 0;
276
    is_write = 0;
277
    DPRINTF("Command: 0x%02x", buf[0]);
278
    switch (s->command >> 5) {
279
    case 0:
280
        lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
281
        len = buf[4];
282
        cmdlen = 6;
283
        break;
284
    case 1:
285
    case 2:
286
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
287
        len = buf[8] | (buf[7] << 8);
288
        cmdlen = 10;
289
        break;
290
    case 4:
291
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
292
        len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
293
        cmdlen = 16;
294
        break;
295
    case 5:
296
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
297
        len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
298
        cmdlen = 12;
299
        break;
300
    default:
301
        BADF("Unsupported command length, command %x\n", s->command);
302
        goto fail;
303
    }
304
#ifdef DEBUG_SCSI
305
    {
306
        int i;
307
        for (i = 1; i < cmdlen; i++) {
308
            printf(" 0x%02x", buf[i]);
309
        }
310
        printf("\n");
311
    }
312
#endif
313
    if (lun || buf[1] >> 5) {
314
        /* Only LUN 0 supported.  */
315
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
316
        goto fail;
317
    }
318
    switch (s->command) {
319
    case 0x0:
320
        DPRINTF("Test Unit Ready\n");
321
        break;
322
    case 0x03:
323
        DPRINTF("Request Sense (len %d)\n", len);
324
        if (len < 4)
325
            goto fail;
326
        memset(buf, 0, 4);
327
        s->buf[0] = 0xf0;
328
        s->buf[1] = 0;
329
        s->buf[2] = s->sense;
330
        s->buf_len = 4;
331
        break;
332
    case 0x12:
333
        DPRINTF("Inquiry (len %d)\n", len);
334
        if (len < 36) {
335
            BADF("Inquiry buffer too small (%d)\n", len);
336
        }
337
        memset(s->buf, 0, 36);
338
        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
339
            s->buf[0] = 5;
340
            s->buf[1] = 0x80;
341
            memcpy(&s->buf[16], "QEMU CD-ROM    ", 16);
342
        } else {
343
            s->buf[0] = 0;
344
            memcpy(&s->buf[16], "QEMU HARDDISK  ", 16);
345
        }
346
        memcpy(&s->buf[8], "QEMU   ", 8);
347
        memcpy(&s->buf[32], QEMU_VERSION, 4);
348
        /* Identify device as SCSI-3 rev 1.
349
           Some later commands are also implemented. */
350
        s->buf[2] = 3;
351
        s->buf[3] = 2; /* Format 2 */
352
        s->buf[4] = 32;
353
        s->buf_len = 36;
354
        break;
355
    case 0x16:
356
        DPRINTF("Reserve(6)\n");
357
        if (buf[1] & 1)
358
            goto fail;
359
        break;
360
    case 0x17:
361
        DPRINTF("Release(6)\n");
362
        if (buf[1] & 1)
363
            goto fail;
364
        break;
365
    case 0x1a:
366
    case 0x5a:
367
        {
368
            char *p;
369
            int page;
370

    
371
            page = buf[2] & 0x3f;
372
            DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
373
            p = s->buf;
374
            memset(p, 0, 4);
375
            s->buf[1] = 0; /* Default media type.  */
376
            s->buf[3] = 0; /* Block descriptor length.  */
377
            if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
378
                s->buf[2] = 0x80; /* Readonly.  */
379
            }
380
            p += 4;
381
            if ((page == 8 || page == 0x3f)) {
382
                /* Caching page.  */
383
                p[0] = 8;
384
                p[1] = 0x12;
385
                p[2] = 4; /* WCE */
386
                p += 19;
387
            }
388
            if ((page == 0x3f || page == 0x2a)
389
                    && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
390
                /* CD Capabilities and Mechanical Status page. */
391
                p[0] = 0x2a;
392
                p[1] = 0x14;
393
                p[2] = 3; // CD-R & CD-RW read
394
                p[3] = 0; // Writing not supported
395
                p[4] = 0x7f; /* Audio, composite, digital out,
396
                                         mode 2 form 1&2, multi session */
397
                p[5] = 0xff; /* CD DA, DA accurate, RW supported,
398
                                         RW corrected, C2 errors, ISRC,
399
                                         UPC, Bar code */
400
                p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
401
                /* Locking supported, jumper present, eject, tray */
402
                p[7] = 0; /* no volume & mute control, no
403
                                      changer */
404
                p[8] = (50 * 176) >> 8; // 50x read speed
405
                p[9] = (50 * 176) & 0xff;
406
                p[10] = 0 >> 8; // No volume
407
                p[11] = 0 & 0xff;
408
                p[12] = 2048 >> 8; // 2M buffer
409
                p[13] = 2048 & 0xff;
410
                p[14] = (16 * 176) >> 8; // 16x read speed current
411
                p[15] = (16 * 176) & 0xff;
412
                p[18] = (16 * 176) >> 8; // 16x write speed
413
                p[19] = (16 * 176) & 0xff;
414
                p[20] = (16 * 176) >> 8; // 16x write speed current
415
                p[21] = (16 * 176) & 0xff;
416
                p += 21;
417
            }
418
            s->buf_len = p - s->buf;
419
            s->buf[0] = s->buf_len - 4;
420
            if (s->buf_len > len)
421
                s->buf_len = len;
422
        }
423
        break;
424
    case 0x1b:
425
        DPRINTF("Start Stop Unit\n");
426
        break;
427
    case 0x1e:
428
        DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
429
        bdrv_set_locked(s->bdrv, buf[4] & 1);
430
        break;
431
    case 0x25:
432
        DPRINTF("Read Capacity\n");
433
        /* The normal LEN field for this command is zero.  */
434
        memset(s->buf, 0, 8);
435
        bdrv_get_geometry(s->bdrv, &nb_sectors);
436
        /* Returned value is the address of the last sector.  */
437
        if (nb_sectors) {
438
            nb_sectors--;
439
            s->buf[0] = (nb_sectors >> 24) & 0xff;
440
            s->buf[1] = (nb_sectors >> 16) & 0xff;
441
            s->buf[2] = (nb_sectors >> 8) & 0xff;
442
            s->buf[3] = nb_sectors & 0xff;
443
            s->buf[4] = 0;
444
            s->buf[5] = 0;
445
            s->buf[6] = s->cluster_size * 2;
446
            s->buf[7] = 0;
447
            s->buf_len = 8;
448
        } else {
449
            scsi_command_complete(s, SENSE_NOT_READY);
450
            return 0;
451
        }
452
        break;
453
    case 0x08:
454
    case 0x28:
455
        DPRINTF("Read (sector %d, count %d)\n", lba, len);
456
        s->sector = lba * s->cluster_size;
457
        s->sector_count = len * s->cluster_size;
458
        break;
459
    case 0x0a:
460
    case 0x2a:
461
        DPRINTF("Write (sector %d, count %d)\n", lba, len);
462
        s->sector = lba * s->cluster_size;
463
        s->sector_count = len * s->cluster_size;
464
        is_write = 1;
465
        break;
466
    case 0x35:
467
        DPRINTF("Syncronise cache (sector %d, count %d)\n", lba, len);
468
        bdrv_flush(s->bdrv);
469
        break;
470
    case 0x43:
471
        {
472
            int start_track, format, msf, toclen;
473

    
474
            msf = buf[1] & 2;
475
            format = buf[2] & 0xf;
476
            start_track = buf[6];
477
            bdrv_get_geometry(s->bdrv, &nb_sectors);
478
            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
479
            switch(format) {
480
            case 0:
481
                toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
482
                break;
483
            case 1:
484
                /* multi session : only a single session defined */
485
                toclen = 12;
486
                memset(s->buf, 0, 12);
487
                s->buf[1] = 0x0a;
488
                s->buf[2] = 0x01;
489
                s->buf[3] = 0x01;
490
                break;
491
            case 2:
492
                toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
493
                break;
494
            default:
495
                goto error_cmd;
496
            }
497
            if (toclen > 0) {
498
                if (len > toclen)
499
                  len = toclen;
500
                s->buf_len = len;
501
                break;
502
            }
503
        error_cmd:
504
            DPRINTF("Read TOC error\n");
505
            goto fail;
506
        }
507
    case 0x46:
508
        DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
509
        memset(s->buf, 0, 8);
510
        /* ??? This shoud probably return much more information.  For now
511
           just return the basic header indicating the CD-ROM profile.  */
512
        s->buf[7] = 8; // CD-ROM
513
        s->buf_len = 8;
514
        break;
515
    case 0x56:
516
        DPRINTF("Reserve(10)\n");
517
        if (buf[1] & 3)
518
            goto fail;
519
        break;
520
    case 0x57:
521
        DPRINTF("Release(10)\n");
522
        if (buf[1] & 3)
523
            goto fail;
524
        break;
525
    case 0xa0:
526
        DPRINTF("Report LUNs (len %d)\n", len);
527
        if (len < 16)
528
            goto fail;
529
        memset(s->buf, 0, 16);
530
        s->buf[3] = 8;
531
        s->buf_len = 16;
532
        break;
533
    default:
534
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
535
    fail:
536
        scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
537
        return 0;
538
    }
539
    if (s->sector_count == 0 && s->buf_len == 0) {
540
        scsi_command_complete(s, SENSE_NO_SENSE);
541
    }
542
    len = s->sector_count * 512 + s->buf_len;
543
    return is_write ? -len : len;
544
}
545

    
546
void scsi_disk_destroy(SCSIDevice *s)
547
{
548
    bdrv_close(s->bdrv);
549
    qemu_free(s);
550
}
551

    
552
SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
553
                           scsi_completionfn completion,
554
                           void *opaque)
555
{
556
    SCSIDevice *s;
557

    
558
    s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
559
    s->bdrv = bdrv;
560
    s->completion = completion;
561
    s->opaque = opaque;
562
    if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
563
        s->cluster_size = 4;
564
    } else {
565
        s->cluster_size = 1;
566
    }
567

    
568
    return s;
569
}
570