qemu-sparc queue
-----BEGIN PGP SIGNATURE----- iQFSBAABCgA8FiEEzGIauY6CIA2RXMnEW8LFb64PMh8FAmB0xfgeHG1hcmsuY2F2 ZS1heWxhbmRAaWxhbmRlLmNvLnVrAAoJEFvCxW+uDzIfoYsH/AgSa1ReFBRqa227 cjdD2KRhYDA4HLj2ukaLAEtgbz57RfNyrBtEDkLcgN+lFjBlWB/1QZDTWA844OZb CkBm83jNMIXFpXknXBcMwGDJ7Yrnr1Cjc2AZwifyKswN7ILDtg1qsxu+aEO+L8v6 YysH8aqxxet4tjFLTS1tYFzPzb2W1dMrNR/fLYFYY5rjgW04UNZIHqw66lOkkGBH wyO9dHr371B6b/40a99NBPOlxO/qfQCvIwk2FagmxBBmABRbWp8SIrNSDosFJ2md LdeVukGaIexI5ylIn+bvTuoJcuuTIoqaiUd1KdrHptvt2sH3UUGE6hBRWso9saJL 1wZ3SI4= =O+4q -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mcayland/tags/qemu-sparc-20210412' into staging qemu-sparc queue # gpg: Signature made Mon 12 Apr 2021 23:13:12 BST # gpg: using RSA key CC621AB98E82200D915CC9C45BC2C56FAE0F321F # gpg: issuer "mark.cave-ayland@ilande.co.uk" # gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>" [full] # Primary key fingerprint: CC62 1AB9 8E82 200D 915C C9C4 5BC2 C56F AE0F 321F * remotes/mcayland/tags/qemu-sparc-20210412: tests/qtest: add tests for am53c974 device esp: ensure that do_cmd is set to zero before submitting an ESP select command esp: don't reset async_len directly in esp_select() if cancelling request esp: don't overflow cmdfifo if TC is larger than the cmdfifo size esp: don't overflow cmdfifo in get_cmd() esp: don't underflow cmdfifo in do_cmd() esp: ensure cmdfifo is not empty and current_dev is non-NULL esp: introduce esp_fifo_pop_buf() and use it instead of fifo8_pop_buf() esp: consolidate esp_cmdfifo_pop() into esp_fifo_pop() esp: consolidate esp_cmdfifo_push() into esp_fifo_push() esp: rework write_response() to avoid using the FIFO for DMA transactions esp: always check current_req is not NULL before use in DMA callbacks esp: fix setting of ESPState mig_version_id when launching QEMU with -S option Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1a66dab9dd
|
@ -1772,6 +1772,7 @@ F: include/hw/scsi/*
|
||||||
F: hw/scsi/*
|
F: hw/scsi/*
|
||||||
F: tests/qtest/virtio-scsi-test.c
|
F: tests/qtest/virtio-scsi-test.c
|
||||||
F: tests/qtest/fuzz-virtio-scsi-test.c
|
F: tests/qtest/fuzz-virtio-scsi-test.c
|
||||||
|
F: tests/qtest/am53c974-test.c
|
||||||
T: git https://github.com/bonzini/qemu.git scsi-next
|
T: git https://github.com/bonzini/qemu.git scsi-next
|
||||||
|
|
||||||
SSI
|
SSI
|
||||||
|
|
|
@ -332,6 +332,7 @@ static const VMStateDescription vmstate_esp_pci_scsi = {
|
||||||
.name = "pciespscsi",
|
.name = "pciespscsi",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
|
.pre_save = esp_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_PCI_DEVICE(parent_obj, PCIESPState),
|
VMSTATE_PCI_DEVICE(parent_obj, PCIESPState),
|
||||||
VMSTATE_BUFFER_UNSAFE(dma_regs, PCIESPState, 0, 8 * sizeof(uint32_t)),
|
VMSTATE_BUFFER_UNSAFE(dma_regs, PCIESPState, 0, 8 * sizeof(uint32_t)),
|
||||||
|
|
126
hw/scsi/esp.c
126
hw/scsi/esp.c
|
@ -95,45 +95,44 @@ void esp_request_cancelled(SCSIRequest *req)
|
||||||
scsi_req_unref(s->current_req);
|
scsi_req_unref(s->current_req);
|
||||||
s->current_req = NULL;
|
s->current_req = NULL;
|
||||||
s->current_dev = NULL;
|
s->current_dev = NULL;
|
||||||
|
s->async_len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void esp_fifo_push(ESPState *s, uint8_t val)
|
static void esp_fifo_push(Fifo8 *fifo, uint8_t val)
|
||||||
{
|
{
|
||||||
if (fifo8_num_used(&s->fifo) == ESP_FIFO_SZ) {
|
if (fifo8_num_used(fifo) == fifo->capacity) {
|
||||||
trace_esp_error_fifo_overrun();
|
trace_esp_error_fifo_overrun();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fifo8_push(&s->fifo, val);
|
fifo8_push(fifo, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t esp_fifo_pop(ESPState *s)
|
static uint8_t esp_fifo_pop(Fifo8 *fifo)
|
||||||
{
|
{
|
||||||
if (fifo8_is_empty(&s->fifo)) {
|
if (fifo8_is_empty(fifo)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fifo8_pop(&s->fifo);
|
return fifo8_pop(fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void esp_cmdfifo_push(ESPState *s, uint8_t val)
|
static uint32_t esp_fifo_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen)
|
||||||
{
|
{
|
||||||
if (fifo8_num_used(&s->cmdfifo) == ESP_CMDFIFO_SZ) {
|
const uint8_t *buf;
|
||||||
trace_esp_error_fifo_overrun();
|
uint32_t n;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fifo8_push(&s->cmdfifo, val);
|
if (maxlen == 0) {
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t esp_cmdfifo_pop(ESPState *s)
|
|
||||||
{
|
|
||||||
if (fifo8_is_empty(&s->cmdfifo)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fifo8_pop(&s->cmdfifo);
|
buf = fifo8_pop_buf(fifo, maxlen, &n);
|
||||||
|
if (dest) {
|
||||||
|
memcpy(dest, buf, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t esp_get_tc(ESPState *s)
|
static uint32_t esp_get_tc(ESPState *s)
|
||||||
|
@ -170,9 +169,9 @@ static uint8_t esp_pdma_read(ESPState *s)
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
|
|
||||||
if (s->do_cmd) {
|
if (s->do_cmd) {
|
||||||
val = esp_cmdfifo_pop(s);
|
val = esp_fifo_pop(&s->cmdfifo);
|
||||||
} else {
|
} else {
|
||||||
val = esp_fifo_pop(s);
|
val = esp_fifo_pop(&s->fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
@ -187,9 +186,9 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->do_cmd) {
|
if (s->do_cmd) {
|
||||||
esp_cmdfifo_push(s, val);
|
esp_fifo_push(&s->cmdfifo, val);
|
||||||
} else {
|
} else {
|
||||||
esp_fifo_push(s, val);
|
esp_fifo_push(&s->fifo, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
dmalen--;
|
dmalen--;
|
||||||
|
@ -208,7 +207,6 @@ static int esp_select(ESPState *s)
|
||||||
if (s->current_req) {
|
if (s->current_req) {
|
||||||
/* Started a new command before the old one finished. Cancel it. */
|
/* Started a new command before the old one finished. Cancel it. */
|
||||||
scsi_req_cancel(s->current_req);
|
scsi_req_cancel(s->current_req);
|
||||||
s->async_len = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
|
s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
|
||||||
|
@ -245,6 +243,7 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
|
||||||
}
|
}
|
||||||
if (s->dma_memory_read) {
|
if (s->dma_memory_read) {
|
||||||
s->dma_memory_read(s->dma_opaque, buf, dmalen);
|
s->dma_memory_read(s->dma_opaque, buf, dmalen);
|
||||||
|
dmalen = MIN(fifo8_num_free(&s->cmdfifo), dmalen);
|
||||||
fifo8_push_all(&s->cmdfifo, buf, dmalen);
|
fifo8_push_all(&s->cmdfifo, buf, dmalen);
|
||||||
} else {
|
} else {
|
||||||
if (esp_select(s) < 0) {
|
if (esp_select(s) < 0) {
|
||||||
|
@ -260,11 +259,12 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
|
||||||
if (dmalen == 0) {
|
if (dmalen == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(buf, fifo8_pop_buf(&s->fifo, dmalen, &n), dmalen);
|
n = esp_fifo_pop_buf(&s->fifo, buf, dmalen);
|
||||||
if (dmalen >= 3) {
|
if (n >= 3) {
|
||||||
buf[0] = buf[2] >> 5;
|
buf[0] = buf[2] >> 5;
|
||||||
}
|
}
|
||||||
fifo8_push_all(&s->cmdfifo, buf, dmalen);
|
n = MIN(fifo8_num_free(&s->cmdfifo), n);
|
||||||
|
fifo8_push_all(&s->cmdfifo, buf, n);
|
||||||
}
|
}
|
||||||
trace_esp_get_cmd(dmalen, target);
|
trace_esp_get_cmd(dmalen, target);
|
||||||
|
|
||||||
|
@ -277,16 +277,19 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
|
||||||
|
|
||||||
static void do_busid_cmd(ESPState *s, uint8_t busid)
|
static void do_busid_cmd(ESPState *s, uint8_t busid)
|
||||||
{
|
{
|
||||||
uint32_t n, cmdlen;
|
uint32_t cmdlen;
|
||||||
int32_t datalen;
|
int32_t datalen;
|
||||||
int lun;
|
int lun;
|
||||||
SCSIDevice *current_lun;
|
SCSIDevice *current_lun;
|
||||||
uint8_t *buf;
|
uint8_t buf[ESP_CMDFIFO_SZ];
|
||||||
|
|
||||||
trace_esp_do_busid_cmd(busid);
|
trace_esp_do_busid_cmd(busid);
|
||||||
lun = busid & 7;
|
lun = busid & 7;
|
||||||
cmdlen = fifo8_num_used(&s->cmdfifo);
|
cmdlen = fifo8_num_used(&s->cmdfifo);
|
||||||
buf = (uint8_t *)fifo8_pop_buf(&s->cmdfifo, cmdlen, &n);
|
if (!cmdlen || !s->current_dev) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen);
|
||||||
|
|
||||||
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
|
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
|
||||||
s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
|
s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
|
||||||
|
@ -318,14 +321,15 @@ static void do_busid_cmd(ESPState *s, uint8_t busid)
|
||||||
|
|
||||||
static void do_cmd(ESPState *s)
|
static void do_cmd(ESPState *s)
|
||||||
{
|
{
|
||||||
uint8_t busid = fifo8_pop(&s->cmdfifo);
|
uint8_t busid = esp_fifo_pop(&s->cmdfifo);
|
||||||
uint32_t n;
|
int len;
|
||||||
|
|
||||||
s->cmdfifo_cdb_offset--;
|
s->cmdfifo_cdb_offset--;
|
||||||
|
|
||||||
/* Ignore extended messages for now */
|
/* Ignore extended messages for now */
|
||||||
if (s->cmdfifo_cdb_offset) {
|
if (s->cmdfifo_cdb_offset) {
|
||||||
fifo8_pop_buf(&s->cmdfifo, s->cmdfifo_cdb_offset, &n);
|
len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo));
|
||||||
|
esp_fifo_pop_buf(&s->cmdfifo, NULL, len);
|
||||||
s->cmdfifo_cdb_offset = 0;
|
s->cmdfifo_cdb_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +357,7 @@ static void handle_satn(ESPState *s)
|
||||||
cmdlen = get_cmd(s, ESP_CMDFIFO_SZ);
|
cmdlen = get_cmd(s, ESP_CMDFIFO_SZ);
|
||||||
if (cmdlen > 0) {
|
if (cmdlen > 0) {
|
||||||
s->cmdfifo_cdb_offset = 1;
|
s->cmdfifo_cdb_offset = 1;
|
||||||
|
s->do_cmd = 0;
|
||||||
do_cmd(s);
|
do_cmd(s);
|
||||||
} else if (cmdlen == 0) {
|
} else if (cmdlen == 0) {
|
||||||
s->do_cmd = 1;
|
s->do_cmd = 1;
|
||||||
|
@ -386,6 +391,7 @@ static void handle_s_without_atn(ESPState *s)
|
||||||
cmdlen = get_cmd(s, ESP_CMDFIFO_SZ);
|
cmdlen = get_cmd(s, ESP_CMDFIFO_SZ);
|
||||||
if (cmdlen > 0) {
|
if (cmdlen > 0) {
|
||||||
s->cmdfifo_cdb_offset = 0;
|
s->cmdfifo_cdb_offset = 0;
|
||||||
|
s->do_cmd = 0;
|
||||||
do_busid_cmd(s, 0);
|
do_busid_cmd(s, 0);
|
||||||
} else if (cmdlen == 0) {
|
} else if (cmdlen == 0) {
|
||||||
s->do_cmd = 1;
|
s->do_cmd = 1;
|
||||||
|
@ -445,18 +451,16 @@ static void write_response_pdma_cb(ESPState *s)
|
||||||
|
|
||||||
static void write_response(ESPState *s)
|
static void write_response(ESPState *s)
|
||||||
{
|
{
|
||||||
uint32_t n;
|
uint8_t buf[2];
|
||||||
|
|
||||||
trace_esp_write_response(s->status);
|
trace_esp_write_response(s->status);
|
||||||
|
|
||||||
fifo8_reset(&s->fifo);
|
buf[0] = s->status;
|
||||||
esp_fifo_push(s, s->status);
|
buf[1] = 0;
|
||||||
esp_fifo_push(s, 0);
|
|
||||||
|
|
||||||
if (s->dma) {
|
if (s->dma) {
|
||||||
if (s->dma_memory_write) {
|
if (s->dma_memory_write) {
|
||||||
s->dma_memory_write(s->dma_opaque,
|
s->dma_memory_write(s->dma_opaque, buf, 2);
|
||||||
(uint8_t *)fifo8_pop_buf(&s->fifo, 2, &n), 2);
|
|
||||||
s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
|
s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
|
||||||
s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
|
s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
|
||||||
s->rregs[ESP_RSEQ] = SEQ_CD;
|
s->rregs[ESP_RSEQ] = SEQ_CD;
|
||||||
|
@ -466,7 +470,8 @@ static void write_response(ESPState *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s->ti_size = 2;
|
fifo8_reset(&s->fifo);
|
||||||
|
fifo8_push_all(&s->fifo, buf, 2);
|
||||||
s->rregs[ESP_RFLAGS] = 2;
|
s->rregs[ESP_RFLAGS] = 2;
|
||||||
}
|
}
|
||||||
esp_raise_irq(s);
|
esp_raise_irq(s);
|
||||||
|
@ -496,11 +501,15 @@ static void do_dma_pdma_cb(ESPState *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!s->current_req) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (to_device) {
|
if (to_device) {
|
||||||
/* Copy FIFO data to device */
|
/* Copy FIFO data to device */
|
||||||
len = MIN(s->async_len, ESP_FIFO_SZ);
|
len = MIN(s->async_len, ESP_FIFO_SZ);
|
||||||
len = MIN(len, fifo8_num_used(&s->fifo));
|
len = MIN(len, fifo8_num_used(&s->fifo));
|
||||||
memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len);
|
n = esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
|
||||||
s->async_buf += n;
|
s->async_buf += n;
|
||||||
s->async_len -= n;
|
s->async_len -= n;
|
||||||
s->ti_size += n;
|
s->ti_size += n;
|
||||||
|
@ -508,7 +517,7 @@ static void do_dma_pdma_cb(ESPState *s)
|
||||||
if (n < len) {
|
if (n < len) {
|
||||||
/* Unaligned accesses can cause FIFO wraparound */
|
/* Unaligned accesses can cause FIFO wraparound */
|
||||||
len = len - n;
|
len = len - n;
|
||||||
memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len);
|
n = esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
|
||||||
s->async_buf += n;
|
s->async_buf += n;
|
||||||
s->async_len -= n;
|
s->async_len -= n;
|
||||||
s->ti_size += n;
|
s->ti_size += n;
|
||||||
|
@ -527,11 +536,9 @@ static void do_dma_pdma_cb(ESPState *s)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (s->async_len == 0) {
|
if (s->async_len == 0) {
|
||||||
if (s->current_req) {
|
/* Defer until the scsi layer has completed */
|
||||||
/* Defer until the scsi layer has completed */
|
scsi_req_continue(s->current_req);
|
||||||
scsi_req_continue(s->current_req);
|
s->data_in_ready = false;
|
||||||
s->data_in_ready = false;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,6 +580,7 @@ static void esp_do_dma(ESPState *s)
|
||||||
cmdlen = fifo8_num_used(&s->cmdfifo);
|
cmdlen = fifo8_num_used(&s->cmdfifo);
|
||||||
trace_esp_do_dma(cmdlen, len);
|
trace_esp_do_dma(cmdlen, len);
|
||||||
if (s->dma_memory_read) {
|
if (s->dma_memory_read) {
|
||||||
|
len = MIN(len, fifo8_num_free(&s->cmdfifo));
|
||||||
s->dma_memory_read(s->dma_opaque, buf, len);
|
s->dma_memory_read(s->dma_opaque, buf, len);
|
||||||
fifo8_push_all(&s->cmdfifo, buf, len);
|
fifo8_push_all(&s->cmdfifo, buf, len);
|
||||||
} else {
|
} else {
|
||||||
|
@ -604,6 +612,9 @@ static void esp_do_dma(ESPState *s)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!s->current_req) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (s->async_len == 0) {
|
if (s->async_len == 0) {
|
||||||
/* Defer until data is available. */
|
/* Defer until data is available. */
|
||||||
return;
|
return;
|
||||||
|
@ -641,7 +652,7 @@ static void esp_do_dma(ESPState *s)
|
||||||
*/
|
*/
|
||||||
if (len < esp_get_tc(s) && esp_get_tc(s) <= ESP_FIFO_SZ) {
|
if (len < esp_get_tc(s) && esp_get_tc(s) <= ESP_FIFO_SZ) {
|
||||||
while (fifo8_num_used(&s->fifo) < ESP_FIFO_SZ) {
|
while (fifo8_num_used(&s->fifo) < ESP_FIFO_SZ) {
|
||||||
esp_fifo_push(s, 0);
|
esp_fifo_push(&s->fifo, 0);
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,7 +694,7 @@ static void esp_do_dma(ESPState *s)
|
||||||
static void esp_do_nodma(ESPState *s)
|
static void esp_do_nodma(ESPState *s)
|
||||||
{
|
{
|
||||||
int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
|
int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
|
||||||
uint32_t cmdlen, n;
|
uint32_t cmdlen;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (s->do_cmd) {
|
if (s->do_cmd) {
|
||||||
|
@ -713,6 +724,10 @@ static void esp_do_nodma(ESPState *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!s->current_req) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (s->async_len == 0) {
|
if (s->async_len == 0) {
|
||||||
/* Defer until data is available. */
|
/* Defer until data is available. */
|
||||||
return;
|
return;
|
||||||
|
@ -720,7 +735,7 @@ static void esp_do_nodma(ESPState *s)
|
||||||
|
|
||||||
if (to_device) {
|
if (to_device) {
|
||||||
len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ);
|
len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ);
|
||||||
memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len);
|
esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
|
||||||
s->async_buf += len;
|
s->async_buf += len;
|
||||||
s->async_len -= len;
|
s->async_len -= len;
|
||||||
s->ti_size += len;
|
s->ti_size += len;
|
||||||
|
@ -890,7 +905,7 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
|
||||||
qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
|
qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
|
||||||
s->rregs[ESP_FIFO] = 0;
|
s->rregs[ESP_FIFO] = 0;
|
||||||
} else {
|
} else {
|
||||||
s->rregs[ESP_FIFO] = esp_fifo_pop(s);
|
s->rregs[ESP_FIFO] = esp_fifo_pop(&s->fifo);
|
||||||
}
|
}
|
||||||
val = s->rregs[ESP_FIFO];
|
val = s->rregs[ESP_FIFO];
|
||||||
break;
|
break;
|
||||||
|
@ -939,9 +954,9 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||||
break;
|
break;
|
||||||
case ESP_FIFO:
|
case ESP_FIFO:
|
||||||
if (s->do_cmd) {
|
if (s->do_cmd) {
|
||||||
esp_cmdfifo_push(s, val);
|
esp_fifo_push(&s->cmdfifo, val);
|
||||||
} else {
|
} else {
|
||||||
esp_fifo_push(s, val);
|
esp_fifo_push(&s->fifo, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non-DMA transfers raise an interrupt after every byte */
|
/* Non-DMA transfers raise an interrupt after every byte */
|
||||||
|
@ -1076,9 +1091,10 @@ static bool esp_is_version_5(void *opaque, int version_id)
|
||||||
return version_id == 5;
|
return version_id == 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int esp_pre_save(void *opaque)
|
int esp_pre_save(void *opaque)
|
||||||
{
|
{
|
||||||
ESPState *s = ESP(opaque);
|
ESPState *s = ESP(object_resolve_path_component(
|
||||||
|
OBJECT(opaque), "esp"));
|
||||||
|
|
||||||
s->mig_version_id = vmstate_esp.version_id;
|
s->mig_version_id = vmstate_esp.version_id;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1114,7 +1130,6 @@ const VMStateDescription vmstate_esp = {
|
||||||
.name = "esp",
|
.name = "esp",
|
||||||
.version_id = 5,
|
.version_id = 5,
|
||||||
.minimum_version_id = 3,
|
.minimum_version_id = 3,
|
||||||
.pre_save = esp_pre_save,
|
|
||||||
.post_load = esp_post_load,
|
.post_load = esp_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_BUFFER(rregs, ESPState),
|
VMSTATE_BUFFER(rregs, ESPState),
|
||||||
|
@ -1304,6 +1319,7 @@ static const VMStateDescription vmstate_sysbus_esp_scsi = {
|
||||||
.name = "sysbusespscsi",
|
.name = "sysbusespscsi",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
|
.pre_save = esp_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2),
|
VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2),
|
||||||
VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
|
VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
|
||||||
|
|
|
@ -157,5 +157,6 @@ void esp_hard_reset(ESPState *s);
|
||||||
uint64_t esp_reg_read(ESPState *s, uint32_t saddr);
|
uint64_t esp_reg_read(ESPState *s, uint32_t saddr);
|
||||||
void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val);
|
void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val);
|
||||||
extern const VMStateDescription vmstate_esp;
|
extern const VMStateDescription vmstate_esp;
|
||||||
|
int esp_pre_save(void *opaque);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
218
tests/qtest/am53c974-test.c
Normal file
218
tests/qtest/am53c974-test.c
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
* QTest testcase for am53c974
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* later. See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
#include "libqos/libqtest.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void test_cmdfifo_underflow_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi "
|
||||||
|
"-device scsi-hd,drive=disk0 -drive "
|
||||||
|
"id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x01);
|
||||||
|
qtest_outl(s, 0xcf8, 0x8000100e);
|
||||||
|
qtest_outl(s, 0xcfc, 0x8a000000);
|
||||||
|
qtest_outl(s, 0x8a09, 0x42000000);
|
||||||
|
qtest_outl(s, 0x8a0d, 0x00);
|
||||||
|
qtest_outl(s, 0x8a0b, 0x1000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reported as crash_1548bd10e7 */
|
||||||
|
static void test_cmdfifo_underflow2_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi -device scsi-hd,drive=disk0 "
|
||||||
|
"-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001010);
|
||||||
|
qtest_outl(s, 0xcfc, 0xc000);
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x01);
|
||||||
|
qtest_outw(s, 0xc00c, 0x41);
|
||||||
|
qtest_outw(s, 0xc00a, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00c, 0x43);
|
||||||
|
qtest_outw(s, 0xc00b, 0x00);
|
||||||
|
qtest_outw(s, 0xc00b, 0x00);
|
||||||
|
qtest_outw(s, 0xc00c, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00a, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00c, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00a, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00c, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00a, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00c, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outl(s, 0xc006, 0x00);
|
||||||
|
qtest_outl(s, 0xc00b, 0x00);
|
||||||
|
qtest_outw(s, 0xc00b, 0x0800);
|
||||||
|
qtest_outw(s, 0xc00b, 0x00);
|
||||||
|
qtest_outw(s, 0xc00b, 0x00);
|
||||||
|
qtest_outl(s, 0xc006, 0x00);
|
||||||
|
qtest_outl(s, 0xc00b, 0x00);
|
||||||
|
qtest_outw(s, 0xc00b, 0x0800);
|
||||||
|
qtest_outw(s, 0xc00b, 0x00);
|
||||||
|
qtest_outw(s, 0xc00b, 0x4100);
|
||||||
|
qtest_outw(s, 0xc00a, 0x00);
|
||||||
|
qtest_outl(s, 0xc00a, 0x100000);
|
||||||
|
qtest_outl(s, 0xc00a, 0x00);
|
||||||
|
qtest_outw(s, 0xc00c, 0x43);
|
||||||
|
qtest_outl(s, 0xc00a, 0x100000);
|
||||||
|
qtest_outl(s, 0xc00a, 0x100000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_cmdfifo_overflow_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi "
|
||||||
|
"-device scsi-hd,drive=disk0 -drive "
|
||||||
|
"id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x01);
|
||||||
|
qtest_outl(s, 0xcf8, 0x8000100e);
|
||||||
|
qtest_outl(s, 0xcfc, 0x0e000000);
|
||||||
|
qtest_outl(s, 0xe40, 0x03);
|
||||||
|
qtest_outl(s, 0xe0b, 0x4100);
|
||||||
|
qtest_outl(s, 0xe0b, 0x9000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reported as crash_530ff2e211 */
|
||||||
|
static void test_cmdfifo_overflow2_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi -device scsi-hd,drive=disk0 "
|
||||||
|
"-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001010);
|
||||||
|
qtest_outl(s, 0xcfc, 0xc000);
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x01);
|
||||||
|
qtest_outl(s, 0xc00b, 0x4100);
|
||||||
|
qtest_outw(s, 0xc00b, 0xc200);
|
||||||
|
qtest_outl(s, 0xc03f, 0x0300);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reported as crash_0900379669 */
|
||||||
|
static void test_fifo_pop_buf(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi -device scsi-hd,drive=disk0 "
|
||||||
|
"-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001010);
|
||||||
|
qtest_outl(s, 0xcfc, 0xc000);
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x01);
|
||||||
|
qtest_outb(s, 0xc000, 0x4);
|
||||||
|
qtest_outb(s, 0xc008, 0xa0);
|
||||||
|
qtest_outl(s, 0xc03f, 0x0300);
|
||||||
|
qtest_outl(s, 0xc00b, 0xc300);
|
||||||
|
qtest_outw(s, 0xc00b, 0x9000);
|
||||||
|
qtest_outl(s, 0xc00b, 0xc300);
|
||||||
|
qtest_outl(s, 0xc00b, 0xc300);
|
||||||
|
qtest_outl(s, 0xc00b, 0xc300);
|
||||||
|
qtest_outw(s, 0xc00b, 0x9000);
|
||||||
|
qtest_outw(s, 0xc00b, 0x1000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_target_selected_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi "
|
||||||
|
"-device scsi-hd,drive=disk0 -drive "
|
||||||
|
"id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001001);
|
||||||
|
qtest_outl(s, 0xcfc, 0x01000000);
|
||||||
|
qtest_outl(s, 0xcf8, 0x8000100e);
|
||||||
|
qtest_outl(s, 0xcfc, 0xef800000);
|
||||||
|
qtest_outl(s, 0xef8b, 0x4100);
|
||||||
|
qtest_outw(s, 0xef80, 0x01);
|
||||||
|
qtest_outl(s, 0xefc0, 0x03);
|
||||||
|
qtest_outl(s, 0xef8b, 0xc100);
|
||||||
|
qtest_outl(s, 0xef8b, 0x9000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_fifo_underflow_on_write_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi "
|
||||||
|
"-device scsi-hd,drive=disk0 -drive "
|
||||||
|
"id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001010);
|
||||||
|
qtest_outl(s, 0xcfc, 0xc000);
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x01);
|
||||||
|
qtest_outl(s, 0xc008, 0x0a);
|
||||||
|
qtest_outl(s, 0xc009, 0x41000000);
|
||||||
|
qtest_outl(s, 0xc009, 0x41000000);
|
||||||
|
qtest_outl(s, 0xc00b, 0x1000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_cancelled_request_ok(void)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init(
|
||||||
|
"-device am53c974,id=scsi "
|
||||||
|
"-device scsi-hd,drive=disk0 -drive "
|
||||||
|
"id=disk0,if=none,file=null-co://,format=raw -nodefaults");
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001010);
|
||||||
|
qtest_outl(s, 0xcfc, 0xc000);
|
||||||
|
qtest_outl(s, 0xcf8, 0x80001004);
|
||||||
|
qtest_outw(s, 0xcfc, 0x05);
|
||||||
|
qtest_outb(s, 0xc046, 0x02);
|
||||||
|
qtest_outl(s, 0xc00b, 0xc100);
|
||||||
|
qtest_outl(s, 0xc040, 0x03);
|
||||||
|
qtest_outl(s, 0xc040, 0x03);
|
||||||
|
qtest_bufwrite(s, 0x0, "\x41", 0x1);
|
||||||
|
qtest_outl(s, 0xc00b, 0xc100);
|
||||||
|
qtest_outw(s, 0xc040, 0x02);
|
||||||
|
qtest_outw(s, 0xc040, 0x81);
|
||||||
|
qtest_outl(s, 0xc00b, 0x9000);
|
||||||
|
qtest_quit(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *arch = qtest_get_arch();
|
||||||
|
|
||||||
|
g_test_init(&argc, &argv, NULL);
|
||||||
|
|
||||||
|
if (strcmp(arch, "i386") == 0) {
|
||||||
|
qtest_add_func("am53c974/test_cmdfifo_underflow_ok",
|
||||||
|
test_cmdfifo_underflow_ok);
|
||||||
|
qtest_add_func("am53c974/test_cmdfifo_underflow2_ok",
|
||||||
|
test_cmdfifo_underflow2_ok);
|
||||||
|
qtest_add_func("am53c974/test_cmdfifo_overflow_ok",
|
||||||
|
test_cmdfifo_overflow_ok);
|
||||||
|
qtest_add_func("am53c974/test_cmdfifo_overflow2_ok",
|
||||||
|
test_cmdfifo_overflow2_ok);
|
||||||
|
qtest_add_func("am53c974/test_fifo_pop_buf",
|
||||||
|
test_fifo_pop_buf);
|
||||||
|
qtest_add_func("am53c974/test_target_selected_ok",
|
||||||
|
test_target_selected_ok);
|
||||||
|
qtest_add_func("am53c974/test_fifo_underflow_on_write_ok",
|
||||||
|
test_fifo_underflow_on_write_ok);
|
||||||
|
qtest_add_func("am53c974/test_cancelled_request_ok",
|
||||||
|
test_cancelled_request_ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
|
@ -65,6 +65,7 @@ qtests_i386 = \
|
||||||
(config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-swtpm-test'] : []) + \
|
(config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-swtpm-test'] : []) + \
|
||||||
(config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : []) + \
|
(config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : []) + \
|
||||||
(config_all_devices.has_key('CONFIG_E1000E_PCI_EXPRESS') ? ['fuzz-e1000e-test'] : []) + \
|
(config_all_devices.has_key('CONFIG_E1000E_PCI_EXPRESS') ? ['fuzz-e1000e-test'] : []) + \
|
||||||
|
(config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \
|
||||||
qtests_pci + \
|
qtests_pci + \
|
||||||
['fdc-test',
|
['fdc-test',
|
||||||
'ide-test',
|
'ide-test',
|
||||||
|
|
Loading…
Reference in a new issue