2 * SCSI Device emulation
4 * Copyright (c) 2006 CodeSourcery.
5 * Based on code by Fabrice Bellard
7 * Written by Paul Brook
9 * This code is licenced under the LGPL.
15 #define DPRINTF(fmt, args...) \
16 do { printf("scsi-disk: " fmt , ##args); } while (0)
18 #define DPRINTF(fmt, args...) do {} while(0)
21 #define BADF(fmt, args...) \
22 do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
26 #define SENSE_NO_SENSE 0
27 #define SENSE_ILLEGAL_REQUEST 5
33 BlockDriverState *bdrv;
35 /* When transfering data buf_pos and buf_len contain a partially
36 transferred block of data (or response to a command), and
37 sector/sector_count identify any remaining sectors. */
38 /* ??? We should probably keep track of whether the data trasfer is
39 a read or a write. Currently we rely on the host getting it right. */
46 scsi_completionfn completion;
50 static void scsi_command_complete(SCSIDevice *s, int sense)
53 s->completion(s->opaque, s->tag, sense != SENSE_NO_SENSE);
56 /* Read data from a scsi device. Returns nonzero on failure. */
57 int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
61 DPRINTF("Read %d (%d/%d)\n", len, s->buf_len, s->sector_count);
62 if (s->buf_len == 0 && s->sector_count == 0)
69 memcpy(data, s->buf + s->buf_pos, n);
78 n = len / s->sector_size;
79 if (n > s->sector_count)
83 bdrv_read(s->bdrv, s->sector, data, n);
84 data += n * s->sector_size;
85 len -= n * s->sector_size;
90 if (len && s->sector_count) {
91 bdrv_read(s->bdrv, s->sector, s->buf, 1);
95 s->buf_len = s->sector_size;
96 /* Recurse to complete the partial read. */
97 return scsi_read_data(s, data, len);
103 if (s->buf_len == 0 && s->sector_count == 0)
104 scsi_command_complete(s, SENSE_NO_SENSE);
109 /* Read data to a scsi device. Returns nonzero on failure. */
110 int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
114 DPRINTF("Write %d (%d/%d)\n", len, s->buf_len, s->sector_count);
115 if (s->buf_pos != 0) {
116 BADF("Bad state on write\n");
120 if (s->sector_count == 0)
123 if (s->buf_len != 0 || len < s->sector_size) {
124 n = s->sector_size - s->buf_len;
128 memcpy(s->buf + s->buf_len, data, n);
132 if (s->buf_len == s->sector_size) {
133 /* A full sector has been accumulated. Write it to disk. */
134 bdrv_write(s->bdrv, s->sector, s->buf, 1);
141 n = len / s->sector_size;
142 if (n > s->sector_count)
146 bdrv_write(s->bdrv, s->sector, data, n);
147 data += n * s->sector_size;
148 len -= n * s->sector_size;
150 s->sector_count -= n;
153 if (len >= s->sector_size)
156 if (len && s->sector_count) {
157 /* Recurse to complete the partial write. */
158 return scsi_write_data(s, data, len);
164 if (s->sector_count == 0)
165 scsi_command_complete(s, SENSE_NO_SENSE);
170 /* Execute a scsi command. Returns the length of the data expected by the
171 command. This will be Positive for data transfers from the device
172 (eg. disk reads), negative for transfers to the device (eg. disk writes),
173 and zero if the command does not transfer any data. */
175 int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
189 DPRINTF("Command: 0x%02x", buf[0]);
190 switch (s->command >> 5) {
192 lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
198 lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
199 len = buf[8] | (buf[7] << 8);
203 lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
204 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
208 lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
209 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
213 BADF("Unsupported command length\n");
219 for (i = 1; i < cmdlen; i++) {
220 printf(" 0x%02x", buf[i]);
226 /* Only LUN 0 supported. */
229 switch (s->command) {
231 DPRINTF("Test Unit Ready\n");
234 DPRINTF("Request Sense (len %d)\n", len);
240 s->buf[2] = s->sense;
244 DPRINTF("Inquiry (len %d)\n", len);
246 BADF("Inquiry buffer too small (%d)\n", len);
248 memset(s->buf, 0, 36);
249 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
252 memcpy(&s->buf[16], "QEMU CDROM ", 16);
255 memcpy(&s->buf[16], "QEMU HARDDISK ", 16);
257 memcpy(&s->buf[8], "QEMU ", 8);
258 s->buf[2] = 3; /* SCSI-3 */
259 s->buf[3] = 2; /* Format 2 */
264 DPRINTF("Reserve(6)\n");
269 DPRINTF("Release(6)\n");
274 DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[2], len);
275 memset(s->buf, 0, 4);
276 s->buf[0] = 0x16; /* Mode data length (4 + 0x12). */
277 s->buf[1] = 0; /* Default media type. */
278 s->buf[2] = 0; /* Write enabled. */
279 s->buf[3] = 0; /* Block descriptor length. */
282 s->buf[4 + 1] = 0x12;
283 s->buf[4 + 2] = 4; /* WCE */
289 DPRINTF("Read Capacity\n");
290 /* The normal LEN field for this command is zero. */
291 memset(s->buf, 0, 8);
292 bdrv_get_geometry(s->bdrv, &nb_sectors);
293 s->buf[0] = (nb_sectors >> 24) & 0xff;
294 s->buf[1] = (nb_sectors >> 16) & 0xff;
295 s->buf[2] = (nb_sectors >> 8) & 0xff;
296 s->buf[3] = nb_sectors & 0xff;
299 s->buf[6] = s->sector_size >> 8;
300 s->buf[7] = s->sector_size & 0xff;
305 DPRINTF("Read (sector %d, count %d)\n", lba, len);
307 s->sector_count = len;
311 DPRINTF("Write (sector %d, count %d)\n", lba, len);
313 s->sector_count = len;
318 int start_track, format, msf;
321 format = buf[2] & 0xf;
322 start_track = buf[6];
323 bdrv_get_geometry(s->bdrv, &nb_sectors);
324 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
327 len = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
333 /* multi session : only a single session defined */
334 memset(s->buf, 0, 12);
341 len = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
348 DPRINTF("Read TOC error\n");
354 DPRINTF("Reserve(10)\n");
359 DPRINTF("Release(10)\n");
364 DPRINTF("Report LUNs (len %d)\n", len);
367 memset(s->buf, 0, 16);
372 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
374 scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
377 if (s->sector_count == 0 && s->buf_len == 0) {
378 scsi_command_complete(s, SENSE_NO_SENSE);
380 len = s->sector_count * s->sector_size + s->buf_len;
381 return is_write ? -len : len;
384 void scsi_disk_destroy(SCSIDevice *s)
390 SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
391 scsi_completionfn completion,
396 s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
398 s->completion = completion;
400 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
401 s->sector_size = 2048;
403 s->sector_size = 512;