mirror of https://github.com/xqemu/xqemu.git
Pull request
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbMVpqAAoJEH3vgQaq/DkOvcAP/0UFYZcdoUm4g9gEkFJ1UKB6 INIpvQuTcIDoHctBQTfBZIN8mRKc9DPwhE21XWfcHzYQJ6mSnvzFc0LqigzJ5mbN pIS40i5m5B/KPje9aJYaWezciD18q5UFdzWHFOv0phfkmkmNxsys0jgo6VZRkOwW DxyuKpMzz0OkFxxr9Odm2GwFq40CL8Ajh+EABvDZYQAI8msMpxfoa/Fx5Kv1n1Ss woL3t5nlVmDK4o44Jmv5WodzA+nHal+Ct/Kw6OL4q7XxzR3x56s82pLDynlZeh2E clqgZ19+LsJ5yHwF5NaZCiRNHeNvZJcRBEW1DQb7q+D4yPT1+iyHINh4lxxW9sPR mzuOQl5ECmF+j2Acsch+dbPTB8UsQKDmpD8zrV/TuQkycoGLso5MbLdPHCmiPWIS ZhAE6wLgtCqgSr3KxvljYlAHCnbKKOqwWjOSVPajKhvmadXcOOCVkkY2AjLPS4Y9 p76hWGe2KfRzBFJbqKkoXTo0nxg1CnglzMwuS9Dre88rk1aKT+xIE9X9yfXGP86s i+fFYAkNe+m2e30GXklprmAof/ZE9E/LmrH/M5pwzjXhwSCl6bbhQhCZ8zpmBHx/ +n3ww1BTk4VNxWvrHxfysmSA20JDYta1l5e4OPHQwnGTODTi2bq4YbybC7StIfWb bjNlSSBkuGhNaE2EACbG =x3YN -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging Pull request # gpg: Signature made Mon 25 Jun 2018 22:11:06 BST # gpg: using RSA key 7DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * remotes/jnsnow/tags/ide-pull-request: ahci: fix FIS I bit and PIO Setup FIS interrupt Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
595123df1d
|
@ -801,7 +801,7 @@ static void ahci_write_fis_sdb(AHCIState *s, NCQTransferState *ncq_tfs)
|
|||
}
|
||||
}
|
||||
|
||||
static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len)
|
||||
static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len, bool pio_fis_i)
|
||||
{
|
||||
AHCIPortRegs *pr = &ad->port_regs;
|
||||
uint8_t *pio_fis;
|
||||
|
@ -814,7 +814,7 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len)
|
|||
pio_fis = &ad->res_fis[RES_FIS_PSFIS];
|
||||
|
||||
pio_fis[0] = SATA_FIS_TYPE_PIO_SETUP;
|
||||
pio_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0);
|
||||
pio_fis[1] = (pio_fis_i ? (1 << 6) : 0);
|
||||
pio_fis[2] = s->status;
|
||||
pio_fis[3] = s->error;
|
||||
|
||||
|
@ -842,8 +842,6 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len)
|
|||
if (pio_fis[2] & ERR_STAT) {
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES);
|
||||
}
|
||||
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_PSS);
|
||||
}
|
||||
|
||||
static bool ahci_write_fis_d2h(AHCIDevice *ad)
|
||||
|
@ -860,7 +858,7 @@ static bool ahci_write_fis_d2h(AHCIDevice *ad)
|
|||
d2h_fis = &ad->res_fis[RES_FIS_RFIS];
|
||||
|
||||
d2h_fis[0] = SATA_FIS_TYPE_REGISTER_D2H;
|
||||
d2h_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0);
|
||||
d2h_fis[1] = (1 << 6); /* interrupt bit */
|
||||
d2h_fis[2] = s->status;
|
||||
d2h_fis[3] = s->error;
|
||||
|
||||
|
@ -1258,11 +1256,10 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
|
|||
trace_handle_reg_h2d_fis_dump(s, port, pretty_fis);
|
||||
g_free(pretty_fis);
|
||||
}
|
||||
s->dev[port].done_atapi_packet = false;
|
||||
}
|
||||
|
||||
ide_state->error = 0;
|
||||
|
||||
s->dev[port].done_first_drq = false;
|
||||
/* Reset transferred byte counter */
|
||||
cmd->status = 0;
|
||||
|
||||
|
@ -1351,13 +1348,23 @@ static void ahci_pio_transfer(IDEDMA *dma)
|
|||
int is_write = opts & AHCI_CMD_WRITE;
|
||||
int is_atapi = opts & AHCI_CMD_ATAPI;
|
||||
int has_sglist = 0;
|
||||
bool pio_fis_i;
|
||||
|
||||
/* PIO FIS gets written prior to transfer */
|
||||
ahci_write_fis_pio(ad, size);
|
||||
/* The PIO Setup FIS is received prior to transfer, but the interrupt
|
||||
* is only triggered after data is received.
|
||||
*
|
||||
* The device only sets the 'I' bit in the PIO Setup FIS for device->host
|
||||
* requests (see "DPIOI1" in the SATA spec), or for host->device DRQs after
|
||||
* the first (see "DPIOO1"). The latter is consistent with the spec's
|
||||
* description of the PACKET protocol, where the command part of ATAPI requests
|
||||
* ("DPKT0") has the 'I' bit clear, while the data part of PIO ATAPI requests
|
||||
* ("DPKT4a" and "DPKT7") has the 'I' bit set for both directions for all DRQs.
|
||||
*/
|
||||
pio_fis_i = ad->done_first_drq || (!is_atapi && !is_write);
|
||||
ahci_write_fis_pio(ad, size, pio_fis_i);
|
||||
|
||||
if (is_atapi && !ad->done_atapi_packet) {
|
||||
if (is_atapi && !ad->done_first_drq) {
|
||||
/* already prepopulated iobuffer */
|
||||
ad->done_atapi_packet = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1379,9 +1386,15 @@ static void ahci_pio_transfer(IDEDMA *dma)
|
|||
|
||||
/* Update number of transferred bytes, destroy sglist */
|
||||
dma_buf_commit(s, size);
|
||||
|
||||
out:
|
||||
/* declare that we processed everything */
|
||||
s->data_ptr = s->data_end;
|
||||
|
||||
ad->done_first_drq = true;
|
||||
if (pio_fis_i) {
|
||||
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_PSS);
|
||||
}
|
||||
}
|
||||
|
||||
static void ahci_start_dma(IDEDMA *dma, IDEState *s,
|
||||
|
@ -1627,7 +1640,7 @@ static const VMStateDescription vmstate_ahci_device = {
|
|||
VMSTATE_UINT32(port_regs.scr_err, AHCIDevice),
|
||||
VMSTATE_UINT32(port_regs.scr_act, AHCIDevice),
|
||||
VMSTATE_UINT32(port_regs.cmd_issue, AHCIDevice),
|
||||
VMSTATE_BOOL(done_atapi_packet, AHCIDevice),
|
||||
VMSTATE_BOOL(done_first_drq, AHCIDevice),
|
||||
VMSTATE_INT32(busy_slot, AHCIDevice),
|
||||
VMSTATE_BOOL(init_d2h_sent, AHCIDevice),
|
||||
VMSTATE_STRUCT_ARRAY(ncq_tfs, AHCIDevice, AHCI_MAX_CMDS,
|
||||
|
|
|
@ -315,7 +315,7 @@ struct AHCIDevice {
|
|||
QEMUBH *check_bh;
|
||||
uint8_t *lst;
|
||||
uint8_t *res_fis;
|
||||
bool done_atapi_packet;
|
||||
bool done_first_drq;
|
||||
int32_t busy_slot;
|
||||
bool init_d2h_sent;
|
||||
AHCICmdHdr *cur_cmd;
|
||||
|
|
|
@ -651,10 +651,7 @@ void ahci_exec(AHCIQState *ahci, uint8_t port,
|
|||
/* Command creation */
|
||||
if (opts->atapi) {
|
||||
uint16_t bcl = opts->set_bcl ? opts->bcl : ATAPI_SECTOR_SIZE;
|
||||
cmd = ahci_atapi_command_create(op, bcl);
|
||||
if (opts->atapi_dma) {
|
||||
ahci_command_enable_atapi_dma(cmd);
|
||||
}
|
||||
cmd = ahci_atapi_command_create(op, bcl, opts->atapi_dma);
|
||||
} else {
|
||||
cmd = ahci_command_create(op);
|
||||
}
|
||||
|
@ -874,7 +871,6 @@ AHCICommand *ahci_command_create(uint8_t command_name)
|
|||
/* cmd->interrupts |= props->data ? AHCI_PX_IS_DPS : 0; */
|
||||
/* BUG: We expect the DMA Setup interrupt for DMA commands */
|
||||
/* cmd->interrupts |= props->dma ? AHCI_PX_IS_DSS : 0; */
|
||||
cmd->interrupts |= props->pio ? AHCI_PX_IS_PSS : 0;
|
||||
cmd->interrupts |= props->ncq ? AHCI_PX_IS_SDBS : 0;
|
||||
|
||||
command_header_init(cmd);
|
||||
|
@ -883,19 +879,24 @@ AHCICommand *ahci_command_create(uint8_t command_name)
|
|||
return cmd;
|
||||
}
|
||||
|
||||
AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd, uint16_t bcl)
|
||||
AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd, uint16_t bcl, bool dma)
|
||||
{
|
||||
AHCICommand *cmd = ahci_command_create(CMD_PACKET);
|
||||
cmd->atapi_cmd = g_malloc0(16);
|
||||
cmd->atapi_cmd[0] = scsi_cmd;
|
||||
stw_le_p(&cmd->fis.lba_lo[1], bcl);
|
||||
if (dma) {
|
||||
ahci_command_enable_atapi_dma(cmd);
|
||||
} else {
|
||||
cmd->interrupts |= bcl ? AHCI_PX_IS_PSS : 0;
|
||||
}
|
||||
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);
|
||||
AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_TEST_UNIT_READY, 0, false);
|
||||
ahci_command_set_size(cmd, 0);
|
||||
if (!ready) {
|
||||
cmd->interrupts |= AHCI_PX_IS_TFES;
|
||||
|
@ -937,7 +938,7 @@ void ahci_atapi_get_sense(AHCIQState *ahci, uint8_t port,
|
|||
|
||||
void ahci_atapi_eject(AHCIQState *ahci, uint8_t port)
|
||||
{
|
||||
AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT, 0);
|
||||
AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT, 0, false);
|
||||
ahci_command_set_size(cmd, 0);
|
||||
|
||||
cmd->atapi_cmd[4] = 0x02; /* loej = true */
|
||||
|
@ -949,7 +950,7 @@ void ahci_atapi_eject(AHCIQState *ahci, uint8_t port)
|
|||
|
||||
void ahci_atapi_load(AHCIQState *ahci, uint8_t port)
|
||||
{
|
||||
AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT, 0);
|
||||
AHCICommand *cmd = ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT, 0, false);
|
||||
ahci_command_set_size(cmd, 0);
|
||||
|
||||
cmd->atapi_cmd[4] = 0x03; /* loej,start = true */
|
||||
|
@ -1098,6 +1099,12 @@ void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
|
|||
} else if (cmd->props->atapi) {
|
||||
ahci_atapi_set_size(cmd, xbytes);
|
||||
} else {
|
||||
/* For writes, the PIO Setup FIS interrupt only comes from DRQs
|
||||
* after the first.
|
||||
*/
|
||||
if (cmd->props->pio && sect_count > (cmd->props->read ? 0 : 1)) {
|
||||
cmd->interrupts |= AHCI_PX_IS_PSS;
|
||||
}
|
||||
cmd->fis.count = sect_count;
|
||||
}
|
||||
cmd->header.prdtl = size_to_prdtl(cmd->xbytes, cmd->prd_size);
|
||||
|
|
|
@ -622,7 +622,7 @@ void ahci_atapi_load(AHCIQState *ahci, uint8_t port);
|
|||
|
||||
/* Command: Fine-grained lifecycle */
|
||||
AHCICommand *ahci_command_create(uint8_t command_name);
|
||||
AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd, uint16_t bcl);
|
||||
AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd, uint16_t bcl, bool dma);
|
||||
void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port);
|
||||
void ahci_command_issue(AHCIQState *ahci, AHCICommand *cmd);
|
||||
void ahci_command_issue_async(AHCIQState *ahci, AHCICommand *cmd);
|
||||
|
|
Loading…
Reference in New Issue