Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' i…
Browse files Browse the repository at this point in the history
…nto staging

# gpg: Signature made Sat Jul  4 07:06:08 2015 BST using RSA key ID AAFC390E
# gpg: Good signature from "John Snow (John Huston) <[email protected]>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# 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: (35 commits)
  ahci: fix sdb fis semantics
  qtest/ahci: halted ncq migration test
  ahci: Do not map cmd_fis to generate response
  ahci: ncq migration
  ahci: add get_cmd_header helper
  ahci: add cmd header to ncq transfer state
  qtest/ahci: halted NCQ test
  ahci: correct ncq sector count
  ahci: correct types in NCQTransferState
  ahci: add rwerror=stop support for ncq
  ahci: factor ncq_finish out of ncq_cb
  ahci: refactor process_ncq_command
  ahci: assert is_ncq for process_ncq
  ahci: stash ncq command
  ide: add limit to .prepare_buf()
  qtest/ahci: ncq migration test
  qtest/ahci: simple ncq data test
  libqos/ahci: Force all NCQ commands to be LBA48
  libqos/ahci: set the NCQ tag on command_commit
  libqos/ahci: adjust expected NCQ interrupts
  ...

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Jul 5, 2015
2 parents 63a9294 + 7c649ac commit f50a164
Show file tree
Hide file tree
Showing 9 changed files with 635 additions and 268 deletions.
437 changes: 286 additions & 151 deletions hw/ide/ahci.c

Large diffs are not rendered by default.

47 changes: 33 additions & 14 deletions hw/ide/ahci.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@
#define RECEIVE_FPDMA_QUEUED 0x65
#define SEND_FPDMA_QUEUED 0x64

#define NCQ_FIS_FUA_MASK 0x80
#define NCQ_FIS_RARC_MASK 0x01

#define RES_FIS_DSFIS 0x00
#define RES_FIS_PSFIS 0x20
#define RES_FIS_RFIS 0x40
Expand Down Expand Up @@ -233,7 +236,8 @@ typedef struct AHCIPortRegs {
} AHCIPortRegs;

