SCSI lun probing fix.
[qemu] / hw / scsi-disk.c
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_ILLEGAL_REQUEST 5
28
29 struct SCSIDevice
30 {
31     int command;
32     uint32_t tag;
33     BlockDriverState *bdrv;
34     /* The qemu block layer uses a fixed 512 byte sector size.
35        This is the number of 512 byte blocks in a single scsi sector.  */
36     int cluster_size;
37     /* When transfering data buf_pos and buf_len contain a partially
38        transferred block of data (or response to a command), and
39        sector/sector_count identify any remaining sectors.
40        Both sector and sector_count are in terms of qemu 512 byte blocks.  */
41     /* ??? We should probably keep track of whether the data trasfer is
42        a read or a write.  Currently we rely on the host getting it right.  */
43     int sector;
44     int sector_count;
45     int buf_pos;
46     int buf_len;
47     int sense;
48     char buf[512];
49     scsi_completionfn completion;
50     void *opaque;
51 };
52
53 static void scsi_command_complete(SCSIDevice *s, int sense)
54 {
55     s->sense = sense;
56     s->completion(s->opaque, s->tag, sense);
57 }
58
59 /* Read data from a scsi device.  Returns nonzero on failure.  */
60 int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
61 {
62     uint32_t n;
63
64     DPRINTF("Read %d (%d/%d)\n", len, s->buf_len, s->sector_count);
65     if (s->buf_len == 0 && s->sector_count == 0)
66         return 1;
67
68     if (s->buf_len) {
69         n = s->buf_len;
70         if (n > len)
71             n = len;
72         memcpy(data, s->buf + s->buf_pos, n);
73         s->buf_pos += n;
74         s->buf_len -= n;
75         data += n;
76         len -= n;
77         if (s->buf_len == 0)
78             s->buf_pos = 0;
79     }
80
81     n = len / 512;
82     if (n > s->sector_count)
83       n = s->sector_count;
84
85     if (n != 0) {
86         bdrv_read(s->bdrv, s->sector, data, n);
87         data += n * 512;
88         len -= n * 512;
89         s->sector += n;
90         s->sector_count -= n;
91     }
92
93     if (len && s->sector_count) {
94         bdrv_read(s->bdrv, s->sector, s->buf, 1);
95         s->sector++;
96         s->sector_count--;
97         s->buf_pos = 0;
98         s->buf_len = 512;
99         /* Recurse to complete the partial read.  */
100         return scsi_read_data(s, data, len);
101     }
102
103     if (len != 0)
104         return 1;
105
106     if (s->buf_len == 0 && s->sector_count == 0)
107         scsi_command_complete(s, SENSE_NO_SENSE);
108
109     return 0;
110 }
111
112 /* Read data to a scsi device.  Returns nonzero on failure.  */
113 int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
114 {
115     uint32_t n;
116
117     DPRINTF("Write %d (%d/%d)\n", len, s->buf_len, s->sector_count);
118     if (s->buf_pos != 0) {
119         BADF("Bad state on write\n");
120         return 1;
121     }
122
123     if (s->sector_count == 0)
124         return 1;
125
126     if (s->buf_len != 0 || len < 512) {
127         n = 512 - s->buf_len;
128         if (n > len)
129             n = len;
130
131         memcpy(s->buf + s->buf_len, data, n);
132         data += n;
133         s->buf_len += n;
134         len -= n;
135         if (s->buf_len == 512) {
136             /* A full sector has been accumulated. Write it to disk.  */
137             bdrv_write(s->bdrv, s->sector, s->buf, 1);
138             s->buf_len = 0;
139             s->sector++;
140             s->sector_count--;
141         }
142     }
143
144     n = len / 512;
145     if (n > s->sector_count)
146         n = s->sector_count;
147
148     if (n != 0) {
149         bdrv_write(s->bdrv, s->sector, data, n);
150         data += n * 512;
151         len -= n * 512;
152         s->sector += n;
153         s->sector_count -= n;
154     }
155
156     if (len >= 512)
157         return 1;
158
159     if (len && s->sector_count) {
160         /* Recurse to complete the partial write.  */
161         return scsi_write_data(s, data, len);
162     }
163
164     if (len != 0)
165         return 1;
166
167     if (s->sector_count == 0)
168         scsi_command_complete(s, SENSE_NO_SENSE);
169
170     return 0;
171 }
172
173 /* Execute a scsi command.  Returns the length of the data expected by the
174    command.  This will be Positive for data transfers from the device
175    (eg. disk reads), negative for transfers to the device (eg. disk writes),
176    and zero if the command does not transfer any data.  */
177
178 int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
179 {
180     int64_t nb_sectors;
181     uint32_t lba;
182     uint32_t len;
183     int cmdlen;
184     int is_write;
185
186     s->command = buf[0];
187     s->tag = tag;
188     s->sector_count = 0;
189     s->buf_pos = 0;
190     s->buf_len = 0;
191     is_write = 0;
192     DPRINTF("Command: 0x%02x", buf[0]);
193     switch (s->command >> 5) {
194     case 0:
195         lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
196         len = buf[4];
197         cmdlen = 6;
198         break;
199     case 1:
200     case 2:
201         lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
202         len = buf[8] | (buf[7] << 8);
203         cmdlen = 10;
204         break;
205     case 4:
206         lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
207         len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
208         cmdlen = 16;
209         break;
210     case 5:
211         lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
212         len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
213         cmdlen = 12;
214         break;
215     default:
216         BADF("Unsupported command length\n");
217         goto fail;
218     }
219 #ifdef DEBUG_SCSI
220     {
221         int i;
222         for (i = 1; i < cmdlen; i++) {
223             printf(" 0x%02x", buf[i]);
224         }
225         printf("\n");
226     }
227 #endif
228     if (lun || buf[1] >> 5) {
229         /* Only LUN 0 supported.  */
230         DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
231         goto fail;
232     }
233     switch (s->command) {
234     case 0x0:
235         DPRINTF("Test Unit Ready\n");
236         break;
237     case 0x03:
238         DPRINTF("Request Sense (len %d)\n", len);
239         if (len < 4)
240             goto fail;
241         memset(buf, 0, 4);
242         s->buf[0] = 0xf0;
243         s->buf[1] = 0;
244         s->buf[2] = s->sense;
245         s->buf_len = 4;
246         break;
247     case 0x12:
248         DPRINTF("Inquiry (len %d)\n", len);
249         if (len < 36) {
250             BADF("Inquiry buffer too small (%d)\n", len);
251         }
252         memset(s->buf, 0, 36);
253         if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
254             s->buf[0] = 5;
255             s->buf[1] = 0x80;
256             memcpy(&s->buf[16], "QEMU CDROM     ", 16);
257         } else {
258             s->buf[0] = 0;
259             memcpy(&s->buf[16], "QEMU HARDDISK  ", 16);
260         }
261         memcpy(&s->buf[8], "QEMU   ", 8);
262         s->buf[2] = 3; /* SCSI-3 */
263         s->buf[3] = 2; /* Format 2 */
264         s->buf[4] = 32;
265         s->buf_len = 36;
266         break;
267     case 0x16:
268         DPRINTF("Reserve(6)\n");
269         if (buf[1] & 1)
270             goto fail;
271         break;
272     case 0x17:
273         DPRINTF("Release(6)\n");
274         if (buf[1] & 1)
275             goto fail;
276         break;
277     case 0x1a:
278         DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[2], len);
279         memset(s->buf, 0, 4);
280         s->buf[0] = 0x16; /* Mode data length (4 + 0x12).  */
281         s->buf[1] = 0; /* Default media type.  */
282         s->buf[2] = 0; /* Write enabled.  */
283         s->buf[3] = 0; /* Block descriptor length.  */
284         /* Caching page.  */
285         s->buf[4 + 0] = 8;
286         s->buf[4 + 1] = 0x12;
287         s->buf[4 + 2] = 4; /* WCE */
288         if (len > 0x16)
289             len = 0x16;
290         s->buf_len = len;
291         break;
292     case 0x25:
293         DPRINTF("Read Capacity\n");
294         /* The normal LEN field for this command is zero.  */
295         memset(s->buf, 0, 8);
296         bdrv_get_geometry(s->bdrv, &nb_sectors);
297         s->buf[0] = (nb_sectors >> 24) & 0xff;
298         s->buf[1] = (nb_sectors >> 16) & 0xff;
299         s->buf[2] = (nb_sectors >> 8) & 0xff;
300         s->buf[3] = nb_sectors & 0xff;
301         s->buf[4] = 0;
302         s->buf[5] = 0;
303         s->buf[6] = s->cluster_size * 2;
304         s->buf[7] = 0;
305         s->buf_len = 8;
306         break;
307     case 0x08:
308     case 0x28:
309         DPRINTF("Read (sector %d, count %d)\n", lba, len);
310         s->sector = lba * s->cluster_size;
311         s->sector_count = len * s->cluster_size;
312         break;
313     case 0x0a:
314     case 0x2a:
315         DPRINTF("Write (sector %d, count %d)\n", lba, len);
316         s->sector = lba * s->cluster_size;
317         s->sector_count = len * s->cluster_size;
318         is_write = 1;
319         break;
320     case 0x43:
321         {
322             int start_track, format, msf, toclen;
323
324             msf = buf[1] & 2;
325             format = buf[2] & 0xf;
326             start_track = buf[6];
327             bdrv_get_geometry(s->bdrv, &nb_sectors);
328             DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
329             switch(format) {
330             case 0:
331                 toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
332                 break;
333             case 1:
334                 /* multi session : only a single session defined */
335                 toclen = 12;
336                 memset(s->buf, 0, 12);
337                 s->buf[1] = 0x0a;
338                 s->buf[2] = 0x01;
339                 s->buf[3] = 0x01;
340                 break;
341             case 2:
342                 toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
343                 break;
344             default:
345                 goto error_cmd;
346             }
347             if (toclen > 0) {
348                 if (len > toclen)
349                   len = toclen;
350                 s->buf_len = len;
351                 break;
352             }
353         error_cmd:
354             DPRINTF("Read TOC error\n");
355             goto fail;
356         }
357     case 0x56:
358         DPRINTF("Reserve(10)\n");
359         if (buf[1] & 3)
360             goto fail;
361         break;
362     case 0x57:
363         DPRINTF("Release(10)\n");
364         if (buf[1] & 3)
365             goto fail;
366         break;
367     case 0xa0:
368         DPRINTF("Report LUNs (len %d)\n", len);
369         if (len < 16)
370             goto fail;
371         memset(s->buf, 0, 16);
372         s->buf[3] = 8;
373         s->buf_len = 16;
374         break;
375     default:
376         DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
377     fail:
378         scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
379         return 0;
380     }
381     if (s->sector_count == 0 && s->buf_len == 0) {
382         scsi_command_complete(s, SENSE_NO_SENSE);
383     }
384     len = s->sector_count * 512 + s->buf_len;
385     return is_write ? -len : len;
386 }
387
388 void scsi_disk_destroy(SCSIDevice *s)
389 {
390     bdrv_close(s->bdrv);
391     qemu_free(s);
392 }
393
394 SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
395                            scsi_completionfn completion,
396                            void *opaque)
397 {
398     SCSIDevice *s;
399
400     s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
401     s->bdrv = bdrv;
402     s->completion = completion;
403     s->opaque = opaque;
404     if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
405         s->cluster_size = 4;
406     } else {
407         s->cluster_size = 1;
408     }
409
410     return s;
411 }
412