]> Git Repo - qemu.git/blame - hw/scsi-disk.c
no need for bdrv_close()
[qemu.git] / hw / scsi-disk.c
CommitLineData
2e5d83bb
PB
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...) \
16do { 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...) \
22do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
23
24#include "vl.h"
25
26#define SENSE_NO_SENSE 0
1aacf348 27#define SENSE_NOT_READY 2
4d611c9a 28#define SENSE_HARDWARE_ERROR 4
2e5d83bb
PB
29#define SENSE_ILLEGAL_REQUEST 5
30
31struct SCSIDevice
32{
33 int command;
34 uint32_t tag;
35 BlockDriverState *bdrv;
7c22dd52
PB
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;
2e5d83bb
PB
39 /* When transfering data buf_pos and buf_len contain a partially
40 transferred block of data (or response to a command), and
7c22dd52
PB
41 sector/sector_count identify any remaining sectors.
42 Both sector and sector_count are in terms of qemu 512 byte blocks. */
2e5d83bb
PB
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;
4d611c9a
PB
50 BlockDriverAIOCB *aiocb;
51 /* Data still to be transfered after this request completes. */
52 uint8_t *aiodata;
53 uint32_t aiolen;
7c22dd52 54 char buf[512];
4d611c9a
PB
55 /* Completion functions may be called from either scsi_{read,write}_data
56 or from the AIO completion routines. */
2e5d83bb
PB
57 scsi_completionfn completion;
58 void *opaque;
59};
60
61static void scsi_command_complete(SCSIDevice *s, int sense)
62{
63 s->sense = sense;
4d611c9a 64 s->completion(s->opaque, SCSI_REASON_DONE, sense);
2e5d83bb
PB
65}
66
4d611c9a
PB
67static void scsi_transfer_complete(SCSIDevice *s)
68{
69 s->completion(s->opaque, SCSI_REASON_DATA, 0);
70 s->aiocb = NULL;
71}
72
73static 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. */
95void 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. */
2e5d83bb
PB
107int 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
7c22dd52 128 n = len / 512;
2e5d83bb
PB
129 if (n > s->sector_count)
130 n = s->sector_count;
131
132 if (n != 0) {
4d611c9a
PB
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);
2e5d83bb
PB
139 s->sector += n;
140 s->sector_count -= n;
4d611c9a 141 return 0;
2e5d83bb
PB
142 }
143
144 if (len && s->sector_count) {
4d611c9a 145 /* TODO: Make this use AIO. */
cac782d4 146 bdrv_read(s->bdrv, s->sector, s->buf, 1);
2e5d83bb
PB
147 s->sector++;
148 s->sector_count--;
149 s->buf_pos = 0;
7c22dd52 150 s->buf_len = 512;
2e5d83bb
PB
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);
4d611c9a
PB
160 else
161 scsi_transfer_complete(s);
2e5d83bb
PB
162
163 return 0;
164}
165
4d611c9a
PB
166static 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
181static 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. */
2e5d83bb
PB
207int 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
7c22dd52 220 if (s->buf_len != 0 || len < 512) {
4d611c9a 221 n = scsi_write_partial_sector(s, data, len);
2e5d83bb 222 len -= n;
4d611c9a 223 data += n;
2e5d83bb
PB
224 }
225
7c22dd52 226 n = len / 512;
2e5d83bb 227 if (n > s->sector_count)
4d611c9a 228 return 1;
2e5d83bb
PB
229
230 if (n != 0) {
4d611c9a
PB
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);
7c22dd52
PB
235 data += n * 512;
236 len -= n * 512;
2e5d83bb
PB
237 s->sector += n;
238 s->sector_count -= n;
239 }
240
4d611c9a
PB
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);
2e5d83bb 253 }
2e5d83bb
PB
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
0fc5c15a 263int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
2e5d83bb
PB
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:
17acfe32 301 BADF("Unsupported command length, command %x\n", s->command);
2e5d83bb
PB
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
0fc5c15a 313 if (lun || buf[1] >> 5) {
2e5d83bb 314 /* Only LUN 0 supported. */
0fc5c15a 315 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
2e5d83bb
PB
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:
7d8406be 333 DPRINTF("Inquiry (len %d)\n", len);
2e5d83bb
PB
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;
7d8406be 341 memcpy(&s->buf[16], "QEMU CD-ROM ", 16);
2e5d83bb
PB
342 } else {
343 s->buf[0] = 0;
344 memcpy(&s->buf[16], "QEMU HARDDISK ", 16);
345 }
346 memcpy(&s->buf[8], "QEMU ", 8);
7d8406be 347 memcpy(&s->buf[32], QEMU_VERSION, 4);
17acfe32
PB
348 /* Identify device as SCSI-3 rev 1.
349 Some later commands are also implemented. */
350 s->buf[2] = 3;
2e5d83bb
PB
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:
7d8406be 366 case 0x5a:
17acfe32
PB
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);
7d8406be 375 s->buf[1] = 0; /* Default media type. */
7d8406be 376 s->buf[3] = 0; /* Block descriptor length. */
17acfe32
PB
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;
7d8406be 422 }
17acfe32
PB
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);
2e5d83bb
PB
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);
51c1ebb1
PB
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);
35f1df84 450 return 0;
51c1ebb1 451 }
2e5d83bb
PB
452 break;
453 case 0x08:
454 case 0x28:
455 DPRINTF("Read (sector %d, count %d)\n", lba, len);
7c22dd52
PB
456 s->sector = lba * s->cluster_size;
457 s->sector_count = len * s->cluster_size;
2e5d83bb
PB
458 break;
459 case 0x0a:
460 case 0x2a:
461 DPRINTF("Write (sector %d, count %d)\n", lba, len);
7c22dd52
PB
462 s->sector = lba * s->cluster_size;
463 s->sector_count = len * s->cluster_size;
2e5d83bb
PB
464 is_write = 1;
465 break;
7d8406be
PB
466 case 0x35:
467 DPRINTF("Syncronise cache (sector %d, count %d)\n", lba, len);
7a6cba61 468 bdrv_flush(s->bdrv);
7d8406be 469 break;
2e5d83bb
PB
470 case 0x43:
471 {
7c22dd52 472 int start_track, format, msf, toclen;
2e5d83bb
PB
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:
7c22dd52 481 toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
2e5d83bb
PB
482 break;
483 case 1:
484 /* multi session : only a single session defined */
7c22dd52 485 toclen = 12;
2e5d83bb
PB
486 memset(s->buf, 0, 12);
487 s->buf[1] = 0x0a;
488 s->buf[2] = 0x01;
489 s->buf[3] = 0x01;
2e5d83bb
PB
490 break;
491 case 2:
7c22dd52 492 toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
2e5d83bb
PB
493 break;
494 default:
7c22dd52
PB
495 goto error_cmd;
496 }
497 if (toclen > 0) {
498 if (len > toclen)
499 len = toclen;
500 s->buf_len = len;
501 break;
2e5d83bb 502 }
7c22dd52
PB
503 error_cmd:
504 DPRINTF("Read TOC error\n");
505 goto fail;
2e5d83bb 506 }
17acfe32
PB
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;
2e5d83bb
PB
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 }
7c22dd52 542 len = s->sector_count * 512 + s->buf_len;
2e5d83bb
PB
543 return is_write ? -len : len;
544}
545
546void scsi_disk_destroy(SCSIDevice *s)
547{
2e5d83bb
PB
548 qemu_free(s);
549}
550
551SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
552 scsi_completionfn completion,
553 void *opaque)
554{
555 SCSIDevice *s;
556
557 s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
558 s->bdrv = bdrv;
559 s->completion = completion;
560 s->opaque = opaque;
561 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
7c22dd52 562 s->cluster_size = 4;
2e5d83bb 563 } else {
7c22dd52 564 s->cluster_size = 1;
2e5d83bb
PB
565 }
566
567 return s;
568}
569
This page took 0.098434 seconds and 4 git commands to generate.