typedef struct AHCICmdHdr {
uint32_t opts;
uint16_t opts;
uint16_t prdtl;
uint32_t status;
uint64_t tbl_addr;
uint32_t reserved[4];
Expand All @@ -250,13 +254,16 @@ typedef struct AHCIDevice AHCIDevice;
typedef struct NCQTransferState {
AHCIDevice *drive;
BlockAIOCB *aiocb;
AHCICmdHdr *cmdh;
QEMUSGList sglist;
BlockAcctCookie acct;
uint16_t sector_count;
uint32_t sector_count;
uint64_t lba;
uint8_t tag;
int slot;
int used;
uint8_t cmd;
uint8_t slot;
bool used;
bool halt;
} NCQTransferState;

struct AHCIDevice {
Expand Down Expand Up @@ -312,27 +319,39 @@ extern const VMStateDescription vmstate_ahci;
.offset = vmstate_offset_value(_state, _field, AHCIState), \
}

/**
* NCQFrame is the same as a Register H2D FIS (described in SATA 3.2),
* but some fields have been re-mapped and re-purposed, as seen in
* SATA 3.2 section 13.6.4.1 ("READ FPDMA QUEUED")
*
* cmd_fis[3], feature 7:0, becomes sector count 7:0.
* cmd_fis[7], device 7:0, uses bit 7 as the Force Unit Access bit.
* cmd_fis[11], feature 15:8, becomes sector count 15:8.
* cmd_fis[12], count 7:0, becomes the NCQ TAG (7:3) and RARC bit (0)
* cmd_fis[13], count 15:8, becomes the priority value (7:6)
* bytes 16-19 become an le32 "auxiliary" field.
*/
typedef struct NCQFrame {
uint8_t fis_type;
uint8_t c;
uint8_t command;
uint8_t sector_count_low;
uint8_t sector_count_low; /* (feature 7:0) */
uint8_t lba0;
uint8_t lba1;
uint8_t lba2;
uint8_t fua;
uint8_t fua; /* (device 7:0) */
uint8_t lba3;
uint8_t lba4;
uint8_t lba5;
uint8_t sector_count_high;
uint8_t tag;
uint8_t reserved5;
uint8_t reserved6;
uint8_t sector_count_high; /* (feature 15:8) */
uint8_t tag; /* (count 0:7) */
uint8_t prio; /* (count 15:8) */
uint8_t icc;
uint8_t control;
uint8_t reserved7;
uint8_t reserved8;
uint8_t reserved9;
uint8_t reserved10;
uint8_t aux0;
uint8_t aux1;
uint8_t aux2;
uint8_t aux3;
} QEMU_PACKED NCQFrame;

typedef struct SDBFIS {
Expand Down
15 changes: 11 additions & 4 deletions hw/ide/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,8 @@ static void ide_dma_cb(void *opaque, int ret)

sector_num = ide_get_sector(s);
if (n > 0) {
assert(s->io_buffer_size == s->sg.size);
dma_buf_commit(s, s->io_buffer_size);
assert(n * 512 == s->sg.size);
dma_buf_commit(s, s->sg.size);
sector_num += n;
ide_set_sector(s, sector_num);
s->nsector -= n;
Expand All @@ -734,7 +734,7 @@ static void ide_dma_cb(void *opaque, int ret)
n = s->nsector;
s->io_buffer_index = 0;
s->io_buffer_size = n * 512;
if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) < 512) {
if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) {
/* The PRDs were too short. Reset the Active bit, but don't raise an
* interrupt. */
s->status = READY_STAT | SEEK_STAT;
Expand Down Expand Up @@ -2326,7 +2326,7 @@ static void ide_nop(IDEDMA *dma)
{
}

static int32_t ide_nop_int32(IDEDMA *dma, int x)
static int32_t ide_nop_int32(IDEDMA *dma, int32_t l)
{
return 0;
}
Expand Down Expand Up @@ -2371,6 +2371,13 @@ static void ide_restart_bh(void *opaque)
* called function can set a new error status. */
bus->error_status = 0;

/* The HBA has generically asked to be kicked on retry */
if (error_status & IDE_RETRY_HBA) {
if (s->bus->dma->ops->restart) {
s->bus->dma->ops->restart(s->bus->dma);
}
}

if (error_status & IDE_RETRY_DMA) {
if (error_status & IDE_RETRY_TRIM) {
ide_restart_dma(s, IDE_DMA_TRIM);
Expand Down
4 changes: 3 additions & 1 deletion hw/ide/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ typedef void EndTransferFunc(IDEState *);
typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *);
typedef void DMAVoidFunc(IDEDMA *);
typedef int DMAIntFunc(IDEDMA *, int);
typedef int32_t DMAInt32Func(IDEDMA *, int);
typedef int32_t DMAInt32Func(IDEDMA *, int32_t len);
typedef void DMAu32Func(IDEDMA *, uint32_t);
typedef void DMAStopFunc(IDEDMA *, bool);
typedef void DMARestartFunc(void *, int, RunState);
Expand Down Expand Up @@ -436,6 +436,7 @@ struct IDEDMAOps {
DMAInt32Func *prepare_buf;
DMAu32Func *commit_buf;
DMAIntFunc *rw_buf;
DMAVoidFunc *restart;
DMAVoidFunc *restart_dma;
DMAStopFunc *set_inactive;
DMAVoidFunc *cmd_done;
Expand Down Expand Up @@ -499,6 +500,7 @@ struct IDEDevice {
#define IDE_RETRY_READ 0x20
#define IDE_RETRY_FLUSH 0x40
#define IDE_RETRY_TRIM 0x80
#define IDE_RETRY_HBA 0x100

static inline IDEState *idebus_active_if(IDEBus *bus)
{
Expand Down
2 changes: 1 addition & 1 deletion hw/ide/macio.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ static int ide_nop_int(IDEDMA *dma, int x)
return 0;
}

static int32_t ide_nop_int32(IDEDMA *dma, int x)
static int32_t ide_nop_int32(IDEDMA *dma, int32_t l)
{
return 0;
}
Expand Down
21 changes: 16 additions & 5 deletions hw/ide/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
}

/**
* Return the number of bytes successfully prepared.
* -1 on error.
* Prepare an sglist based on available PRDs.
* @limit: How many bytes to prepare total.
*
* Returns the number of bytes prepared, -1 on error.
* IDEState.io_buffer_size will contain the number of bytes described
* by the PRDs, whether or not we added them to the sglist.
*/
static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write)
static int32_t bmdma_prepare_buf(IDEDMA *dma, int32_t limit)
{
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
IDEState *s = bmdma_active_if(bm);
Expand All @@ -75,7 +79,7 @@ static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write)
/* end of table (with a fail safe of one page) */
if (bm->cur_prd_last ||
(bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) {
return s->io_buffer_size;
return s->sg.size;
}
pci_dma_read(pci_dev, bm->cur_addr, &prd, 8);
bm->cur_addr += 8;
Expand All @@ -90,7 +94,14 @@ static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write)
}
l = bm->cur_prd_len;
if (l > 0) {
qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
uint64_t sg_len;

/* Don't add extra bytes to the SGList; consume any remaining
* PRDs from the guest, but ignore them. */
sg_len = MIN(limit - s->sg.size, bm->cur_prd_len);
if (sg_len) {
qemu_sglist_add(&s->sg, bm->cur_prd_addr, sg_len);
}

/* Note: We limit the max transfer to be 2GiB.
* This should accommodate the largest ATA transaction
Expand Down
Loading

0 comments on commit f50a164

Please sign in to comment.