From: Andrew McNeil Date: Wed, 9 Sep 2009 13:32:00 +0000 (+0100) Subject: Tidy up of atapi pass through code. X-Git-Url: http://xenbits.xen.org/gitweb?a=commitdiff_plain;h=d8d74afae1b3edb93b862eb5119ef5f9a03312f2;p=xenclient%2Fioemu-pq.git Tidy up of atapi pass through code. Overhaul of atapi command specific data size handling code, fixes various minor bugs with uncommon atapi commands. Removes "most greusome line of code" touch call. --- diff --git a/master/atapi-pt-write b/master/atapi-pt-write index 31612ee..1ea1996 100644 --- a/master/atapi-pt-write +++ b/master/atapi-pt-write @@ -1,8 +1,199 @@ diff --git a/hw/atapi-pt.c b/hw/atapi-pt.c -index 413cc47..66da45a 100644 +index 413cc47..a097f78 100644 --- a/hw/atapi-pt.c +++ b/hw/atapi-pt.c -@@ -497,124 +497,106 @@ static void ide_atapi_pt_error(IDEState *s) +@@ -1,4 +1,6 @@ ++#include + #include ++#include + + #define DEBUG_IDE_ATAPI_PT + +@@ -480,6 +482,183 @@ static const char *atapi_sense_to_str(int key, int asc, int ascq) + } + + ++/* For each SCSI command we need to know up to 3 data sizes. These are: ++ * 1. The amount of data to send to the LU. ++ * 2. The size of the buffer provided for data sent back from the LU. ++ * 3. The amount of data the LU wanted to send. ++ * ++ * These are all measured in bytes. ++ * ++ * The table ide_atapi_cmd_data_sizes specifies how to determine these sizes for ++ * each SCSI command. Each size is given by: ++ * ++ * constant + (base * block_size) ++ * ++ * where base is a value specified within the command data. This is specified in ++ * our table as an offset into the data at which the value starts and the size of ++ * the value, in bytes. All base value are assumed to be MSB first (lowest offset). ++ * ++ * The number of bytes forming the base value can only take values between 0 and 4 ++ * inclusive, with 0 indicating that there is no base value. ++ * ++ * The amount of data to send to the LU and the size of the receiving buffer are ++ * both determined from the CDB. A value of 0 means that no data is transfered and ++ * a value of -1 indicates that the table entry is invalid (eg undefined command). ++ * ++ * The amount of data the LU wanted to return is determined from the returned data. ++ * A value of 0 is invalid and a value of -1 indicates that this size is the same ++ * as the receiving buffer size. ++ * ++ * A few commands are too complex for this scheme and so are handled by code in ++ * ide_atapi_pt_cmd() and ide_atapi_pt_do_sg_io(). ++ */ ++static struct ++{ ++ int dout_len_const; // size of data to send to LU, dout ++ int dout_len_offset; ++ int dout_len_size; ++ int dout_block_size; ++ ++ int alloc_len_const; // size of buffer to receive din ++ int alloc_len_offset; ++ int alloc_len_size; ++ int alloc_block_size; ++ ++ int din_len_const; // size of data LU wanted to send, din ++ int din_len_offset; ++ int din_len_size; ++ int din_block_size; ++} atapi_data_sizes[256] = { ++ // dout buffer din ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x00 GPCMD_TEST_UNIT_READY ++ {-1},{-1}, // 0x01-0x02 ++ {-1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0}, // 0x03 GPCMD_REQUEST_SENSE ++ {12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x04 GPCMD_FORMAT_UNIT ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x05-0x0c ++ {-1},{-1},{-1},{-1},{-1}, // 0x0d-0x11 ++ { 0, 0, 0, 0, 0, 4, 1, 1, 5, 4, 1, 1}, // 0x12 GPCMD_INQUIRY ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x13-0x1a ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x1b GPCMD_START_STOP_UNIT ++ {-1},{-1}, // 0x1c-0x1d ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x1e GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL ++ {-1},{-1},{-1},{-1}, // 0x1f-0x20 ++ { 0, 0, 0, 0, 0, 7, 2, 1, 4, 3, 1, 1}, // 0x23 GPCMD_READ_FORMAT_CAPACITIES ++ {-1}, // 0x24 ++ { 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0}, // 0x25 GPCMD_READ_CDVD_CAPACITY ++ {-1},{-1}, // 0x26-0x27 ++ { 0, 0, 0, 0, 0, 7, 2, CD_FRAMESIZE, ++ -1, 0, 0, 0}, // 0x28 GPCMD_READ_10 ++ {-1}, // 0x29 ++ { 0, 7, 2, CD_FRAMESIZE, ++ 0, 0, 0, 0 , 0, 0, 0, 0}, // 0x2a GPCMD_WRITE_10 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x2b GPCMD_SEEK ++ {-1},{-1}, // 0x2c-0x2d ++ { 0, 7, 2, CD_FRAMESIZE, ++ 0, 0, 0, 0, 0, 0, 0, 0}, // 0x2e GPCMD_WRITE_AND_VERIFY_10 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x2f GPCMD_VERIFY_10 ++ {-1},{-1},{-1},{-1},{-1}, // 0x30-0x34 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x35 GPCMD_FLUSH_CACHE ++ {-1},{-1},{-1},{-1},{-1}, // 0x36-0x3a ++ { 0, 6, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x3b GPCMD_WRITE_BUFFER ++ { 0, 0, 0, 0, 0, 6, 3, 1, 4, 1, 3, 1}, // 0x3c GPCMD_READ_BUFFER ++ {-1},{-1},{-1},{-1},{-1}, // 0x3d-0x41 ++ { 0, 0, 0, 0, 0, 7, 2, 1, 4, 2, 2, 1}, // 0x42 GPCMD_READ_SUBCHANNEL ++ { 0, 0, 0, 0, 0, 7, 2, 1, 2, 0, 2, 1}, // 0x43 GPCMD_READ_TOC_PMA_ATIP ++ { 0, 0, 0, 0, 0, 7, 2, 1, 8, 0, 0, 0}, // 0x44 GPCMD_READ_HEADER ++ { 0, 0, 0, 0, 0, 7, 2, CD_FRAMESIZE, ++ -1, 0, 0, 0}, // 0x45 GPCMD_PLAY_AUDIO_10 ++ { 0, 0, 0, 0, 0, 7, 2, 1, 4, 0, 4, 1}, // 0x46 GPCMD_GET_CONFIGURATION ++ { 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0}, // 0x47 GPCMD_PLAY_AUDIO_MSF ++ {-1},{-1}, // 0x48-0x49 ++ { 0, 0, 0, 0, 0, 7, 2, 1, 2, 0, 2, 1}, // 0x4a GPCMD_GET_EVENT_STATUS_NOTIFICATION ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x4b GPCMD_PAUSE_RESUME ++ {-1},{-1}, // 0x4c-0x4d ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x4e GPCMD_STOP_PLAY_SCAN ++ {-1},{-1}, // 0x4f-0x50 ++ { 0, 0, 0, 0, 0, 7, 2, 1, 2, 0, 2, 1}, // 0x51 GPCMD_READ_DISC_INFO ++ { 0, 0, 0, 0, 0, 7, 2, 1, 2, 0, 2, 1}, // 0x52 GPCMD_READ_TRACK_RZONE_INFO ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x53 GPCMD_RESERVE_RZONE_TRACK ++ { 0, 7, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x54 GPCMD_SEND_OPC ++ { 0, 7, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x55 GPCMD_MODE_SELECT_10 ++ {-1},{-1}, // 0x56-0x57 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x58 GPCMD_REPAIR_RZONE_TRACK ++ {-1}, // 0x59 ++ { 0, 0, 0, 0, 0, 7, 2, 1, 2, 0, 2, 1}, // 0x5a GPCMD_MODE_SENSE_10 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x5b GPCMD_CLOSE_TRACK ++ { 0, 0, 0, 0, 0, 7, 2, 1, 2, 0, 2, 1}, // 0x5c GPCMD_READ_BUFFER_CAPACITY ++ { 0, 6, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0x5d GPCMD_SEND_CUE_SHEET ++ {-1},{-1}, // 0x5e-0x5f ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x60-0x67 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x68-0x6f ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x70-0x77 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x78-0x7f ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x80-0x87 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x88-0x8f ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x90-0x97 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0x98-0x9f ++ {-1}, // 0xa0 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xa1 GPCMD_BLANK ++ { 0, 8, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xa2 GPCMD_SEND_EVENT ++ { 0, 8, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xa3 GPCMD_SEND_KEY ++ { 0, 0, 0, 0, 0, 8, 2, 1, 2, 0, 2, 1}, // 0xa4 GPCMD_REPORT_KEY ++ {-1}, // 0xa5 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xa6 GPCMD_LOAD_UNLOAD ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xa7 GPCMD_SET_READ_AHEAD ++ { 0, 0, 0, 0, 0, 6, 4, CD_FRAMESIZE, ++ -1, 0, 0, 0}, // 0xa8 GPCMD_READ_12 ++ {-1}, // 0xa9 ++ { 0, 6, 4, CD_FRAMESIZE, ++ 0, 0, 0, 0, 0, 0, 0, 0}, // 0xaa GPCMD_WRITE_12 ++ {-1}, // 0xab ++ { 0, 0, 0, 0, 0, 8, 2, 1, 4, 0, 4, 1}, // 0xac GPCMD_GET_PERFORMANCE ++ { 0, 0, 0, 0, 0, 8, 2, 1, 2, 0, 2, 1}, // 0xad GPCMD_READ_DVD_STRUCTURE ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xae-0xb5 ++ { 0, 9, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xb6 GPCMD_SET_STREAMING ++ {-1},{-1}, // 0xb7-0xb8 ++ { 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0}, // 0xb9 GPCMD_READ_CD_MSF ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xba GPCMD_SCAN ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xbb GPCMD_SET_SPEED - Not in docs ++ {-1}, // 0xbc ++ { 0, 0, 0, 0, 0, 8, 2, 1, 8, 6, 2, 1}, // 0xbd GPCMD_MECHANISM_STATUS ++ { 0, 0, 0, 0, 0, 6, 3, 1, -1, 0, 0, 0}, // 0xbe GPCMD_READ_CD ++ { 0, 8, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 0xbf GPCMD_SEND_DVD_STRUCTURE ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xc0-0xc7 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xc8-0xcf ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xd0-0xd7 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xd8-0xdf ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xe0-0xe7 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xe8-0xef ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1}, // 0xf0-0xf7 ++ {-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1} // 0xf8-0xff ++}; ++ ++// TODO: check these commands: ++//# define GPCMD_PLAY_CD 0xbc ++//# define GPCMD_PLAYAUDIO_TI 0x48 ++//# define GPCMD_GET_MEDIA_STATUS 0xda ++ ++ ++static uint32_t ide_atapi_pt_read_field_at_offset(uint8_t *data, int offset, int field_size) ++{ ++ switch(field_size) ++ { ++ case 0: ++ return 0; ++ case 1: ++ return data[offset]; ++ case 2: ++ return ube16_to_cpu(data + offset); ++ case 3: ++ return ube24_to_cpu(data + offset); ++ case 4: ++ return ube32_to_cpu(data + offset); ++ default: ++ assert(0); ++ return -1; ++ } ++} ++ ++ + static void ide_atapi_pt_set_error(IDEState *s, int sense_key, int asc, int error) + { + s->atapi_pt.sense.sense_key = sense_key; +@@ -497,124 +676,173 @@ static void ide_atapi_pt_error(IDEState *s) ide_set_irq(s); } @@ -19,29 +210,27 @@ index 413cc47..66da45a 100644 - int read_bytes; - int i; + int r; ++ uint8_t cmd_code = s->atapi_pt.request[0]; ++ uint32_t din_desired; - ++finish_count; - DEBUG_PRINTF("**** finish (%p, u=%p, raw=%p, fd=%d, %d-%d(%d))\n", - s, s->atapi_pt.cmd.usr_ptr, - raw_state, raw_state->fd, cmd_count, - finish_count + no_finish_count, no_finish_count); -+ s->atapi_pt.sense.error_code = 0; -+ s->atapi_pt.sense.sense_key = 0; -+ s->atapi_pt.sense.asc = 0; -+ s->atapi_pt.sense.ascq = 0; ++ assert(cmd->din_xfer_len != (__u32)-1); - DEBUG_PRINTF("Preread: 0x"); - for(i = 0; i < sizeof(s->atapi_pt.cmd); ++i) - DEBUG_PRINTF("%02x", ((unsigned char *)&s->atapi_pt.cmd)[i]); - DEBUG_PRINTF("\n"); -+ /* Send command and wait for reply, SG_IO ioctl*/ -+ r = ioctl(raw_state->fd, 0x2285, cmd); ++ s->atapi_pt.sense.error_code = 0; ++ s->atapi_pt.sense.sense_key = 0; ++ s->atapi_pt.sense.asc = 0; ++ s->atapi_pt.sense.ascq = 0; -#if 1 - read_bytes = read(raw_state->fd, &s->atapi_pt.cmd, sizeof (s->atapi_pt.cmd)); -+ if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION) -+ { -+ struct stat file_stat; - DEBUG_PRINTF("Postread: 0x"); - for(i = 0; i < sizeof(s->atapi_pt.cmd); ++i) @@ -56,29 +245,51 @@ index 413cc47..66da45a 100644 - DEBUG_PRINTF("\n"); - read_bytes = i; -#endif +- +- // DEBUG_PRINTF("finish read\n"); ++ /* Send command and wait for reply, SG_IO ioctl*/ ++ r = ioctl(raw_state->fd, 0x2285, cmd); + +- if (read_bytes != sizeof (s->atapi_pt.cmd)) ++ if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION) + { +- ide_atapi_pt_error(s); +- s->atapi_pt.cmd_sent = NULL; +- return; ++ struct stat file_stat; ++ int fd; ++ + if(s->io_buffer[2] == 4 && s->io_buffer[4] == 2) + { + /* This is a "new media" message, tell any other VMs */ + DEBUG_PRINTF("[ATAPI] new media detected\n"); -+ system("touch " IDE_ATAPI_PT_NEW_CD_FILE); - -- // DEBUG_PRINTF("finish read\n"); ++ ++ fd = open(IDE_ATAPI_PT_NEW_CD_FILE, O_WRONLY | O_TRUNC | O_CREAT, 0666); ++ if(fd < 0) { ++ DEBUG_PRINTF("Error touching new CD file\n"); ++ } else { ++ close(fd); ++ utime(IDE_ATAPI_PT_NEW_CD_FILE, NULL); ++ } ++ + if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &file_stat) != 0) + DEBUG_PRINTF("Error writing to new CD file\n"); + else + s->atapi_pt.new_cd_time = file_stat.st_ctime; + } - -- if (read_bytes != sizeof (s->atapi_pt.cmd)) -- { -- ide_atapi_pt_error(s); -- s->atapi_pt.cmd_sent = NULL; -- return; ++ + if(s->io_buffer[2] == 4 && s->io_buffer[4] == 3) + { + /* This is a "media removed" message, tell any other VMs */ + DEBUG_PRINTF("[ATAPI] media removed\n"); -+ system("touch " IDE_ATAPI_PT_EJECT_CD_FILE); ++ ++ fd = open(IDE_ATAPI_PT_NEW_CD_FILE, O_WRONLY | O_TRUNC | O_CREAT, 0666); ++ if(fd < 0) { ++ DEBUG_PRINTF("Error touching new CD file\n"); ++ } else { ++ close(fd); ++ utime(IDE_ATAPI_PT_NEW_CD_FILE, NULL); ++ } + + if(stat(IDE_ATAPI_PT_EJECT_CD_FILE, &file_stat) != 0) + DEBUG_PRINTF("Error writing to eject CD file\n"); @@ -150,14 +361,18 @@ index 413cc47..66da45a 100644 + s->atapi_pt.sense.ascq)); ide_atapi_pt_error(s); - s->atapi_pt.cmd_sent = NULL; -- return; -- } + return; + } - if(s->atapi_pt.cmd_sent == NULL) { - static int null_count = 0; - ++null_count; - DEBUG_PRINTF("\e[1;31m%s called with cmd_sent = NULL %d time%c\e[m\n", - __FUNCTION__, null_count, (null_count == 1) ? ' ' : 's'); -- ide_atapi_cmd_ok(s); ++ ++ if(cmd->din_xfer_len == 0) ++ { ++ // Nothing else to do + ide_atapi_cmd_ok(s); - s->atapi_pt.cmd_sent = NULL; return; } @@ -166,7 +381,7 @@ index 413cc47..66da45a 100644 - s->atapi_pt.cmd_sent = NULL; - DEBUG_PRINTF("**** finished (%p)\n", s); -} -- + -#define ATAPI_PT_SEND_PACKET \ - do { \ - BDRVRawState *raw_state = s->bs->opaque; \ @@ -186,7 +401,46 @@ index 413cc47..66da45a 100644 - s->atapi_pt.cmd.dout_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_cmd_ok; - ATAPI_PT_SEND_PACKET; -+ s->atapi_pt.cmd_sent(s); ++ din_desired = atapi_data_sizes[cmd_code].din_len_const + ++ (ide_atapi_pt_read_field_at_offset(s->io_buffer, ++ atapi_data_sizes[cmd_code].din_len_offset, ++ atapi_data_sizes[cmd_code].din_len_size) * ++ atapi_data_sizes[cmd_code].din_block_size); ++ ++ /* cmd->din_xfer_len is the size of the buffer provided for the din data, ++ * din_desired in the size of the data the LU tried to send to us. Either one ++ * may be bigger. */ ++ ++ if(s->atapi_pt.request[0] == GPCMD_READ_BUFFER) ++ { ++ switch (s->atapi_pt.request[1] & 7) ++ { ++ case 0: // data with header, as specified in atapi_data_sizes table ++ break; ++ ++ case 2: // data only ++ din_desired = cmd->din_xfer_len; ++ break; ++ ++ case 3: // header only ++ din_desired = 4; ++ break; ++ ++ case 1: // vendor specific ++ default: ++ DEBUG_PRINTF("\e[3;31mIllegal read buffer mode %d\e[m\n", ++ s->io_buffer[1] & 7); ++ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, ++ ASC_ILLEGAL_OPCODE, 0x70); ++ return; ++ } ++ } ++ ++ if(din_desired == (__u32)-1) ++ din_desired = cmd->din_xfer_len; ++ ++ DEBUG_PRINTF("Reply, %d in %d\n", din_desired, cmd->din_xfer_len); ++ ide_atapi_cmd_reply(s, din_desired, cmd->din_xfer_len); } -static void ide_atapi_pt_read_pio_end(IDEState *s) @@ -202,7 +456,7 @@ index 413cc47..66da45a 100644 { BMDMAState *bm = opaque; IDEState *s = bm->ide_if; -@@ -626,11 +608,9 @@ static void ide_atapi_pt_read_dma_cb(void *opaque, int ret) +@@ -626,11 +854,9 @@ static void ide_atapi_pt_read_dma_cb(void *opaque, int ret) } i = dma_buf_rw(bm, 0); @@ -215,7 +469,7 @@ index 413cc47..66da45a 100644 static void ide_atapi_pt_wcmd(IDEState *s) { if (s->atapi_dma) -@@ -638,7 +618,7 @@ static void ide_atapi_pt_wcmd(IDEState *s) +@@ -638,7 +864,7 @@ static void ide_atapi_pt_wcmd(IDEState *s) /* DMA */ s->io_buffer_index = 0; s->io_buffer_size = s->atapi_pt.cmd.dout_xfer_len; @@ -224,7 +478,7 @@ index 413cc47..66da45a 100644 return; } -@@ -653,11 +633,10 @@ static void ide_atapi_pt_wcmd(IDEState *s) +@@ -653,44 +879,10 @@ static void ide_atapi_pt_wcmd(IDEState *s) ~ATAPI_INT_REASON_IO & ~ATAPI_INT_REASON_CD; ide_transfer_start(s, s->io_buffer, s->atapi_pt.cmd.dout_xfer_len, @@ -234,104 +488,212 @@ index 413cc47..66da45a 100644 return; } -#endif +- +-static void ide_atapi_pt_read_format_capacities_sent(IDEState *s) +-{ +- int size = (s->io_buffer[3] << 3) + 4; +- ide_atapi_cmd_reply(s, size, s->atapi_pt.cmd.din_xfer_len); +-} +- +-static void ide_atapi_pt_standard_reply(IDEState *s) +-{ +- uint32_t size = s->atapi_pt.reply_size_init; +- +- switch (s->atapi_pt.reply_size_len) +- { +- case 0: +- break; +- case 1: +- size += s->io_buffer[s->atapi_pt.reply_size_offset]; +- break; +- case 2: +- size += ube16_to_cpu(s->io_buffer + s->atapi_pt.reply_size_offset); +- break; +- case 3: +- size += ube24_to_cpu(s->io_buffer + s->atapi_pt.reply_size_offset); +- break; +- case 4: +- size += ube32_to_cpu(s->io_buffer + s->atapi_pt.reply_size_offset); +- break; +- default: +- assert(0); +- break; +- } +- ide_atapi_cmd_reply(s, size, s->atapi_pt.cmd.din_xfer_len); +-} - static void ide_atapi_pt_read_format_capacities_sent(IDEState *s) + static int ide_atapi_pt_read_cd_block_size(const uint8_t *io_buffer) { -@@ -817,9 +796,6 @@ static int ide_atapi_pt_read_cd_block_size(const uint8_t *io_buffer) +@@ -813,221 +1005,66 @@ static int ide_atapi_pt_read_cd_block_size(const uint8_t *io_buffer) + return block_size; + } + +- static void ide_atapi_pt_cmd(IDEState *s) { struct sg_io_v4 *cmd = &s->atapi_pt.cmd; - int r; - int command; - BDRVRawState *raw_state = s->bs->opaque; ++ uint8_t cmd_code; - memset(cmd, 0, sizeof (*cmd)); +- memset(cmd, 0, sizeof (*cmd)); ++ memset(cmd, 0, sizeof(*cmd)); memcpy(s->atapi_pt.request, s->io_buffer, ATAPI_PACKET_SIZE); -@@ -838,11 +814,13 @@ static void ide_atapi_pt_cmd(IDEState *s) - s->atapi_pt.reply_size_len = 0; ++ cmd_code = s->atapi_pt.request[0]; + cmd->guard = 'Q'; + cmd->protocol = 0; + cmd->subprotocol = 0; + cmd->request_len = ATAPI_PACKET_SIZE; + cmd->request = (__u64)s->atapi_pt.request; + cmd->response = (__u64)&s->atapi_pt.sense; +- cmd->max_response_len = sizeof (s->atapi_pt.sense); ++ cmd->max_response_len = sizeof(s->atapi_pt.sense); + cmd->timeout = 15000; // 15 seconds + +- s->status |= BUSY_STAT; +- s->atapi_pt.reply_size_init = 0; +- s->atapi_pt.reply_size_offset = 0; +- s->atapi_pt.reply_size_len = 0; ++ s->status |= BUSY_STAT; cmd->din_xferp = (__u64)s->io_buffer; - cmd->dout_xferp = (__u64)(s->io_buffer + ATAPI_PACKET_SIZE); -+ cmd->dout_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_cmd_ok; +- s->atapi_pt.cmd_sent = ide_atapi_cmd_ok; - command = s->io_buffer[0]; ++ cmd->dout_xferp = (__u64)s->io_buffer; - switch (s->io_buffer[0]) +- { +- /*******************/ +- /* SIMPLE COMMANDS */ +- /*******************/ + DEBUG_PRINTF("[ATAPI] sending command: 0x%02x (\e[0;32m%s\e[m)\n", -+ s->atapi_pt.request[0], atapi_cmd_to_str(s->atapi_pt.request[0])); -+ -+ switch (s->atapi_pt.request[0]) - { - /*******************/ - /* SIMPLE COMMANDS */ -@@ -880,25 +858,19 @@ static void ide_atapi_pt_cmd(IDEState *s) - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7) * CD_FRAMESIZE; -- ++ cmd_code, atapi_cmd_to_str(cmd_code)); + +- case GPCMD_BLANK: // bigger timeout while blanking +- cmd->timeout = 1000 * 60 * 80; // 80 mins +- goto simple_cmd; +- case GPCMD_CLOSE_TRACK: +- cmd->timeout = 1000 * 60 * 5; // 5 mins +- goto simple_cmd; +- case GPCMD_FLUSH_CACHE: // also called SYNCHRONIZE_CACHE +- case GPCMD_LOAD_UNLOAD: +- case GPCMD_PAUSE_RESUME: +- case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: +- case GPCMD_REPAIR_RZONE_TRACK: +- case GPCMD_RESERVE_RZONE_TRACK: +- case GPCMD_SCAN: +- case GPCMD_SEEK: +- case GPCMD_SET_READ_AHEAD: +- case GPCMD_START_STOP_UNIT: +- case GPCMD_STOP_PLAY_SCAN: +- case GPCMD_TEST_UNIT_READY: +- case GPCMD_VERIFY_10: +- case GPCMD_SET_SPEED: /* FIXME: find the documentation */ +- simple_cmd: +- CHECK_SAME_VALUE(s->lcyl, 0); +- CHECK_SAME_VALUE(s->hcyl, 0); +- break; ++ cmd->dout_xfer_len = atapi_data_sizes[cmd_code].dout_len_const + ++ (ide_atapi_pt_read_field_at_offset(s->atapi_pt.request, ++ atapi_data_sizes[cmd_code].dout_len_offset, ++ atapi_data_sizes[cmd_code].dout_len_size) * ++ atapi_data_sizes[cmd_code].dout_block_size); + +- /******************/ +- /* WRITE COMMANDS */ +- /******************/ ++ cmd->din_xfer_len = atapi_data_sizes[cmd_code].alloc_len_const + ++ (ide_atapi_pt_read_field_at_offset(s->atapi_pt.request, ++ atapi_data_sizes[cmd_code].alloc_len_offset, ++ atapi_data_sizes[cmd_code].alloc_len_size) * ++ atapi_data_sizes[cmd_code].alloc_block_size); + +- case GPCMD_WRITE_10: +- case GPCMD_WRITE_AND_VERIFY_10: +- cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7) * CD_FRAMESIZE; + - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - if (cmd->dout_xfer_len == 0) - goto simple_cmd; +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; - - case GPCMD_WRITE_12: - cmd->dout_xfer_len = ube32_to_cpu(s->io_buffer + 6); +- +- case GPCMD_WRITE_12: +- cmd->dout_xfer_len = ube32_to_cpu(s->io_buffer + 6); - - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - if (cmd->dout_xfer_len == 0) - goto simple_cmd; +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - // ide_atapi_pt_wcmd(s); - // return; - break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; - - case GPCMD_WRITE_BUFFER: +- +- case GPCMD_WRITE_BUFFER: ++ /* A few commands need special attention */ ++ switch(cmd_code) { -@@ -925,109 +897,68 @@ static void ide_atapi_pt_cmd(IDEState *s) - goto illegal_request; - } - +- int32_t parameter_list_length = ube24_to_cpu(s->io_buffer + 3); +- int8_t mode = s->io_buffer[1] & 0x03; +- +- switch (mode) +- { +- case 0x0: // Combined header and data mode +- // The documentation is confusing because it says that parameter +- // list length contains all the data, but the buffer should be +- // greater than parameter list length + 4... +- cmd->dout_xfer_len = parameter_list_length + 4; +- break; +- case 0x2: // Data mode +- cmd->dout_xfer_len = parameter_list_length; +- break; +- case 0x1: // Vendor specific +- case 0x4: // Download microcode +- case 0x5: // Download microcode and save mode +- case 0x6: // Download microcode with offsets +- case 0x7: // Download microcode with offsets and save mode +- default: +- goto illegal_request; +- } +- - - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - // ide_atapi_pt_wcmd(s); - // return; -- break; -+ ide_atapi_pt_wcmd(s); -+ return; - } - - case GPCMD_SEND_CUE_SHEET: - cmd->dout_xfer_len = ube24_to_cpu(s->io_buffer + 6); ++ case GPCMD_BLANK: // bigger timeout while blanking ++ cmd->timeout = 1000 * 60 * 80; // 80 mins + break; +- } - +- case GPCMD_SEND_CUE_SHEET: +- cmd->dout_xfer_len = ube24_to_cpu(s->io_buffer + 6); + - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - if (cmd->dout_xfer_len == 0) - goto simple_cmd; +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - // ide_atapi_pt_wcmd(s); - // return; -- break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; ++ case GPCMD_CLOSE_TRACK: ++ cmd->timeout = 1000 * 60 * 5; // 5 mins + break; - case GPCMD_MODE_SELECT_10: - cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7); - CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->dout_xfer_len); +- case GPCMD_MODE_SELECT_10: +- cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->dout_xfer_len); - - DEBUG_PRINTF("Mode select 10 %d bytes\n", cmd->dout_xfer_len); -- { ++ case GPCMD_WRITE_BUFFER: ++ if((s->io_buffer[1] & 7) != 0 && // Combined header and data mode ++ (s->io_buffer[1] & 7) != 2) // Data mode + { - int i; - DEBUG_PRINTF("0x"); - for(i = 0; i < 12; ++i) @@ -340,66 +702,59 @@ index 413cc47..66da45a 100644 - for(i = 0; i < cmd->dout_xfer_len; ++i) - DEBUG_PRINTF("%02x ", s->io_buffer[i + 12]); - DEBUG_PRINTF("\n"); -- } -- - if (cmd->dout_xfer_len == 0) - goto simple_cmd; ++ DEBUG_PRINTF("\e[3;31mIllegal write buffer mode %d\e[m\n", ++ s->io_buffer[1] & 7); ++ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, ++ ASC_ILLEGAL_OPCODE, 0x70); ++ return; + } + +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - // ide_atapi_pt_wcmd(s); - // return; - break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; - - case GPCMD_SEND_KEY: - case GPCMD_SEND_EVENT: - cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 8); +- +- case GPCMD_SEND_KEY: +- case GPCMD_SEND_EVENT: +- cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 8); - - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - if (cmd->dout_xfer_len == 0) - goto simple_cmd; +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - // ide_atapi_pt_wcmd(s); - // return; - break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; - - case GPCMD_SEND_OPC: - cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7) << 3; - CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->dout_xfer_len); +- +- case GPCMD_SEND_OPC: +- cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7) << 3; +- CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->dout_xfer_len); - - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - if (cmd->dout_xfer_len == 0) - goto simple_cmd; +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - // ide_atapi_pt_wcmd(s); - // return; - break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; - - case GPCMD_SET_STREAMING: - cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 9); +- +- case GPCMD_SET_STREAMING: +- cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 9); - - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); - - if (cmd->dout_xfer_len == 0) - goto simple_cmd; +- if (cmd->dout_xfer_len == 0) +- goto simple_cmd; - // ide_atapi_pt_wcmd(s); - // return; - break; -+ -+ ide_atapi_pt_wcmd(s); -+ return; - - case GPCMD_FORMAT_UNIT: - cmd->dout_xfer_len = 12; +- +- case GPCMD_FORMAT_UNIT: +- cmd->dout_xfer_len = 12; - - DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command), - cmd->dout_xfer_len); @@ -407,25 +762,23 @@ index 413cc47..66da45a 100644 - // ide_atapi_pt_wcmd(s); - // return; - break; -+ ide_atapi_pt_wcmd(s); -+ return; - - /*****************/ - /* READ COMMANDS */ - /*****************/ - - case GPCMD_INQUIRY: +- +- /*****************/ +- /* READ COMMANDS */ +- /*****************/ +- +- case GPCMD_INQUIRY: - // cmd->din_xferp = (__u64)s->io_buffer; - cmd->din_xfer_len = s->io_buffer[4]; - s->atapi_pt.reply_size_init = 5; - s->atapi_pt.reply_size_offset = 4; - s->atapi_pt.reply_size_len = 1; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- cmd->din_xfer_len = s->io_buffer[4]; +- s->atapi_pt.reply_size_init = 5; +- s->atapi_pt.reply_size_offset = 4; +- s->atapi_pt.reply_size_len = 1; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - // ATAPI_PT_SEND_PACKET; break; case GPCMD_REQUEST_SENSE: -@@ -1042,10 +973,6 @@ static void ide_atapi_pt_cmd(IDEState *s) +@@ -1042,185 +1079,15 @@ static void ide_atapi_pt_cmd(IDEState *s) int max_size = s->io_buffer[4]; int size = 8 + s->atapi_pt.sense.add_sense_len; @@ -436,216 +789,293 @@ index 413cc47..66da45a 100644 memcpy(s->io_buffer, &s->atapi_pt.sense, sizeof (s->atapi_pt.sense)); ide_atapi_cmd_reply(s, size, max_size); return; -@@ -1053,57 +980,41 @@ static void ide_atapi_pt_cmd(IDEState *s) + } - case GPCMD_READ_DVD_STRUCTURE: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); +- case GPCMD_READ_DVD_STRUCTURE: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; -+ s->atapi_pt.reply_size_init = 4; - s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 2; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_READ_HEADER: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- break; +- +- case GPCMD_READ_HEADER: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_MECHANISM_STATUS: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); +- break; +- +- case GPCMD_MECHANISM_STATUS: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_offset = 6; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_offset = 6; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_REPORT_KEY: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); +- break; +- +- case GPCMD_REPORT_KEY: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_len = 2; - s->atapi_pt.reply_size_init = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.reply_size_init = 2; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_READ_BUFFER_CAPACITY: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- break; +- +- case GPCMD_READ_BUFFER_CAPACITY: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_len = 2; - s->atapi_pt.reply_size_init = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.reply_size_init = 2; - // return; - break; - - case GPCMD_GET_PERFORMANCE: - cmd->din_xfer_len = 8 + 8 * ube16_to_cpu(s->io_buffer + 8); +- break; +- +- case GPCMD_GET_PERFORMANCE: +- cmd->din_xfer_len = 8 + 8 * ube16_to_cpu(s->io_buffer + 8); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_len = 4; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 4; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_READ_10: -@@ -1123,17 +1034,12 @@ static void ide_atapi_pt_cmd(IDEState *s) - default: assert(0); - } - cmd->din_xfer_len = nbblocks * blocksize; +- break; +- +- case GPCMD_READ_10: +- case GPCMD_READ_12: +- { +- int blocksize = 0, nbblocks; +- +- switch (s->io_buffer[0]) { +- case GPCMD_READ_10: +- blocksize = CD_FRAMESIZE; +- nbblocks = ube16_to_cpu(s->io_buffer + 7); +- break; +- case GPCMD_READ_12: +- blocksize = CD_FRAMESIZE_RAW0; +- nbblocks = ube32_to_cpu(s->io_buffer + 6); +- break; +- default: assert(0); +- } +- cmd->din_xfer_len = nbblocks * blocksize; - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; - break; - } - - case GPCMD_READ_BUFFER: +- break; +- } +- +- case GPCMD_READ_BUFFER: - // TODO check this one is correct - // cmd->din_xferp = (__u64)s->io_buffer; - cmd->din_xfer_len = ube24_to_cpu(s->io_buffer + 6); - - switch (s->io_buffer[1] & 0x7) -@@ -1157,30 +1063,21 @@ static void ide_atapi_pt_cmd(IDEState *s) - goto illegal_request; - } - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- cmd->din_xfer_len = ube24_to_cpu(s->io_buffer + 6); +- +- switch (s->io_buffer[1] & 0x7) +- { +- case 0: // data with header +- s->atapi_pt.reply_size_init = 4; +- s->atapi_pt.reply_size_len = 3; +- s->atapi_pt.reply_size_offset = 1; +- break; +- +- case 2: // data only +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- break; +- +- case 3: // header only +- s->atapi_pt.reply_size_init = 4; +- break; +- +- case 1: // vendor specific +- default: +- goto illegal_request; +- } +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_READ_CDVD_CAPACITY: - cmd->din_xfer_len = 8; - CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->din_xfer_len); +- break; +- +- case GPCMD_READ_CDVD_CAPACITY: +- cmd->din_xfer_len = 8; +- CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->din_xfer_len); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_MODE_SENSE_10: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->din_xfer_len); +- break; +- +- case GPCMD_MODE_SENSE_10: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->din_xfer_len); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_len = 2; - s->atapi_pt.reply_size_init = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.reply_size_init = 2; - //s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: -@@ -1188,22 +1085,16 @@ static void ide_atapi_pt_cmd(IDEState *s) - case GPCMD_READ_TOC_PMA_ATIP: - case GPCMD_READ_TRACK_RZONE_INFO: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- break; +- +- case GPCMD_GET_EVENT_STATUS_NOTIFICATION: +- case GPCMD_READ_DISC_INFO: +- case GPCMD_READ_TOC_PMA_ATIP: +- case GPCMD_READ_TRACK_RZONE_INFO: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_len = 2; - s->atapi_pt.reply_size_init = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.reply_size_init = 2; - // ATAPI_PT_SEND_PACKET; - // return; - break; - - case GPCMD_READ_SUBCHANNEL: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- break; +- +- case GPCMD_READ_SUBCHANNEL: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_len = 2; - s->atapi_pt.reply_size_offset = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.reply_size_offset = 2; - // ATAPI_PT_SEND_PACKET; - // return; - break; - +- break; +- case GPCMD_READ_CD: -@@ -1214,11 +1105,8 @@ static void ide_atapi_pt_cmd(IDEState *s) - int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer); - - cmd->din_xfer_len = block_count * block_size; +- { +- // command fields +- int block_count = ((s->io_buffer[6] << 16) | +- ube16_to_cpu(s->io_buffer + 7)); +- int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer); +- +- cmd->din_xfer_len = block_count * block_size; - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; ++ // We read blocks, not bytes ++ cmd->din_xfer_len *= ide_atapi_pt_read_cd_block_size(s->io_buffer); break; - } +- } -@@ -1233,11 +1121,8 @@ static void ide_atapi_pt_cmd(IDEState *s) + case GPCMD_READ_CD_MSF: + { +@@ -1233,23 +1100,6 @@ static void ide_atapi_pt_cmd(IDEState *s) int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer); cmd->din_xfer_len = block_count * block_size; - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; - break; - } - -@@ -1245,11 +1130,8 @@ static void ide_atapi_pt_cmd(IDEState *s) - { - int block_count = ube16_to_cpu(s->io_buffer + 7); - cmd->din_xfer_len = block_count * CD_FRAMESIZE; +- break; +- } +- +- case GPCMD_PLAY_AUDIO_10: +- { +- int block_count = ube16_to_cpu(s->io_buffer + 7); +- cmd->din_xfer_len = block_count * CD_FRAMESIZE; - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; break; } -@@ -1261,40 +1143,28 @@ static void ide_atapi_pt_cmd(IDEState *s) +@@ -1261,167 +1111,53 @@ static void ide_atapi_pt_cmd(IDEState *s) MSF_TO_FRAMES(s->io_buffer[6], s->io_buffer[7], s->io_buffer[8]); int block_count = ending_frame - starting_frame; cmd->din_xfer_len = block_count * CD_FRAMESIZE; - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = cmd->din_xfer_len; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = cmd->din_xfer_len; - // ATAPI_PT_SEND_PACKET; - // return; break; } - case GPCMD_READ_FORMAT_CAPACITIES: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- case GPCMD_READ_FORMAT_CAPACITIES: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_read_format_capacities_sent; +- s->atapi_pt.cmd_sent = ide_atapi_pt_read_format_capacities_sent; - // ATAPI_PT_SEND_PACKET; - // return; - break; +- break; ++ case GPCMD_GET_PERFORMANCE: ++ // din_xfer_len is currently the max number of descriptors ++ switch(s->io_buffer[10]) ++ { ++ case 0: // performance ++ if((s->io_buffer[1] & 3) == 0) // nominal performance, 16 byte descriptors ++ cmd->din_xfer_len *= 16; ++ else // exceptions, 6 byte descriptors ++ cmd->din_xfer_len *= 6; - case GPCMD_GET_CONFIGURATION: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); +- case GPCMD_GET_CONFIGURATION: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = 4; - s->atapi_pt.reply_size_len = 4; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = 4; +- s->atapi_pt.reply_size_len = 4; - // ATAPI_PT_SEND_PACKET; - // return; - break; +- break; ++ cmd->din_xfer_len += 8; // 8 bytes of header ++ break; - case GPCMD_SEND_DVD_STRUCTURE: - cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); +- case GPCMD_SEND_DVD_STRUCTURE: +- cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8); - // cmd->din_xferp = (__u64)s->io_buffer; - s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; - s->atapi_pt.reply_size_init = 2; - s->atapi_pt.reply_size_len = 2; +- s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; +- s->atapi_pt.reply_size_init = 2; +- s->atapi_pt.reply_size_len = 2; - // ATAPI_PT_SEND_PACKET; - // return; - break; +- break; ++ case 1: // unusable area ++ cmd->din_xfer_len *= 8; // 8 byte descriptors ++ cmd->din_xfer_len += 8; // 8 bytes of header ++ break; - case 0x01: // GPMODE_R_W_ERROR_PAGE ? -@@ -1318,110 +1188,5 @@ static void ide_atapi_pt_cmd(IDEState *s) - return; +- case 0x01: // GPMODE_R_W_ERROR_PAGE ? +- case 0x1a: // GPMODE_POWER_PAGE ? +- case 0xfa: +- case 0xfd: +- case 0xf2: +- case 0xf3: // WIN_SECURITY_ERASE_PREPARE ? +- case 0xee: // WIN_IDENTIFY_DMA ? +- case 0xdf: // WIN_DOORUNLOCK ? +- DEBUG_PRINTF("[\e[3;31mILLEGAL?\e[m] 0x%02x, size: %d\n", +- s->io_buffer[0], s->lcyl | (s->hcyl << 8)); +- illegal_request: +- ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, +- ASC_ILLEGAL_OPCODE, 0x70); +- return; ++ case 2: // defect status ++ cmd->din_xfer_len *= 2048; // 2048 byte descriptors ++ cmd->din_xfer_len += 8; // 8 bytes of header ++ break; + +- default: +- DEBUG_PRINTF("[UNHANDLED] 0x%02x\n", s->io_buffer[0]); +- exit(1); +- return; ++ default: ++ DEBUG_PRINTF("\e[3;31mReserved get performance type %d\e[m\n", ++ s->io_buffer[10]); ++ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, ++ ASC_ILLEGAL_OPCODE, 0x70); ++ return; ++ } ++ break; } - @@ -658,7 +1088,8 @@ index 413cc47..66da45a 100644 - r = ioctl(raw_state->fd, 0x2285, cmd); - - if(command == GPCMD_GET_EVENT_STATUS_NOTIFICATION) -- { ++ if(cmd->dout_xfer_len == (__u32)-1) + { - struct stat file_stat; - - if(s->io_buffer[2] == 4 && s->io_buffer[4] == 2) @@ -718,8 +1149,10 @@ index 413cc47..66da45a 100644 - s->io_buffer[7] = 0; - } - } -- } -- ++ DEBUG_PRINTF("[UNHANDLED SCSI COMMAND] 0x%02x\n", cmd_code); ++ exit(1); + } + - if(r || cmd->driver_status || cmd->transport_status || - cmd->device_status) { - /* @@ -750,9 +1183,12 @@ index 413cc47..66da45a 100644 - s->atapi_pt.sense.asc, - s->atapi_pt.sense.ascq)); - ide_atapi_pt_error(s); -- return; -- } -- ++ if(cmd->dout_xfer_len > 0) ++ { ++ ide_atapi_pt_wcmd(s); + return; + } + - s->atapi_pt.cmd_sent(s); + ide_atapi_pt_do_sg_io(s); }