]> git.proxmox.com Git - qemu.git/blame - hw/scsi-disk.c
fixed blocking io emulation
[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
27#define SENSE_ILLEGAL_REQUEST 5
28
29struct SCSIDevice
30{
31 int command;
32 uint32_t tag;
33 BlockDriverState *bdrv;
7c22dd52
PB
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;
2e5d83bb
PB
37 /* When transfering data buf_pos and buf_len contain a partially
38 transferred block of data (or response to a command), and
7c22dd52
PB
39 sector/sector_count identify any remaining sectors.
40 Both sector and sector_count are in terms of qemu 512 byte blocks. */
2e5d83bb
PB
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;
7c22dd52 48 char buf[512];
2e5d83bb
PB
49 scsi_completionfn completion;
50 void *opaque;
51};
52
53static void scsi_command_complete(SCSIDevice *s, int sense)
54{
55 s->sense = sense;
0fc5c15a 56 s->completion(s->opaque, s->tag, sense);
2e5d83bb
PB
57}
58
59/* Read data from a scsi device. Returns nonzero on failure. */
60int 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
7c22dd52 81 n = len / 512;
2e5d83bb
PB
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);
7c22dd52
PB
87 data += n * 512;
88 len -= n * 512;
2e5d83bb
PB
89 s->sector += n;
90 s->sector_count -= n;
91 }
92
93 if (len && s->sector_count) {
cac782d4 94 bdrv_read(s->bdrv, s->sector, s->buf, 1);
2e5d83bb
PB
95 s->sector++;
96 s->sector_count--;
97 s->buf_pos = 0;
7c22dd52 98 s->buf_len = 512;
2e5d83bb
PB
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. */
113int 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
7c22dd52
PB
126 if (s->buf_len != 0 || len < 512) {
127 n = 512 - s->buf_len;
2e5d83bb
PB
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;
7c22dd52 135 if (s->buf_len == 512) {
2e5d83bb
PB
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
7c22dd52 144 n = len / 512;
2e5d83bb
PB
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);
7c22dd52
PB
150 data += n * 512;
151 len -= n * 512;
2e5d83bb
PB
152 s->sector += n;
153 s->sector_count -= n;
154 }
155
7c22dd52 156 if (len >= 512)
2e5d83bb
PB
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
0fc5c15a 178int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
2e5d83bb
PB
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:
17acfe32 216 BADF("Unsupported command length, command %x\n", s->command);
2e5d83bb
PB
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
0fc5c15a 228 if (lun || buf[1] >> 5) {
2e5d83bb 229 /* Only LUN 0 supported. */
0fc5c15a 230 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
2e5d83bb
PB
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:
7d8406be 248 DPRINTF("Inquiry (len %d)\n", len);
2e5d83bb
PB
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;
7d8406be 256 memcpy(&s->buf[16], "QEMU CD-ROM ", 16);
2e5d83bb
PB
257 } else {
258 s->buf[0] = 0;
259 memcpy(&s->buf[16], "QEMU HARDDISK ", 16);
260 }
261 memcpy(&s->buf[8], "QEMU ", 8);
7d8406be 262 memcpy(&s->buf[32], QEMU_VERSION, 4);
17acfe32
PB
263 /* Identify device as SCSI-3 rev 1.
264 Some later commands are also implemented. */
265 s->buf[2] = 3;
2e5d83bb
PB
266 s->buf[3] = 2; /* Format 2 */
267 s->buf[4] = 32;
268 s->buf_len = 36;
269 break;
270 case 0x16:
271 DPRINTF("Reserve(6)\n");
272 if (buf[1] & 1)
273 goto fail;
274 break;
275 case 0x17:
276 DPRINTF("Release(6)\n");
277 if (buf[1] & 1)
278 goto fail;
279 break;
280 case 0x1a:
7d8406be 281 case 0x5a:
17acfe32
PB
282 {
283 char *p;
284 int page;
285
286 page = buf[2] & 0x3f;
287 DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
288 p = s->buf;
289 memset(p, 0, 4);
7d8406be 290 s->buf[1] = 0; /* Default media type. */
7d8406be 291 s->buf[3] = 0; /* Block descriptor length. */
17acfe32
PB
292 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
293 s->buf[2] = 0x80; /* Readonly. */
294 }
295 p += 4;
296 if ((page == 8 || page == 0x3f)) {
297 /* Caching page. */
298 p[0] = 8;
299 p[1] = 0x12;
300 p[2] = 4; /* WCE */
301 p += 19;
302 }
303 if ((page == 0x3f || page == 0x2a)
304 && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
305 /* CD Capabilities and Mechanical Status page. */
306 p[0] = 0x2a;
307 p[1] = 0x14;
308 p[2] = 3; // CD-R & CD-RW read
309 p[3] = 0; // Writing not supported
310 p[4] = 0x7f; /* Audio, composite, digital out,
311 mode 2 form 1&2, multi session */
312 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
313 RW corrected, C2 errors, ISRC,
314 UPC, Bar code */
315 p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
316 /* Locking supported, jumper present, eject, tray */
317 p[7] = 0; /* no volume & mute control, no
318 changer */
319 p[8] = (50 * 176) >> 8; // 50x read speed
320 p[9] = (50 * 176) & 0xff;
321 p[10] = 0 >> 8; // No volume
322 p[11] = 0 & 0xff;
323 p[12] = 2048 >> 8; // 2M buffer
324 p[13] = 2048 & 0xff;
325 p[14] = (16 * 176) >> 8; // 16x read speed current
326 p[15] = (16 * 176) & 0xff;
327 p[18] = (16 * 176) >> 8; // 16x write speed
328 p[19] = (16 * 176) & 0xff;
329 p[20] = (16 * 176) >> 8; // 16x write speed current
330 p[21] = (16 * 176) & 0xff;
331 p += 21;
332 }
333 s->buf_len = p - s->buf;
334 s->buf[0] = s->buf_len - 4;
335 if (s->buf_len > len)
336 s->buf_len = len;
7d8406be 337 }
17acfe32
PB
338 break;
339 case 0x1b:
340 DPRINTF("Start Stop Unit\n");
341 break;
342 case 0x1e:
343 DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
344 bdrv_set_locked(s->bdrv, buf[4] & 1);
2e5d83bb
PB
345 break;
346 case 0x25:
347 DPRINTF("Read Capacity\n");
348 /* The normal LEN field for this command is zero. */
349 memset(s->buf, 0, 8);
350 bdrv_get_geometry(s->bdrv, &nb_sectors);
351 s->buf[0] = (nb_sectors >> 24) & 0xff;
352 s->buf[1] = (nb_sectors >> 16) & 0xff;
353 s->buf[2] = (nb_sectors >> 8) & 0xff;
354 s->buf[3] = nb_sectors & 0xff;
355 s->buf[4] = 0;
356 s->buf[5] = 0;
7c22dd52
PB
357 s->buf[6] = s->cluster_size * 2;
358 s->buf[7] = 0;
2e5d83bb
PB
359 s->buf_len = 8;
360 break;
361 case 0x08:
362 case 0x28:
363 DPRINTF("Read (sector %d, count %d)\n", lba, len);
7c22dd52
PB
364 s->sector = lba * s->cluster_size;
365 s->sector_count = len * s->cluster_size;
2e5d83bb
PB
366 break;
367 case 0x0a:
368 case 0x2a:
369 DPRINTF("Write (sector %d, count %d)\n", lba, len);
7c22dd52
PB
370 s->sector = lba * s->cluster_size;
371 s->sector_count = len * s->cluster_size;
2e5d83bb
PB
372 is_write = 1;
373 break;
7d8406be
PB
374 case 0x35:
375 DPRINTF("Syncronise cache (sector %d, count %d)\n", lba, len);
7a6cba61 376 bdrv_flush(s->bdrv);
7d8406be 377 break;
2e5d83bb
PB
378 case 0x43:
379 {
7c22dd52 380 int start_track, format, msf, toclen;
2e5d83bb
PB
381
382 msf = buf[1] & 2;
383 format = buf[2] & 0xf;
384 start_track = buf[6];
385 bdrv_get_geometry(s->bdrv, &nb_sectors);
386 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
387 switch(format) {
388 case 0:
7c22dd52 389 toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
2e5d83bb
PB
390 break;
391 case 1:
392 /* multi session : only a single session defined */
7c22dd52 393 toclen = 12;
2e5d83bb
PB
394 memset(s->buf, 0, 12);
395 s->buf[1] = 0x0a;
396 s->buf[2] = 0x01;
397 s->buf[3] = 0x01;
2e5d83bb
PB
398 break;
399 case 2:
7c22dd52 400 toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
2e5d83bb
PB
401 break;
402 default:
7c22dd52
PB
403 goto error_cmd;
404 }
405 if (toclen > 0) {
406 if (len > toclen)
407 len = toclen;
408 s->buf_len = len;
409 break;
2e5d83bb 410 }
7c22dd52
PB
411 error_cmd:
412 DPRINTF("Read TOC error\n");
413 goto fail;
2e5d83bb 414 }
17acfe32
PB
415 case 0x46:
416 DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
417 memset(s->buf, 0, 8);
418 /* ??? This shoud probably return much more information. For now
419 just return the basic header indicating the CD-ROM profile. */
420 s->buf[7] = 8; // CD-ROM
421 s->buf_len = 8;
422 break;
2e5d83bb
PB
423 case 0x56:
424 DPRINTF("Reserve(10)\n");
425 if (buf[1] & 3)
426 goto fail;
427 break;
428 case 0x57:
429 DPRINTF("Release(10)\n");
430 if (buf[1] & 3)
431 goto fail;
432 break;
433 case 0xa0:
434 DPRINTF("Report LUNs (len %d)\n", len);
435 if (len < 16)
436 goto fail;
437 memset(s->buf, 0, 16);
438 s->buf[3] = 8;
439 s->buf_len = 16;
440 break;
441 default:
442 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
443 fail:
444 scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
445 return 0;
446 }
447 if (s->sector_count == 0 && s->buf_len == 0) {
448 scsi_command_complete(s, SENSE_NO_SENSE);
449 }
7c22dd52 450 len = s->sector_count * 512 + s->buf_len;
2e5d83bb
PB
451 return is_write ? -len : len;
452}
453
454void scsi_disk_destroy(SCSIDevice *s)
455{
456 bdrv_close(s->bdrv);
457 qemu_free(s);
458}
459
460SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
461 scsi_completionfn completion,
462 void *opaque)
463{
464 SCSIDevice *s;
465
466 s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
467 s->bdrv = bdrv;
468 s->completion = completion;
469 s->opaque = opaque;
470 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
7c22dd52 471 s->cluster_size = 4;
2e5d83bb 472 } else {
7c22dd52 473 s->cluster_size = 1;
2e5d83bb
PB
474 }
475
476 return s;
477}
478