Commit e0a4cb2c authored by John Snow's avatar John Snow
Browse files

libqos/ahci: Add get_sense and test_ready



Required for tray tests once a medium may have changed.

Signed-off-by: default avatarJohn Snow <jsnow@redhat.com>
Reviewed-by: default avatarKevin Wolf <kwolf@redhat.com>
Message-id: 1478553214-497-6-git-send-email-jsnow@redhat.com
[Line length edit --js]
Signed-off-by: default avatarJohn Snow <jsnow@redhat.com>
parent 48cde091
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -882,6 +882,49 @@ AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd, uint16_t bcl)
    return cmd;
}

void ahci_atapi_test_ready(AHCIQState *ahci, uint8_t port,
                           bool ready, uint8_t expected_sense)
{
    AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_TEST_UNIT_READY, 0);
    ahci_command_set_size(cmd, 0);
    if (!ready) {
        cmd->interrupts |= AHCI_PX_IS_TFES;
        cmd->errors |= expected_sense << 4;
    }
    ahci_command_commit(ahci, cmd, port);
    ahci_command_issue(ahci, cmd);
    ahci_command_verify(ahci, cmd);
    ahci_command_free(cmd);
}

static int copy_buffer(AHCIQState *ahci, AHCICommand *cmd,
                        const AHCIOpts *opts)
{
    unsigned char *rx = opts->opaque;
    bufread(opts->buffer, rx, opts->size);
    return 0;
}

void ahci_atapi_get_sense(AHCIQState *ahci, uint8_t port,
                          uint8_t *sense, uint8_t *asc)
{
    unsigned char *rx;
    AHCIOpts opts = {
        .size = 18,
        .atapi = true,
        .post_cb = copy_buffer,
    };
    rx = g_malloc(18);
    opts.opaque = rx;

    ahci_exec(ahci, port, CMD_ATAPI_REQUEST_SENSE, &opts);

    *sense = rx[2];
    *asc = rx[12];

    g_free(rx);
}

void ahci_atapi_eject(AHCIQState *ahci, uint8_t port)
{
    AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT, 0);
@@ -934,6 +977,8 @@ static void ahci_atapi_command_set_offset(AHCICommand *cmd, uint64_t lba)
        g_assert_cmpuint(lba, <=, UINT32_MAX);
        stl_be_p(&cbd[2], lba);
        break;
    case CMD_ATAPI_REQUEST_SENSE:
    case CMD_ATAPI_TEST_UNIT_READY:
    case CMD_ATAPI_START_STOP_UNIT:
        g_assert_cmpuint(lba, ==, 0x00);
        break;
@@ -1004,6 +1049,11 @@ static void ahci_atapi_set_size(AHCICommand *cmd, uint64_t xbytes)
        cbd[7] = (tmp & 0xFF00) >> 8;
        cbd[8] = (tmp & 0xFF);
        break;
    case CMD_ATAPI_REQUEST_SENSE:
        g_assert_cmpuint(xbytes, <=, UINT8_MAX);
        cbd[4] = (uint8_t)xbytes;
        break;
    case CMD_ATAPI_TEST_UNIT_READY:
    case CMD_ATAPI_START_STOP_UNIT:
        g_assert_cmpuint(xbytes, ==, 0);
        break;
+17 −0
Original line number Diff line number Diff line
@@ -287,11 +287,24 @@ enum {

/* ATAPI Commands */
enum {
    CMD_ATAPI_TEST_UNIT_READY = 0x00,
    CMD_ATAPI_REQUEST_SENSE   = 0x03,
    CMD_ATAPI_START_STOP_UNIT = 0x1b,
    CMD_ATAPI_READ_10         = 0x28,
    CMD_ATAPI_READ_CD         = 0xbe,
};

enum {
    SENSE_NO_SENSE       = 0x00,
    SENSE_NOT_READY      = 0x02,
    SENSE_UNIT_ATTENTION = 0x06,
};

enum {
    ASC_MEDIUM_MAY_HAVE_CHANGED = 0x28,
    ASC_MEDIUM_NOT_PRESENT      = 0x3a,
};

/* AHCI Command Header Flags & Masks*/
#define CMDH_CFL        (0x1F)
#define CMDH_ATAPI      (0x20)
@@ -601,6 +614,10 @@ void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
             void *buffer, size_t bufsize, uint64_t sector);
void ahci_exec(AHCIQState *ahci, uint8_t port,
               uint8_t op, const AHCIOpts *opts);
void ahci_atapi_test_ready(AHCIQState *ahci, uint8_t port, bool ready,
                           uint8_t expected_sense);
void ahci_atapi_get_sense(AHCIQState *ahci, uint8_t port,
                          uint8_t *sense, uint8_t *asc);
void ahci_atapi_eject(AHCIQState *ahci, uint8_t port);
void ahci_atapi_load(AHCIQState *ahci, uint8_t port);