symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/scsi-disk.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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  * Note that this file only handles the SCSI architecture model and device
       
    12  * commands.  Emulation of interface/link layer protocols is handled by
       
    13  * the host adapter emulator.
       
    14  */
       
    15 
       
    16 //#define DEBUG_SCSI
       
    17 
       
    18 #ifdef DEBUG_SCSI
       
    19 #define DPRINTF(fmt, args...) \
       
    20 do { printf("scsi-disk: " fmt , ##args); } while (0)
       
    21 #else
       
    22 #define DPRINTF(fmt, args...) do {} while(0)
       
    23 #endif
       
    24 
       
    25 #define BADF(fmt, args...) \
       
    26 do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
       
    27 
       
    28 #include "qemu-common.h"
       
    29 #include "block.h"
       
    30 #include "scsi-disk.h"
       
    31 
       
    32 #define SENSE_NO_SENSE        0
       
    33 #define SENSE_NOT_READY       2
       
    34 #define SENSE_HARDWARE_ERROR  4
       
    35 #define SENSE_ILLEGAL_REQUEST 5
       
    36 
       
    37 #define STATUS_GOOD            0
       
    38 #define STATUS_CHECK_CONDITION 2
       
    39 
       
    40 #define SCSI_DMA_BUF_SIZE    131072
       
    41 #define SCSI_MAX_INQUIRY_LEN 256
       
    42 
       
    43 typedef struct SCSIRequest {
       
    44     SCSIDeviceState *dev;
       
    45     uint32_t tag;
       
    46     /* ??? We should probably keep track of whether the data trasfer is
       
    47        a read or a write.  Currently we rely on the host getting it right.  */
       
    48     /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
       
    49     int sector;
       
    50     int sector_count;
       
    51     /* The amounnt of data in the buffer.  */
       
    52     int buf_len;
       
    53     uint8_t *dma_buf;
       
    54     BlockDriverAIOCB *aiocb;
       
    55     struct SCSIRequest *next;
       
    56 } SCSIRequest;
       
    57 
       
    58 struct SCSIDeviceState
       
    59 {
       
    60     BlockDriverState *bdrv;
       
    61     SCSIRequest *requests;
       
    62     /* The qemu block layer uses a fixed 512 byte sector size.
       
    63        This is the number of 512 byte blocks in a single scsi sector.  */
       
    64     int cluster_size;
       
    65     int sense;
       
    66     int tcq;
       
    67     /* Completion functions may be called from either scsi_{read,write}_data
       
    68        or from the AIO completion routines.  */
       
    69     scsi_completionfn completion;
       
    70     void *opaque;
       
    71 };
       
    72 
       
    73 /* Global pool of SCSIRequest structures.  */
       
    74 static SCSIRequest *free_requests = NULL;
       
    75 
       
    76 static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
       
    77 {
       
    78     SCSIRequest *r;
       
    79 
       
    80     if (free_requests) {
       
    81         r = free_requests;
       
    82         free_requests = r->next;
       
    83     } else {
       
    84         r = qemu_malloc(sizeof(SCSIRequest));
       
    85         r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
       
    86     }
       
    87     r->dev = s;
       
    88     r->tag = tag;
       
    89     r->sector_count = 0;
       
    90     r->buf_len = 0;
       
    91     r->aiocb = NULL;
       
    92 
       
    93     r->next = s->requests;
       
    94     s->requests = r;
       
    95     return r;
       
    96 }
       
    97 
       
    98 static void scsi_remove_request(SCSIRequest *r)
       
    99 {
       
   100     SCSIRequest *last;
       
   101     SCSIDeviceState *s = r->dev;
       
   102 
       
   103     if (s->requests == r) {
       
   104         s->requests = r->next;
       
   105     } else {
       
   106         last = s->requests;
       
   107         while (last && last->next != r)
       
   108             last = last->next;
       
   109         if (last) {
       
   110             last->next = r->next;
       
   111         } else {
       
   112             BADF("Orphaned request\n");
       
   113         }
       
   114     }
       
   115     r->next = free_requests;
       
   116     free_requests = r;
       
   117 }
       
   118 
       
   119 static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
       
   120 {
       
   121     SCSIRequest *r;
       
   122 
       
   123     r = s->requests;
       
   124     while (r && r->tag != tag)
       
   125         r = r->next;
       
   126 
       
   127     return r;
       
   128 }
       
   129 
       
   130 /* Helper function for command completion.  */
       
   131 static void scsi_command_complete(SCSIRequest *r, int status, int sense)
       
   132 {
       
   133     SCSIDeviceState *s = r->dev;
       
   134     uint32_t tag;
       
   135     DPRINTF("Command complete tag=0x%x status=%d sense=%d\n", r->tag, status, sense);
       
   136     s->sense = sense;
       
   137     tag = r->tag;
       
   138     scsi_remove_request(r);
       
   139     s->completion(s->opaque, SCSI_REASON_DONE, tag, status);
       
   140 }
       
   141 
       
   142 /* Cancel a pending data transfer.  */
       
   143 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
       
   144 {
       
   145     SCSIDeviceState *s = d->state;
       
   146     SCSIRequest *r;
       
   147     DPRINTF("Cancel tag=0x%x\n", tag);
       
   148     r = scsi_find_request(s, tag);
       
   149     if (r) {
       
   150         if (r->aiocb)
       
   151             bdrv_aio_cancel(r->aiocb);
       
   152         r->aiocb = NULL;
       
   153         scsi_remove_request(r);
       
   154     }
       
   155 }
       
   156 
       
   157 static void scsi_read_complete(void * opaque, int ret)
       
   158 {
       
   159     SCSIRequest *r = (SCSIRequest *)opaque;
       
   160     SCSIDeviceState *s = r->dev;
       
   161 
       
   162     if (ret) {
       
   163         DPRINTF("IO error\n");
       
   164         s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 0);
       
   165         scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
       
   166         return;
       
   167     }
       
   168     DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
       
   169 
       
   170     s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
       
   171 }
       
   172 
       
   173 /* Read more data from scsi device into buffer.  */
       
   174 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
       
   175 {
       
   176     SCSIDeviceState *s = d->state;
       
   177     SCSIRequest *r;
       
   178     uint32_t n;
       
   179 
       
   180     r = scsi_find_request(s, tag);
       
   181     if (!r) {
       
   182         BADF("Bad read tag 0x%x\n", tag);
       
   183         /* ??? This is the wrong error.  */
       
   184         scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
       
   185         return;
       
   186     }
       
   187     if (r->sector_count == (uint32_t)-1) {
       
   188         DPRINTF("Read buf_len=%d\n", r->buf_len);
       
   189         r->sector_count = 0;
       
   190         s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
       
   191         return;
       
   192     }
       
   193     DPRINTF("Read sector_count=%d\n", r->sector_count);
       
   194     if (r->sector_count == 0) {
       
   195         scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
       
   196         return;
       
   197     }
       
   198 
       
   199     n = r->sector_count;
       
   200     if (n > SCSI_DMA_BUF_SIZE / 512)
       
   201         n = SCSI_DMA_BUF_SIZE / 512;
       
   202 
       
   203     r->buf_len = n * 512;
       
   204     r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
       
   205                              scsi_read_complete, r);
       
   206     if (r->aiocb == NULL)
       
   207         scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
       
   208     r->sector += n;
       
   209     r->sector_count -= n;
       
   210 }
       
   211 
       
   212 static void scsi_write_complete(void * opaque, int ret)
       
   213 {
       
   214     SCSIRequest *r = (SCSIRequest *)opaque;
       
   215     SCSIDeviceState *s = r->dev;
       
   216     uint32_t len;
       
   217 
       
   218     if (ret) {
       
   219         fprintf(stderr, "scsi-disc: IO write error\n");
       
   220         exit(1);
       
   221     }
       
   222 
       
   223     r->aiocb = NULL;
       
   224     if (r->sector_count == 0) {
       
   225         scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
       
   226     } else {
       
   227         len = r->sector_count * 512;
       
   228         if (len > SCSI_DMA_BUF_SIZE) {
       
   229             len = SCSI_DMA_BUF_SIZE;
       
   230         }
       
   231         r->buf_len = len;
       
   232         DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
       
   233         s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
       
   234     }
       
   235 }
       
   236 
       
   237 /* Write data to a scsi device.  Returns nonzero on failure.
       
   238    The transfer may complete asynchronously.  */
       
   239 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
       
   240 {
       
   241     SCSIDeviceState *s = d->state;
       
   242     SCSIRequest *r;
       
   243     uint32_t n;
       
   244 
       
   245     DPRINTF("Write data tag=0x%x\n", tag);
       
   246     r = scsi_find_request(s, tag);
       
   247     if (!r) {
       
   248         BADF("Bad write tag 0x%x\n", tag);
       
   249         scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
       
   250         return 1;
       
   251     }
       
   252     if (r->aiocb)
       
   253         BADF("Data transfer already in progress\n");
       
   254     n = r->buf_len / 512;
       
   255     if (n) {
       
   256         r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
       
   257                                   scsi_write_complete, r);
       
   258         if (r->aiocb == NULL)
       
   259             scsi_command_complete(r, STATUS_CHECK_CONDITION,
       
   260                                   SENSE_HARDWARE_ERROR);
       
   261         r->sector += n;
       
   262         r->sector_count -= n;
       
   263     } else {
       
   264         /* Invoke completion routine to fetch data from host.  */
       
   265         scsi_write_complete(r, 0);
       
   266     }
       
   267 
       
   268     return 0;
       
   269 }
       
   270 
       
   271 /* Return a pointer to the data buffer.  */
       
   272 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
       
   273 {
       
   274     SCSIDeviceState *s = d->state;
       
   275     SCSIRequest *r;
       
   276 
       
   277     r = scsi_find_request(s, tag);
       
   278     if (!r) {
       
   279         BADF("Bad buffer tag 0x%x\n", tag);
       
   280         return NULL;
       
   281     }
       
   282     return r->dma_buf;
       
   283 }
       
   284 
       
   285 /* Execute a scsi command.  Returns the length of the data expected by the
       
   286    command.  This will be Positive for data transfers from the device
       
   287    (eg. disk reads), negative for transfers to the device (eg. disk writes),
       
   288    and zero if the command does not transfer any data.  */
       
   289 
       
   290 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
       
   291                                  uint8_t *buf, int lun)
       
   292 {
       
   293     SCSIDeviceState *s = d->state;
       
   294     uint64_t nb_sectors;
       
   295     uint32_t lba;
       
   296     uint32_t len;
       
   297     int cmdlen;
       
   298     int is_write;
       
   299     uint8_t command;
       
   300     uint8_t *outbuf;
       
   301     SCSIRequest *r;
       
   302 
       
   303     command = buf[0];
       
   304     r = scsi_find_request(s, tag);
       
   305     if (r) {
       
   306         BADF("Tag 0x%x already in use\n", tag);
       
   307         scsi_cancel_io(d, tag);
       
   308     }
       
   309     /* ??? Tags are not unique for different luns.  We only implement a
       
   310        single lun, so this should not matter.  */
       
   311     r = scsi_new_request(s, tag);
       
   312     outbuf = r->dma_buf;
       
   313     is_write = 0;
       
   314     DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
       
   315     switch (command >> 5) {
       
   316     case 0:
       
   317         lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
       
   318         len = buf[4];
       
   319         cmdlen = 6;
       
   320         break;
       
   321     case 1:
       
   322     case 2:
       
   323         lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
       
   324         len = buf[8] | (buf[7] << 8);
       
   325         cmdlen = 10;
       
   326         break;
       
   327     case 4:
       
   328         lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
       
   329         len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
       
   330         cmdlen = 16;
       
   331         break;
       
   332     case 5:
       
   333         lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
       
   334         len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
       
   335         cmdlen = 12;
       
   336         break;
       
   337     default:
       
   338         BADF("Unsupported command length, command %x\n", command);
       
   339         goto fail;
       
   340     }
       
   341 #ifdef DEBUG_SCSI
       
   342     {
       
   343         int i;
       
   344         for (i = 1; i < cmdlen; i++) {
       
   345             printf(" 0x%02x", buf[i]);
       
   346         }
       
   347         printf("\n");
       
   348     }
       
   349 #endif
       
   350     if (lun || buf[1] >> 5) {
       
   351         /* Only LUN 0 supported.  */
       
   352         DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
       
   353         if (command != 0x03 && command != 0x12) /* REQUEST SENSE and INQUIRY */
       
   354             goto fail;
       
   355     }
       
   356     switch (command) {
       
   357     case 0x0:
       
   358 	DPRINTF("Test Unit Ready\n");
       
   359 	break;
       
   360     case 0x03:
       
   361         DPRINTF("Request Sense (len %d)\n", len);
       
   362         if (len < 4)
       
   363             goto fail;
       
   364         memset(outbuf, 0, 4);
       
   365         outbuf[0] = 0xf0;
       
   366         outbuf[1] = 0;
       
   367         outbuf[2] = s->sense;
       
   368         r->buf_len = 4;
       
   369         break;
       
   370     case 0x12:
       
   371         DPRINTF("Inquiry (len %d)\n", len);
       
   372         if (buf[1] & 0x2) {
       
   373             /* Command support data - optional, not implemented */
       
   374             BADF("optional INQUIRY command support request not implemented\n");
       
   375             goto fail;
       
   376         }
       
   377         else if (buf[1] & 0x1) {
       
   378             /* Vital product data */
       
   379             uint8_t page_code = buf[2];
       
   380             if (len < 4) {
       
   381                 BADF("Error: Inquiry (EVPD[%02X]) buffer size %d is "
       
   382                      "less than 4\n", page_code, len);
       
   383                 goto fail;
       
   384             }
       
   385 
       
   386             switch (page_code) {
       
   387                 case 0x00:
       
   388                     {
       
   389                         /* Supported page codes, mandatory */
       
   390                         DPRINTF("Inquiry EVPD[Supported pages] "
       
   391                                 "buffer size %d\n", len);
       
   392 
       
   393                         r->buf_len = 0;
       
   394 
       
   395                         if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
       
   396                             outbuf[r->buf_len++] = 5;
       
   397                         } else {
       
   398                             outbuf[r->buf_len++] = 0;
       
   399                         }
       
   400 
       
   401                         outbuf[r->buf_len++] = 0x00; // this page
       
   402                         outbuf[r->buf_len++] = 0x00;
       
   403                         outbuf[r->buf_len++] = 3;    // number of pages
       
   404                         outbuf[r->buf_len++] = 0x00; // list of supported pages (this page)
       
   405                         outbuf[r->buf_len++] = 0x80; // unit serial number
       
   406                         outbuf[r->buf_len++] = 0x83; // device identification
       
   407                     }
       
   408                     break;
       
   409                 case 0x80:
       
   410                     {
       
   411                         /* Device serial number, optional */
       
   412                         if (len < 4) {
       
   413                             BADF("Error: EVPD[Serial number] Inquiry buffer "
       
   414                                  "size %d too small, %d needed\n", len, 4);
       
   415                             goto fail;
       
   416                         }
       
   417 
       
   418                         DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len);
       
   419 
       
   420                         r->buf_len = 0;
       
   421 
       
   422                         /* Supported page codes */
       
   423                         if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
       
   424                             outbuf[r->buf_len++] = 5;
       
   425                         } else {
       
   426                             outbuf[r->buf_len++] = 0;
       
   427                         }
       
   428 
       
   429                         outbuf[r->buf_len++] = 0x80; // this page
       
   430                         outbuf[r->buf_len++] = 0x00;
       
   431                         outbuf[r->buf_len++] = 0x01; // 1 byte data follow
       
   432 
       
   433                         outbuf[r->buf_len++] = '0';  // 1 byte data follow 
       
   434                     }
       
   435 
       
   436                     break;
       
   437                 case 0x83:
       
   438                     {
       
   439                         /* Device identification page, mandatory */
       
   440                         int max_len = 255 - 8;
       
   441                         int id_len = strlen(bdrv_get_device_name(s->bdrv));
       
   442                         if (id_len > max_len)
       
   443                             id_len = max_len;
       
   444 
       
   445                         DPRINTF("Inquiry EVPD[Device identification] "
       
   446                                 "buffer size %d\n", len);
       
   447                         r->buf_len = 0;
       
   448                         if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
       
   449                             outbuf[r->buf_len++] = 5;
       
   450                         } else {
       
   451                             outbuf[r->buf_len++] = 0;
       
   452                         }
       
   453 
       
   454                         outbuf[r->buf_len++] = 0x83; // this page
       
   455                         outbuf[r->buf_len++] = 0x00;
       
   456                         outbuf[r->buf_len++] = 3 + id_len;
       
   457 
       
   458                         outbuf[r->buf_len++] = 0x2; // ASCII
       
   459                         outbuf[r->buf_len++] = 0;   // not officially assigned
       
   460                         outbuf[r->buf_len++] = 0;   // reserved
       
   461                         outbuf[r->buf_len++] = id_len; // length of data following
       
   462 
       
   463                         memcpy(&outbuf[r->buf_len],
       
   464                                bdrv_get_device_name(s->bdrv), id_len);
       
   465                         r->buf_len += id_len;
       
   466                     }
       
   467                     break;
       
   468                 default:
       
   469                     BADF("Error: unsupported Inquiry (EVPD[%02X]) "
       
   470                          "buffer size %d\n", page_code, len);
       
   471                     goto fail;
       
   472             }
       
   473             /* done with EVPD */
       
   474             break;
       
   475         }
       
   476         else {
       
   477             /* Standard INQUIRY data */
       
   478             if (buf[2] != 0) {
       
   479                 BADF("Error: Inquiry (STANDARD) page or code "
       
   480                      "is non-zero [%02X]\n", buf[2]);
       
   481                 goto fail;
       
   482             }
       
   483 
       
   484             /* PAGE CODE == 0 */
       
   485             if (len < 5) {
       
   486                 BADF("Error: Inquiry (STANDARD) buffer size %d "
       
   487                      "is less than 5\n", len);
       
   488                 goto fail;
       
   489             }
       
   490 
       
   491             if (len < 36) {
       
   492                 BADF("Error: Inquiry (STANDARD) buffer size %d "
       
   493                      "is less than 36 (TODO: only 5 required)\n", len);
       
   494             }
       
   495         }
       
   496 
       
   497         if(len > SCSI_MAX_INQUIRY_LEN)
       
   498             len = SCSI_MAX_INQUIRY_LEN;
       
   499 
       
   500         memset(outbuf, 0, len);
       
   501 
       
   502         if (lun || buf[1] >> 5) {
       
   503             outbuf[0] = 0x7f;	/* LUN not supported */
       
   504 	} else if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
       
   505 	    outbuf[0] = 5;
       
   506             outbuf[1] = 0x80;
       
   507 	    memcpy(&outbuf[16], "QEMU CD-ROM    ", 16);
       
   508 	} else {
       
   509 	    outbuf[0] = 0;
       
   510 	    memcpy(&outbuf[16], "QEMU HARDDISK  ", 16);
       
   511 	}
       
   512 	memcpy(&outbuf[8], "QEMU   ", 8);
       
   513         memcpy(&outbuf[32], QEMU_VERSION, 4);
       
   514         /* Identify device as SCSI-3 rev 1.
       
   515            Some later commands are also implemented. */
       
   516 	outbuf[2] = 3;
       
   517 	outbuf[3] = 2; /* Format 2 */
       
   518 	outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */
       
   519         /* Sync data transfer and TCQ.  */
       
   520         outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
       
   521 	r->buf_len = len;
       
   522 	break;
       
   523     case 0x16:
       
   524         DPRINTF("Reserve(6)\n");
       
   525         if (buf[1] & 1)
       
   526             goto fail;
       
   527         break;
       
   528     case 0x17:
       
   529         DPRINTF("Release(6)\n");
       
   530         if (buf[1] & 1)
       
   531             goto fail;
       
   532         break;
       
   533     case 0x1a:
       
   534     case 0x5a:
       
   535         {
       
   536             uint8_t *p;
       
   537             int page;
       
   538 
       
   539             page = buf[2] & 0x3f;
       
   540             DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
       
   541             p = outbuf;
       
   542             memset(p, 0, 4);
       
   543             outbuf[1] = 0; /* Default media type.  */
       
   544             outbuf[3] = 0; /* Block descriptor length.  */
       
   545             if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
       
   546                 outbuf[2] = 0x80; /* Readonly.  */
       
   547             }
       
   548             p += 4;
       
   549             if (page == 4) {
       
   550                 int cylinders, heads, secs;
       
   551 
       
   552                 /* Rigid disk device geometry page. */
       
   553                 p[0] = 4;
       
   554                 p[1] = 0x16;
       
   555                 /* if a geometry hint is available, use it */
       
   556                 bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs);
       
   557                 p[2] = (cylinders >> 16) & 0xff;
       
   558                 p[3] = (cylinders >> 8) & 0xff;
       
   559                 p[4] = cylinders & 0xff;
       
   560                 p[5] = heads & 0xff;
       
   561                 /* Write precomp start cylinder, disabled */
       
   562                 p[6] = (cylinders >> 16) & 0xff;
       
   563                 p[7] = (cylinders >> 8) & 0xff;
       
   564                 p[8] = cylinders & 0xff;
       
   565                 /* Reduced current start cylinder, disabled */
       
   566                 p[9] = (cylinders >> 16) & 0xff;
       
   567                 p[10] = (cylinders >> 8) & 0xff;
       
   568                 p[11] = cylinders & 0xff;
       
   569                 /* Device step rate [ns], 200ns */
       
   570                 p[12] = 0;
       
   571                 p[13] = 200;
       
   572                 /* Landing zone cylinder */
       
   573                 p[14] = 0xff;
       
   574                 p[15] =  0xff;
       
   575                 p[16] = 0xff;
       
   576                 /* Medium rotation rate [rpm], 5400 rpm */
       
   577                 p[20] = (5400 >> 8) & 0xff;
       
   578                 p[21] = 5400 & 0xff;
       
   579                 p += 0x16;
       
   580             } else if (page == 5) {
       
   581                 int cylinders, heads, secs;
       
   582 
       
   583                 /* Flexible disk device geometry page. */
       
   584                 p[0] = 5;
       
   585                 p[1] = 0x1e;
       
   586                 /* Transfer rate [kbit/s], 5Mbit/s */
       
   587                 p[2] = 5000 >> 8;
       
   588                 p[3] = 5000 & 0xff;
       
   589                 /* if a geometry hint is available, use it */
       
   590                 bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs);
       
   591                 p[4] = heads & 0xff;
       
   592                 p[5] = secs & 0xff;
       
   593                 p[6] = s->cluster_size * 2;
       
   594                 p[8] = (cylinders >> 8) & 0xff;
       
   595                 p[9] = cylinders & 0xff;
       
   596                 /* Write precomp start cylinder, disabled */
       
   597                 p[10] = (cylinders >> 8) & 0xff;
       
   598                 p[11] = cylinders & 0xff;
       
   599                 /* Reduced current start cylinder, disabled */
       
   600                 p[12] = (cylinders >> 8) & 0xff;
       
   601                 p[13] = cylinders & 0xff;
       
   602                 /* Device step rate [100us], 100us */
       
   603                 p[14] = 0;
       
   604                 p[15] = 1;
       
   605                 /* Device step pulse width [us], 1us */
       
   606                 p[16] = 1;
       
   607                 /* Device head settle delay [100us], 100us */
       
   608                 p[17] = 0;
       
   609                 p[18] = 1;
       
   610                 /* Motor on delay [0.1s], 0.1s */
       
   611                 p[19] = 1;
       
   612                 /* Motor off delay [0.1s], 0.1s */
       
   613                 p[20] = 1;
       
   614                 /* Medium rotation rate [rpm], 5400 rpm */
       
   615                 p[28] = (5400 >> 8) & 0xff;
       
   616                 p[29] = 5400 & 0xff;
       
   617                 p += 0x1e;
       
   618             } else if ((page == 8 || page == 0x3f)) {
       
   619                 /* Caching page.  */
       
   620                 memset(p,0,20);
       
   621                 p[0] = 8;
       
   622                 p[1] = 0x12;
       
   623                 p[2] = 4; /* WCE */
       
   624                 p += 20;
       
   625             }
       
   626             if ((page == 0x3f || page == 0x2a)
       
   627                     && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
       
   628                 /* CD Capabilities and Mechanical Status page. */
       
   629                 p[0] = 0x2a;
       
   630                 p[1] = 0x14;
       
   631                 p[2] = 3; // CD-R & CD-RW read
       
   632                 p[3] = 0; // Writing not supported
       
   633                 p[4] = 0x7f; /* Audio, composite, digital out,
       
   634                                          mode 2 form 1&2, multi session */
       
   635                 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
       
   636                                          RW corrected, C2 errors, ISRC,
       
   637                                          UPC, Bar code */
       
   638                 p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
       
   639                 /* Locking supported, jumper present, eject, tray */
       
   640                 p[7] = 0; /* no volume & mute control, no
       
   641                                       changer */
       
   642                 p[8] = (50 * 176) >> 8; // 50x read speed
       
   643                 p[9] = (50 * 176) & 0xff;
       
   644                 p[10] = 0 >> 8; // No volume
       
   645                 p[11] = 0 & 0xff;
       
   646                 p[12] = 2048 >> 8; // 2M buffer
       
   647                 p[13] = 2048 & 0xff;
       
   648                 p[14] = (16 * 176) >> 8; // 16x read speed current
       
   649                 p[15] = (16 * 176) & 0xff;
       
   650                 p[18] = (16 * 176) >> 8; // 16x write speed
       
   651                 p[19] = (16 * 176) & 0xff;
       
   652                 p[20] = (16 * 176) >> 8; // 16x write speed current
       
   653                 p[21] = (16 * 176) & 0xff;
       
   654                 p += 22;
       
   655             }
       
   656             r->buf_len = p - outbuf;
       
   657             outbuf[0] = r->buf_len - 4;
       
   658             if (r->buf_len > len)
       
   659                 r->buf_len = len;
       
   660         }
       
   661         break;
       
   662     case 0x1b:
       
   663         DPRINTF("Start Stop Unit\n");
       
   664 	break;
       
   665     case 0x1e:
       
   666         DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
       
   667         bdrv_set_locked(s->bdrv, buf[4] & 1);
       
   668 	break;
       
   669     case 0x25:
       
   670 	DPRINTF("Read Capacity\n");
       
   671         /* The normal LEN field for this command is zero.  */
       
   672 	memset(outbuf, 0, 8);
       
   673 	bdrv_get_geometry(s->bdrv, &nb_sectors);
       
   674         /* Returned value is the address of the last sector.  */
       
   675         if (nb_sectors) {
       
   676             nb_sectors--;
       
   677             outbuf[0] = (nb_sectors >> 24) & 0xff;
       
   678             outbuf[1] = (nb_sectors >> 16) & 0xff;
       
   679             outbuf[2] = (nb_sectors >> 8) & 0xff;
       
   680             outbuf[3] = nb_sectors & 0xff;
       
   681             outbuf[4] = 0;
       
   682             outbuf[5] = 0;
       
   683             outbuf[6] = s->cluster_size * 2;
       
   684             outbuf[7] = 0;
       
   685             r->buf_len = 8;
       
   686         } else {
       
   687             scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
       
   688             return 0;
       
   689         }
       
   690 	break;
       
   691     case 0x08:
       
   692     case 0x28:
       
   693         DPRINTF("Read (sector %d, count %d)\n", lba, len);
       
   694         r->sector = lba * s->cluster_size;
       
   695         r->sector_count = len * s->cluster_size;
       
   696         break;
       
   697     case 0x0a:
       
   698     case 0x2a:
       
   699         DPRINTF("Write (sector %d, count %d)\n", lba, len);
       
   700         r->sector = lba * s->cluster_size;
       
   701         r->sector_count = len * s->cluster_size;
       
   702         is_write = 1;
       
   703         break;
       
   704     case 0x35:
       
   705         DPRINTF("Synchronise cache (sector %d, count %d)\n", lba, len);
       
   706         bdrv_flush(s->bdrv);
       
   707         break;
       
   708     case 0x43:
       
   709         {
       
   710             int start_track, format, msf, toclen;
       
   711 
       
   712             msf = buf[1] & 2;
       
   713             format = buf[2] & 0xf;
       
   714             start_track = buf[6];
       
   715             bdrv_get_geometry(s->bdrv, &nb_sectors);
       
   716             DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
       
   717             switch(format) {
       
   718             case 0:
       
   719                 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
       
   720                 break;
       
   721             case 1:
       
   722                 /* multi session : only a single session defined */
       
   723                 toclen = 12;
       
   724                 memset(outbuf, 0, 12);
       
   725                 outbuf[1] = 0x0a;
       
   726                 outbuf[2] = 0x01;
       
   727                 outbuf[3] = 0x01;
       
   728                 break;
       
   729             case 2:
       
   730                 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
       
   731                 break;
       
   732             default:
       
   733                 goto error_cmd;
       
   734             }
       
   735             if (toclen > 0) {
       
   736                 if (len > toclen)
       
   737                   len = toclen;
       
   738                 r->buf_len = len;
       
   739                 break;
       
   740             }
       
   741         error_cmd:
       
   742             DPRINTF("Read TOC error\n");
       
   743             goto fail;
       
   744         }
       
   745     case 0x46:
       
   746         DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
       
   747         memset(outbuf, 0, 8);
       
   748         /* ??? This should probably return much more information.  For now
       
   749            just return the basic header indicating the CD-ROM profile.  */
       
   750         outbuf[7] = 8; // CD-ROM
       
   751         r->buf_len = 8;
       
   752         break;
       
   753     case 0x56:
       
   754         DPRINTF("Reserve(10)\n");
       
   755         if (buf[1] & 3)
       
   756             goto fail;
       
   757         break;
       
   758     case 0x57:
       
   759         DPRINTF("Release(10)\n");
       
   760         if (buf[1] & 3)
       
   761             goto fail;
       
   762         break;
       
   763     case 0xa0:
       
   764         DPRINTF("Report LUNs (len %d)\n", len);
       
   765         if (len < 16)
       
   766             goto fail;
       
   767         memset(outbuf, 0, 16);
       
   768         outbuf[3] = 8;
       
   769         r->buf_len = 16;
       
   770         break;
       
   771     case 0x2f:
       
   772         DPRINTF("Verify (sector %d, count %d)\n", lba, len);
       
   773         break;
       
   774     default:
       
   775 	DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
       
   776     fail:
       
   777         scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_ILLEGAL_REQUEST);
       
   778 	return 0;
       
   779     }
       
   780     if (r->sector_count == 0 && r->buf_len == 0) {
       
   781         scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
       
   782     }
       
   783     len = r->sector_count * 512 + r->buf_len;
       
   784     if (is_write) {
       
   785         return -len;
       
   786     } else {
       
   787         if (!r->sector_count)
       
   788             r->sector_count = -1;
       
   789         return len;
       
   790     }
       
   791 }
       
   792 
       
   793 static void scsi_destroy(SCSIDevice *d)
       
   794 {
       
   795     qemu_free(d->state);
       
   796     qemu_free(d);
       
   797 }
       
   798 
       
   799 SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
       
   800                            scsi_completionfn completion, void *opaque)
       
   801 {
       
   802     SCSIDevice *d;
       
   803     SCSIDeviceState *s;
       
   804 
       
   805     s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
       
   806     s->bdrv = bdrv;
       
   807     s->tcq = tcq;
       
   808     s->completion = completion;
       
   809     s->opaque = opaque;
       
   810     if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
       
   811         s->cluster_size = 4;
       
   812     } else {
       
   813         s->cluster_size = 1;
       
   814     }
       
   815 
       
   816     d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
       
   817     d->state = s;
       
   818     d->destroy = scsi_destroy;
       
   819     d->send_command = scsi_send_command;
       
   820     d->read_data = scsi_read_data;
       
   821     d->write_data = scsi_write_data;
       
   822     d->cancel_io = scsi_cancel_io;
       
   823     d->get_buf = scsi_get_buf;
       
   824 
       
   825     return d;
       
   826 }