#include "hw/ide/internal.h"
#include "hw/scsi/scsi.h"
#include "sysemu/block-backend.h"
+#include "trace.h"
#define ATAPI_SECTOR_BITS (2 + BDRV_SECTOR_BITS)
#define ATAPI_SECTOR_SIZE (1 << ATAPI_SECTOR_BITS)
block_acct_start(blk_get_stats(s->blk), &s->acct,
ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
-#ifdef DEBUG_IDE_ATAPI
- printf("cd_read_sector_sync: lba=%d\n", s->lba);
-#endif
+ trace_cd_read_sector_sync(s->lba);
switch (s->cd_sector_size) {
case 2048:
{
IDEState *s = opaque;
-#ifdef DEBUG_IDE_ATAPI
- printf("cd_read_sector_cb: lba=%d ret=%d\n", s->lba, ret);
-#endif
+ trace_cd_read_sector_cb(s->lba, ret);
if (ret < 0) {
block_acct_failed(blk_get_stats(s->blk), &s->acct);
s->iov.iov_len = ATAPI_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
-#ifdef DEBUG_IDE_ATAPI
- printf("cd_read_sector: lba=%d\n", s->lba);
-#endif
+ trace_cd_read_sector(s->lba);
block_acct_start(blk_get_stats(s->blk), &s->acct,
ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
{
-#ifdef DEBUG_IDE_ATAPI
- printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
-#endif
+ trace_ide_atapi_cmd_error(s, sense_key, asc);
s->error = sense_key << 4;
s->status = READY_STAT | ERR_STAT;
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
void ide_atapi_cmd_reply_end(IDEState *s)
{
int byte_count_limit, size, ret;
-#ifdef DEBUG_IDE_ATAPI
- printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
- s->packet_transfer_size,
- s->elementary_transfer_size,
- s->io_buffer_index);
-#endif
+ trace_ide_atapi_cmd_reply_end(s, s->packet_transfer_size,
+ s->elementary_transfer_size,
+ s->io_buffer_index);
if (s->packet_transfer_size <= 0) {
/* end of transfer */
ide_atapi_cmd_ok(s);
ide_set_irq(s->bus);
-#ifdef DEBUG_IDE_ATAPI
- printf("end of transfer, status=0x%x\n", s->status);
-#endif
+ trace_ide_atapi_cmd_reply_end_eot(s, s->status);
} else {
/* see if a new sector must be read */
if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
/* a new transfer is needed */
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
byte_count_limit = atapi_byte_count_limit(s);
-#ifdef DEBUG_IDE_ATAPI
- printf("byte_count_limit=%d\n", byte_count_limit);
-#endif
+ trace_ide_atapi_cmd_reply_end_bcl(s, byte_count_limit);
size = s->packet_transfer_size;
if (size > byte_count_limit) {
/* byte count limit must be even if this case */
ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
size, ide_atapi_cmd_reply_end);
ide_set_irq(s->bus);
-#ifdef DEBUG_IDE_ATAPI
- printf("status=0x%x\n", s->status);
-#endif
+ trace_ide_atapi_cmd_reply_end_new(s, s->status);
}
}
}
static void ide_atapi_cmd_check_status(IDEState *s)
{
-#ifdef DEBUG_IDE_ATAPI
- printf("atapi_cmd_check_status\n");
-#endif
+ trace_ide_atapi_cmd_check_status(s);
s->error = MC_ERR | (UNIT_ATTENTION << 4);
s->status = ERR_STAT;
s->nsector = 0;
if (ret < 0) {
if (ide_handle_rw_error(s, -ret, ide_dma_cmd_to_retry(s->dma_cmd))) {
if (s->bus->error_status) {
+ s->bus->dma->aiocb = NULL;
return;
}
goto eot;
s->io_buffer_size = n * 2048;
data_offset = 0;
}
-#ifdef DEBUG_AIO
- printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
-#endif
-
+ trace_ide_atapi_cmd_read_dma_cb_aio(s, s->lba, n);
s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE;
qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
int sector_size)
{
-#ifdef DEBUG_IDE_ATAPI
- printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
- lba, nb_sectors);
-#endif
+ trace_ide_atapi_cmd_read(s, s->atapi_dma ? "dma" : "pio",
+ lba, nb_sectors);
if (s->atapi_dma) {
ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
} else {
return 8; /* We wrote to 4 extra bytes from the header */
}
+/*
+ * Before transferring data or otherwise signalling acceptance of a command
+ * marked CONDDATA, we must check the validity of the byte_count_limit.
+ */
+static bool validate_bcl(IDEState *s)
+{
+ /* TODO: Check IDENTIFY data word 125 for defacult BCL (currently 0) */
+ if (s->atapi_dma || atapi_byte_count_limit(s)) {
+ return true;
+ }
+
+ /* TODO: Move abort back into core.c and introduce proper error flow between
+ * ATAPI layer and IDE core layer */
+ ide_abort_command(s);
+ return false;
+}
+
static void cmd_get_event_status_notification(IDEState *s,
uint8_t *buf)
{
return;
}
- transfer_request = buf[9];
- switch(transfer_request & 0xf8) {
- case 0x00:
+ transfer_request = buf[9] & 0xf8;
+ if (transfer_request == 0x00) {
/* nothing */
ide_atapi_cmd_ok(s);
- break;
+ return;
+ }
+
+ /* Check validity of BCL before transferring data */
+ if (!validate_bcl(s)) {
+ return;
+ }
+
+ switch (transfer_request) {
case 0x10:
/* normal read */
ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
* See ATA8-ACS3 "7.21.5 Byte Count Limit"
*/
NONDATA = 0x04,
+
+ /*
+ * CONDDATA implies a command that transfers data only conditionally based
+ * on the presence of suboptions. It should be exempt from the BCL check at
+ * command validation time, but it needs to be checked at the command
+ * handler level instead.
+ */
+ CONDDATA = 0x08,
};
static const struct AtapiCmd {
[ 0xad ] = { cmd_read_dvd_structure, CHECK_READY },
[ 0xbb ] = { cmd_set_speed, NONDATA },
[ 0xbd ] = { cmd_mechanism_status, 0 },
- [ 0xbe ] = { cmd_read_cd, CHECK_READY },
+ [ 0xbe ] = { cmd_read_cd, CHECK_READY | CONDDATA },
/* [1] handler detects and reports not ready condition itself */
};
uint8_t *buf = s->io_buffer;
const struct AtapiCmd *cmd = &atapi_cmd_table[s->io_buffer[0]];
-#ifdef DEBUG_IDE_ATAPI
- {
+ trace_ide_atapi_cmd(s, s->io_buffer[0]);
+
+ if (trace_event_get_state_backends(TRACE_IDE_ATAPI_CMD_PACKET)) {
+ /* Each pretty-printed byte needs two bytes and a space; */
+ char *ppacket = g_malloc(ATAPI_PACKET_SIZE * 3 + 1);
int i;
- printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
- for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
- printf(" %02x", buf[i]);
+ for (i = 0; i < ATAPI_PACKET_SIZE; i++) {
+ sprintf(ppacket + (i * 3), "%02x ", buf[i]);
}
- printf("\n");
+ trace_ide_atapi_cmd_packet(s, s->lcyl | (s->hcyl << 8), ppacket);
+ g_free(ppacket);
}
-#endif
/*
* If there's a UNIT_ATTENTION condition pending, only command flagged with
return;
}
- /* Nondata commands permit the byte_count_limit to be 0.
+ /* Commands that don't transfer DATA permit the byte_count_limit to be 0.
* If this is a data-transferring PIO command and BCL is 0,
* we abort at the /ATA/ level, not the ATAPI level.
* See ATA8 ACS3 section 7.17.6.49 and 7.21.5 */
- if (cmd->handler && !(cmd->flags & NONDATA)) {
- /* TODO: Check IDENTIFY data word 125 for default BCL (currently 0) */
- if (!(atapi_byte_count_limit(s) || s->atapi_dma)) {
- /* TODO: Move abort back into core.c and make static inline again */
- ide_abort_command(s);
+ if (cmd->handler && !(cmd->flags & (NONDATA | CONDDATA))) {
+ if (!validate_bcl(s)) {
return;
}
}