lsi53c895a: convert to trace-events

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Message-Id: <20180917053229.4853-1-mark.cave-ayland@ilande.co.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Mark Cave-Ayland 2018-09-17 06:32:29 +01:00 committed by Paolo Bonzini
parent 51f43d5792
commit c921370b22
2 changed files with 165 additions and 111 deletions

View File

@ -20,20 +20,7 @@
#include "hw/scsi/scsi.h" #include "hw/scsi/scsi.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "trace.h"
//#define DEBUG_LSI
//#define DEBUG_LSI_REG
#ifdef DEBUG_LSI
#define DPRINTF(fmt, ...) \
do { printf("lsi_scsi: " fmt , ## __VA_ARGS__); } while (0)
#define BADF(fmt, ...) \
do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
#else
#define DPRINTF(fmt, ...) do {} while(0)
#define BADF(fmt, ...) \
do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
#endif
static const char *names[] = { static const char *names[] = {
"SCNTL0", "SCNTL1", "SCNTL2", "SCNTL3", "SCID", "SXFER", "SDID", "GPREG", "SCNTL0", "SCNTL1", "SCNTL2", "SCNTL3", "SCID", "SXFER", "SDID", "GPREG",
@ -313,7 +300,7 @@ static inline int lsi_irq_on_rsl(LSIState *s)
static void lsi_soft_reset(LSIState *s) static void lsi_soft_reset(LSIState *s)
{ {
DPRINTF("Reset\n"); trace_lsi_reset();
s->carry = 0; s->carry = 0;
s->msg_action = 0; s->msg_action = 0;
@ -484,15 +471,13 @@ static void lsi_update_irq(LSIState *s)
level = 1; level = 1;
if (level != last_level) { if (level != last_level) {
DPRINTF("Update IRQ level %d dstat %02x sist %02x%02x\n", trace_lsi_update_irq(level, s->dstat, s->sist1, s->sist0);
level, s->dstat, s->sist1, s->sist0);
last_level = level; last_level = level;
} }
lsi_set_irq(s, level); lsi_set_irq(s, level);
if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) { if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
DPRINTF("Handled IRQs & disconnected, looking for pending " trace_lsi_update_irq_disconnected();
"processes\n");
QTAILQ_FOREACH(p, &s->queue, next) { QTAILQ_FOREACH(p, &s->queue, next) {
if (p->pending) { if (p->pending) {
lsi_reselect(s, p); lsi_reselect(s, p);
@ -508,8 +493,7 @@ static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1)
uint32_t mask0; uint32_t mask0;
uint32_t mask1; uint32_t mask1;
DPRINTF("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", trace_lsi_script_scsi_interrupt(stat1, stat0, s->sist1, s->sist0);
stat1, stat0, s->sist1, s->sist0);
s->sist0 |= stat0; s->sist0 |= stat0;
s->sist1 |= stat1; s->sist1 |= stat1;
/* Stop processor on fatal or unmasked interrupt. As a special hack /* Stop processor on fatal or unmasked interrupt. As a special hack
@ -527,7 +511,7 @@ static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1)
/* Stop SCRIPTS execution and raise a DMA interrupt. */ /* Stop SCRIPTS execution and raise a DMA interrupt. */
static void lsi_script_dma_interrupt(LSIState *s, int stat) static void lsi_script_dma_interrupt(LSIState *s, int stat)
{ {
DPRINTF("DMA Interrupt 0x%x prev 0x%x\n", stat, s->dstat); trace_lsi_script_dma_interrupt(stat, s->dstat);
s->dstat |= stat; s->dstat |= stat;
lsi_update_irq(s); lsi_update_irq(s);
lsi_stop_script(s); lsi_stop_script(s);
@ -547,9 +531,9 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase)
} else { } else {
s->dsp = (s->scntl2 & LSI_SCNTL2_WSR ? s->pmjad2 : s->pmjad1); s->dsp = (s->scntl2 & LSI_SCNTL2_WSR ? s->pmjad2 : s->pmjad1);
} }
DPRINTF("Data phase mismatch jump to %08x\n", s->dsp); trace_lsi_bad_phase_jump(s->dsp);
} else { } else {
DPRINTF("Phase mismatch interrupt\n"); trace_lsi_bad_phase_interrupt();
lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0); lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
lsi_stop_script(s); lsi_stop_script(s);
} }
@ -576,7 +560,7 @@ static void lsi_disconnect(LSIState *s)
static void lsi_bad_selection(LSIState *s, uint32_t id) static void lsi_bad_selection(LSIState *s, uint32_t id)
{ {
DPRINTF("Selected absent target %d\n", id); trace_lsi_bad_selection(id);
lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO); lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
lsi_disconnect(s); lsi_disconnect(s);
} }
@ -591,7 +575,7 @@ static void lsi_do_dma(LSIState *s, int out)
assert(s->current); assert(s->current);
if (!s->current->dma_len) { if (!s->current->dma_len) {
/* Wait until data is available. */ /* Wait until data is available. */
DPRINTF("DMA no data available\n"); trace_lsi_do_dma_unavailable();
return; return;
} }
@ -611,7 +595,7 @@ static void lsi_do_dma(LSIState *s, int out)
else if (s->sbms) else if (s->sbms)
addr |= ((uint64_t)s->sbms << 32); addr |= ((uint64_t)s->sbms << 32);
DPRINTF("DMA addr=0x" DMA_ADDR_FMT " len=%d\n", addr, count); trace_lsi_do_dma(addr, count);
s->csbc += count; s->csbc += count;
s->dnad += count; s->dnad += count;
s->dbc -= count; s->dbc -= count;
@ -640,7 +624,7 @@ static void lsi_queue_command(LSIState *s)
{ {
lsi_request *p = s->current; lsi_request *p = s->current;
DPRINTF("Queueing tag=0x%x\n", p->tag); trace_lsi_queue_command(p->tag);
assert(s->current != NULL); assert(s->current != NULL);
assert(s->current->dma_len == 0); assert(s->current->dma_len == 0);
QTAILQ_INSERT_TAIL(&s->queue, s->current, next); QTAILQ_INSERT_TAIL(&s->queue, s->current, next);
@ -654,9 +638,9 @@ static void lsi_queue_command(LSIState *s)
static void lsi_add_msg_byte(LSIState *s, uint8_t data) static void lsi_add_msg_byte(LSIState *s, uint8_t data)
{ {
if (s->msg_len >= LSI_MAX_MSGIN_LEN) { if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
BADF("MSG IN data too long\n"); trace_lsi_add_msg_byte_error();
} else { } else {
DPRINTF("MSG IN 0x%02x\n", data); trace_lsi_add_msg_byte(data);
s->msg[s->msg_len++] = data; s->msg[s->msg_len++] = data;
} }
} }
@ -676,7 +660,7 @@ static void lsi_reselect(LSIState *s, lsi_request *p)
if (!(s->dcntl & LSI_DCNTL_COM)) { if (!(s->dcntl & LSI_DCNTL_COM)) {
s->sfbr = 1 << (id & 0x7); s->sfbr = 1 << (id & 0x7);
} }
DPRINTF("Reselected target %d\n", id); trace_lsi_reselect(id);
s->scntl1 |= LSI_SCNTL1_CON; s->scntl1 |= LSI_SCNTL1_CON;
lsi_set_phase(s, PHASE_MI); lsi_set_phase(s, PHASE_MI);
s->msg_action = p->out ? 2 : 3; s->msg_action = p->out ? 2 : 3;
@ -732,7 +716,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
lsi_request *p = req->hba_private; lsi_request *p = req->hba_private;
if (p->pending) { if (p->pending) {
BADF("Multiple IO pending for request %p\n", p); trace_lsi_queue_req_error(p);
} }
p->pending = len; p->pending = len;
/* Reselect if waiting for it, or if reselection triggers an IRQ /* Reselect if waiting for it, or if reselection triggers an IRQ
@ -747,7 +731,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
lsi_reselect(s, p); lsi_reselect(s, p);
return 0; return 0;
} else { } else {
DPRINTF("Queueing IO tag=0x%x\n", p->tag); trace_lsi_queue_req(p->tag);
p->pending = len; p->pending = len;
return 1; return 1;
} }
@ -760,7 +744,7 @@ static void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid
int out; int out;
out = (s->sstat1 & PHASE_MASK) == PHASE_DO; out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
DPRINTF("Command complete status=%d\n", (int)status); trace_lsi_command_complete(status);
s->status = status; s->status = status;
s->command_complete = 2; s->command_complete = 2;
if (s->waiting && s->dbc != 0) { if (s->waiting && s->dbc != 0) {
@ -795,7 +779,7 @@ static void lsi_transfer_data(SCSIRequest *req, uint32_t len)
out = (s->sstat1 & PHASE_MASK) == PHASE_DO; out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
/* host adapter (re)connected */ /* host adapter (re)connected */
DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, len); trace_lsi_transfer_data(req->tag, len);
s->current->dma_len = len; s->current->dma_len = len;
s->command_complete = 1; s->command_complete = 1;
if (s->waiting) { if (s->waiting) {
@ -814,7 +798,7 @@ static void lsi_do_command(LSIState *s)
uint32_t id; uint32_t id;
int n; int n;
DPRINTF("Send command len=%d\n", s->dbc); trace_lsi_do_command(s->dbc);
if (s->dbc > 16) if (s->dbc > 16)
s->dbc = 16; s->dbc = 16;
pci_dma_read(PCI_DEVICE(s), s->dnad, buf, s->dbc); pci_dma_read(PCI_DEVICE(s), s->dnad, buf, s->dbc);
@ -862,9 +846,10 @@ static void lsi_do_command(LSIState *s)
static void lsi_do_status(LSIState *s) static void lsi_do_status(LSIState *s)
{ {
uint8_t status; uint8_t status;
DPRINTF("Get status len=%d status=%d\n", s->dbc, s->status); trace_lsi_do_status(s->dbc, s->status);
if (s->dbc != 1) if (s->dbc != 1) {
BADF("Bad Status move\n"); trace_lsi_do_status_error();
}
s->dbc = 1; s->dbc = 1;
status = s->status; status = s->status;
s->sfbr = status; s->sfbr = status;
@ -877,7 +862,7 @@ static void lsi_do_status(LSIState *s)
static void lsi_do_msgin(LSIState *s) static void lsi_do_msgin(LSIState *s)
{ {
int len; int len;
DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len); trace_lsi_do_msgin(s->dbc, s->msg_len);
s->sfbr = s->msg[0]; s->sfbr = s->msg[0];
len = s->msg_len; len = s->msg_len;
if (len > s->dbc) if (len > s->dbc)
@ -942,36 +927,36 @@ static void lsi_do_msgout(LSIState *s)
current_req = lsi_find_by_tag(s, current_tag); current_req = lsi_find_by_tag(s, current_tag);
} }
DPRINTF("MSG out len=%d\n", s->dbc); trace_lsi_do_msgout(s->dbc);
while (s->dbc) { while (s->dbc) {
msg = lsi_get_msgbyte(s); msg = lsi_get_msgbyte(s);
s->sfbr = msg; s->sfbr = msg;
switch (msg) { switch (msg) {
case 0x04: case 0x04:
DPRINTF("MSG: Disconnect\n"); trace_lsi_do_msgout_disconnect();
lsi_disconnect(s); lsi_disconnect(s);
break; break;
case 0x08: case 0x08:
DPRINTF("MSG: No Operation\n"); trace_lsi_do_msgout_noop();
lsi_set_phase(s, PHASE_CMD); lsi_set_phase(s, PHASE_CMD);
break; break;
case 0x01: case 0x01:
len = lsi_get_msgbyte(s); len = lsi_get_msgbyte(s);
msg = lsi_get_msgbyte(s); msg = lsi_get_msgbyte(s);
(void)len; /* avoid a warning about unused variable*/ (void)len; /* avoid a warning about unused variable*/
DPRINTF("Extended message 0x%x (len %d)\n", msg, len); trace_lsi_do_msgout_extended(msg, len);
switch (msg) { switch (msg) {
case 1: case 1:
DPRINTF("SDTR (ignored)\n"); trace_lsi_do_msgout_ignored("SDTR");
lsi_skip_msgbytes(s, 2); lsi_skip_msgbytes(s, 2);
break; break;
case 3: case 3:
DPRINTF("WDTR (ignored)\n"); trace_lsi_do_msgout_ignored("WDTR");
lsi_skip_msgbytes(s, 1); lsi_skip_msgbytes(s, 1);
break; break;
case 4: case 4:
DPRINTF("PPR (ignored)\n"); trace_lsi_do_msgout_ignored("PPR");
lsi_skip_msgbytes(s, 5); lsi_skip_msgbytes(s, 5);
break; break;
default: default:
@ -980,19 +965,20 @@ static void lsi_do_msgout(LSIState *s)
break; break;
case 0x20: /* SIMPLE queue */ case 0x20: /* SIMPLE queue */
s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
DPRINTF("SIMPLE queue tag=0x%x\n", s->select_tag & 0xff); trace_lsi_do_msgout_simplequeue(s->select_tag & 0xff);
break; break;
case 0x21: /* HEAD of queue */ case 0x21: /* HEAD of queue */
BADF("HEAD queue not implemented\n"); qemu_log_mask(LOG_UNIMP, "lsi_scsi: HEAD queue not implemented\n");
s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
break; break;
case 0x22: /* ORDERED queue */ case 0x22: /* ORDERED queue */
BADF("ORDERED queue not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: ORDERED queue not implemented\n");
s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
break; break;
case 0x0d: case 0x0d:
/* The ABORT TAG message clears the current I/O process only. */ /* The ABORT TAG message clears the current I/O process only. */
DPRINTF("MSG: ABORT TAG tag=0x%x\n", current_tag); trace_lsi_do_msgout_abort(current_tag);
if (current_req) { if (current_req) {
scsi_req_cancel(current_req->req); scsi_req_cancel(current_req->req);
} }
@ -1004,17 +990,17 @@ static void lsi_do_msgout(LSIState *s)
/* The ABORT message clears all I/O processes for the selecting /* The ABORT message clears all I/O processes for the selecting
initiator on the specified logical unit of the target. */ initiator on the specified logical unit of the target. */
if (msg == 0x06) { if (msg == 0x06) {
DPRINTF("MSG: ABORT tag=0x%x\n", current_tag); trace_lsi_do_msgout_abort(current_tag);
} }
/* The CLEAR QUEUE message clears all I/O processes for all /* The CLEAR QUEUE message clears all I/O processes for all
initiators on the specified logical unit of the target. */ initiators on the specified logical unit of the target. */
if (msg == 0x0e) { if (msg == 0x0e) {
DPRINTF("MSG: CLEAR QUEUE tag=0x%x\n", current_tag); trace_lsi_do_msgout_clearqueue(current_tag);
} }
/* The BUS DEVICE RESET message clears all I/O processes for all /* The BUS DEVICE RESET message clears all I/O processes for all
initiators on all logical units of the target. */ initiators on all logical units of the target. */
if (msg == 0x0c) { if (msg == 0x0c) {
DPRINTF("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); trace_lsi_do_msgout_busdevicereset(current_tag);
} }
/* clear the current I/O process */ /* clear the current I/O process */
@ -1042,14 +1028,14 @@ static void lsi_do_msgout(LSIState *s)
goto bad; goto bad;
} }
s->current_lun = msg & 7; s->current_lun = msg & 7;
DPRINTF("Select LUN %d\n", s->current_lun); trace_lsi_do_msgout_select(s->current_lun);
lsi_set_phase(s, PHASE_CMD); lsi_set_phase(s, PHASE_CMD);
break; break;
} }
} }
return; return;
bad: bad:
BADF("Unimplemented message 0x%02x\n", msg); qemu_log_mask(LOG_UNIMP, "Unimplemented message 0x%02x\n", msg);
lsi_set_phase(s, PHASE_MI); lsi_set_phase(s, PHASE_MI);
lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */ lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */
s->msg_action = 0; s->msg_action = 0;
@ -1061,7 +1047,7 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
int n; int n;
uint8_t buf[LSI_BUF_SIZE]; uint8_t buf[LSI_BUF_SIZE];
DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); trace_lsi_memcpy(dest, src, count);
while (count) { while (count) {
n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count; n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
lsi_mem_read(s, src, buf, n); lsi_mem_read(s, src, buf, n);
@ -1076,7 +1062,7 @@ static void lsi_wait_reselect(LSIState *s)
{ {
lsi_request *p; lsi_request *p;
DPRINTF("Wait Reselect\n"); trace_lsi_wait_reselect();
QTAILQ_FOREACH(p, &s->queue, next) { QTAILQ_FOREACH(p, &s->queue, next) {
if (p->pending) { if (p->pending) {
@ -1109,14 +1095,14 @@ again:
} }
addr = read_dword(s, s->dsp + 4); addr = read_dword(s, s->dsp + 4);
addr_high = 0; addr_high = 0;
DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr); trace_lsi_execute_script(s->dsp, insn, addr);
s->dsps = addr; s->dsps = addr;
s->dcmd = insn >> 24; s->dcmd = insn >> 24;
s->dsp += 8; s->dsp += 8;
switch (insn >> 30) { switch (insn >> 30) {
case 0: /* Block move. */ case 0: /* Block move. */
if (s->sist1 & LSI_SIST1_STO) { if (s->sist1 & LSI_SIST1_STO) {
DPRINTF("Delayed select timeout\n"); trace_lsi_execute_script_blockmove_delayed();
lsi_stop_script(s); lsi_stop_script(s);
break; break;
} }
@ -1171,8 +1157,9 @@ again:
addr_high = s->dbms; addr_high = s->dbms;
break; break;
default: default:
BADF("Illegal selector specified (0x%x > 0x15)" qemu_log_mask(LOG_GUEST_ERROR,
" for 64-bit DMA block move", selector); "lsi_scsi: Illegal selector specified (0x%x > 0x15) "
"for 64-bit DMA block move", selector);
break; break;
} }
} }
@ -1184,8 +1171,8 @@ again:
s->ia = s->dsp - 12; s->ia = s->dsp - 12;
} }
if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
DPRINTF("Wrong phase got %d expected %d\n", trace_lsi_execute_script_blockmove_badphase(s->sstat1 & PHASE_MASK,
s->sstat1 & PHASE_MASK, (insn >> 24) & 7); (insn >> 24) & 7);
lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0); lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
break; break;
} }
@ -1217,8 +1204,8 @@ again:
lsi_do_msgin(s); lsi_do_msgin(s);
break; break;
default: default:
BADF("Unimplemented phase %d\n", s->sstat1 & PHASE_MASK); qemu_log_mask(LOG_UNIMP, "lsi_scsi: Unimplemented phase %d\n",
exit(1); s->sstat1 & PHASE_MASK);
} }
s->dfifo = s->dbc & 0xff; s->dfifo = s->dbc & 0xff;
s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3); s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
@ -1246,7 +1233,7 @@ again:
case 0: /* Select */ case 0: /* Select */
s->sdid = id; s->sdid = id;
if (s->scntl1 & LSI_SCNTL1_CON) { if (s->scntl1 & LSI_SCNTL1_CON) {
DPRINTF("Already reselected, jumping to alternative address\n"); trace_lsi_execute_script_io_alreadyreselected();
s->dsp = s->dnad; s->dsp = s->dnad;
break; break;
} }
@ -1256,8 +1243,8 @@ again:
lsi_bad_selection(s, id); lsi_bad_selection(s, id);
break; break;
} }
DPRINTF("Selected target %d%s\n", trace_lsi_execute_script_io_selected(id,
id, insn & (1 << 3) ? " ATN" : ""); insn & (1 << 3) ? " ATN" : "");
/* ??? Linux drivers compain when this is set. Maybe /* ??? Linux drivers compain when this is set. Maybe
it only applies in low-level mode (unimplemented). it only applies in low-level mode (unimplemented).
lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */ lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
@ -1269,7 +1256,7 @@ again:
lsi_set_phase(s, PHASE_MO); lsi_set_phase(s, PHASE_MO);
break; break;
case 1: /* Disconnect */ case 1: /* Disconnect */
DPRINTF("Wait Disconnect\n"); trace_lsi_execute_script_io_disconnect();
s->scntl1 &= ~LSI_SCNTL1_CON; s->scntl1 &= ~LSI_SCNTL1_CON;
break; break;
case 2: /* Wait Reselect */ case 2: /* Wait Reselect */
@ -1278,7 +1265,7 @@ again:
} }
break; break;
case 3: /* Set */ case 3: /* Set */
DPRINTF("Set%s%s%s%s\n", trace_lsi_execute_script_io_set(
insn & (1 << 3) ? " ATN" : "", insn & (1 << 3) ? " ATN" : "",
insn & (1 << 6) ? " ACK" : "", insn & (1 << 6) ? " ACK" : "",
insn & (1 << 9) ? " TM" : "", insn & (1 << 9) ? " TM" : "",
@ -1288,14 +1275,14 @@ again:
lsi_set_phase(s, PHASE_MO); lsi_set_phase(s, PHASE_MO);
} }
if (insn & (1 << 9)) { if (insn & (1 << 9)) {
BADF("Target mode not implemented\n"); qemu_log_mask(LOG_UNIMP,
exit(1); "lsi_scsi: Target mode not implemented\n");
} }
if (insn & (1 << 10)) if (insn & (1 << 10))
s->carry = 1; s->carry = 1;
break; break;
case 4: /* Clear */ case 4: /* Clear */
DPRINTF("Clear%s%s%s%s\n", trace_lsi_execute_script_io_clear(
insn & (1 << 3) ? " ATN" : "", insn & (1 << 3) ? " ATN" : "",
insn & (1 << 6) ? " ACK" : "", insn & (1 << 6) ? " ACK" : "",
insn & (1 << 9) ? " TM" : "", insn & (1 << 9) ? " TM" : "",
@ -1313,18 +1300,17 @@ again:
uint8_t data8; uint8_t data8;
int reg; int reg;
int operator; int operator;
#ifdef DEBUG_LSI
static const char *opcode_names[3] = static const char *opcode_names[3] =
{"Write", "Read", "Read-Modify-Write"}; {"Write", "Read", "Read-Modify-Write"};
static const char *operator_names[8] = static const char *operator_names[8] =
{"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"}; {"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"};
#endif
reg = ((insn >> 16) & 0x7f) | (insn & 0x80); reg = ((insn >> 16) & 0x7f) | (insn & 0x80);
data8 = (insn >> 8) & 0xff; data8 = (insn >> 8) & 0xff;
opcode = (insn >> 27) & 7; opcode = (insn >> 27) & 7;
operator = (insn >> 24) & 7; operator = (insn >> 24) & 7;
DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n", trace_lsi_execute_script_io_opcode(
opcode_names[opcode - 5], reg, opcode_names[opcode - 5], reg,
operator_names[operator], data8, s->sfbr, operator_names[operator], data8, s->sfbr,
(insn & (1 << 23)) ? " SFBR" : ""); (insn & (1 << 23)) ? " SFBR" : "");
@ -1404,21 +1390,21 @@ again:
int jmp; int jmp;
if ((insn & 0x002e0000) == 0) { if ((insn & 0x002e0000) == 0) {
DPRINTF("NOP\n"); trace_lsi_execute_script_tc_nop();
break; break;
} }
if (s->sist1 & LSI_SIST1_STO) { if (s->sist1 & LSI_SIST1_STO) {
DPRINTF("Delayed select timeout\n"); trace_lsi_execute_script_tc_delayedselect_timeout();
lsi_stop_script(s); lsi_stop_script(s);
break; break;
} }
cond = jmp = (insn & (1 << 19)) != 0; cond = jmp = (insn & (1 << 19)) != 0;
if (cond == jmp && (insn & (1 << 21))) { if (cond == jmp && (insn & (1 << 21))) {
DPRINTF("Compare carry %d\n", s->carry == jmp); trace_lsi_execute_script_tc_compc(s->carry == jmp);
cond = s->carry != 0; cond = s->carry != 0;
} }
if (cond == jmp && (insn & (1 << 17))) { if (cond == jmp && (insn & (1 << 17))) {
DPRINTF("Compare phase %d %c= %d\n", trace_lsi_execute_script_tc_compp(
(s->sstat1 & PHASE_MASK), (s->sstat1 & PHASE_MASK),
jmp ? '=' : '!', jmp ? '=' : '!',
((insn >> 24) & 7)); ((insn >> 24) & 7));
@ -1428,7 +1414,7 @@ again:
uint8_t mask; uint8_t mask;
mask = (~insn >> 8) & 0xff; mask = (~insn >> 8) & 0xff;
DPRINTF("Compare data 0x%x & 0x%x %c= 0x%x\n", trace_lsi_execute_script_tc_compd(
s->sfbr, mask, jmp ? '=' : '!', insn & mask); s->sfbr, mask, jmp ? '=' : '!', insn & mask);
cond = (s->sfbr & mask) == (insn & mask); cond = (s->sfbr & mask) == (insn & mask);
} }
@ -1439,21 +1425,21 @@ again:
} }
switch ((insn >> 27) & 7) { switch ((insn >> 27) & 7) {
case 0: /* Jump */ case 0: /* Jump */
DPRINTF("Jump to 0x%08x\n", addr); trace_lsi_execute_script_tc_jump(addr);
s->adder = addr; s->adder = addr;
s->dsp = addr; s->dsp = addr;
break; break;
case 1: /* Call */ case 1: /* Call */
DPRINTF("Call 0x%08x\n", addr); trace_lsi_execute_script_tc_call(addr);
s->temp = s->dsp; s->temp = s->dsp;
s->dsp = addr; s->dsp = addr;
break; break;
case 2: /* Return */ case 2: /* Return */
DPRINTF("Return to 0x%08x\n", s->temp); trace_lsi_execute_script_tc_return(s->temp);
s->dsp = s->temp; s->dsp = s->temp;
break; break;
case 3: /* Interrupt */ case 3: /* Interrupt */
DPRINTF("Interrupt 0x%08x\n", s->dsps); trace_lsi_execute_script_tc_interrupt(s->dsps);
if ((insn & (1 << 20)) != 0) { if ((insn & (1 << 20)) != 0) {
s->istat0 |= LSI_ISTAT0_INTF; s->istat0 |= LSI_ISTAT0_INTF;
lsi_update_irq(s); lsi_update_irq(s);
@ -1462,12 +1448,12 @@ again:
} }
break; break;
default: default:
DPRINTF("Illegal transfer control\n"); trace_lsi_execute_script_tc_illegal();
lsi_script_dma_interrupt(s, LSI_DSTAT_IID); lsi_script_dma_interrupt(s, LSI_DSTAT_IID);
break; break;
} }
} else { } else {
DPRINTF("Control condition failed\n"); trace_lsi_execute_script_tc_cc_failed();
} }
} }
break; break;
@ -1495,13 +1481,12 @@ again:
reg = (insn >> 16) & 0xff; reg = (insn >> 16) & 0xff;
if (insn & (1 << 24)) { if (insn & (1 << 24)) {
pci_dma_read(pci_dev, addr, data, n); pci_dma_read(pci_dev, addr, data, n);
DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, trace_lsi_execute_script_mm_load(reg, n, addr, *(int *)data);
addr, *(int *)data);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
lsi_reg_writeb(s, reg + i, data[i]); lsi_reg_writeb(s, reg + i, data[i]);
} }
} else { } else {
DPRINTF("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); trace_lsi_execute_script_mm_store(reg, n, addr);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
data[i] = lsi_reg_readb(s, reg + i); data[i] = lsi_reg_readb(s, reg + i);
} }
@ -1515,8 +1500,10 @@ again:
assume this is the case and force an unexpected device disconnect. assume this is the case and force an unexpected device disconnect.
This is apparently sufficient to beat the drivers into submission. This is apparently sufficient to beat the drivers into submission.
*/ */
if (!(s->sien0 & LSI_SIST0_UDC)) if (!(s->sien0 & LSI_SIST0_UDC)) {
fprintf(stderr, "inf. loop with UDC masked\n"); qemu_log_mask(LOG_GUEST_ERROR,
"lsi_scsi: inf. loop with UDC masked");
}
lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
lsi_disconnect(s); lsi_disconnect(s);
} else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) { } else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) {
@ -1526,7 +1513,7 @@ again:
goto again; goto again;
} }
} }
DPRINTF("SCRIPTS execution stopped\n"); trace_lsi_execute_script_stop();
} }
static uint8_t lsi_reg_readb(LSIState *s, int offset) static uint8_t lsi_reg_readb(LSIState *s, int offset)
@ -1761,10 +1748,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
#undef CASE_GET_REG24 #undef CASE_GET_REG24
#undef CASE_GET_REG32 #undef CASE_GET_REG32
#ifdef DEBUG_LSI_REG trace_lsi_reg_read(offset < ARRAY_SIZE(names) ? names[offset] : "???",
DPRINTF("Read reg %s %x = %02x\n", offset, ret);
offset < ARRAY_SIZE(names) ? names[offset] : "???", offset, ret);
#endif
return ret; return ret;
} }
@ -1782,21 +1767,22 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \ case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break; case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
#ifdef DEBUG_LSI_REG trace_lsi_reg_write(offset < ARRAY_SIZE(names) ? names[offset] : "???",
DPRINTF("Write reg %s %x = %02x\n", offset, val);
offset < ARRAY_SIZE(names) ? names[offset] : "???", offset, val);
#endif
switch (offset) { switch (offset) {
case 0x00: /* SCNTL0 */ case 0x00: /* SCNTL0 */
s->scntl0 = val; s->scntl0 = val;
if (val & LSI_SCNTL0_START) { if (val & LSI_SCNTL0_START) {
BADF("Start sequence not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: Start sequence not implemented\n");
} }
break; break;
case 0x01: /* SCNTL1 */ case 0x01: /* SCNTL1 */
s->scntl1 = val & ~LSI_SCNTL1_SST; s->scntl1 = val & ~LSI_SCNTL1_SST;
if (val & LSI_SCNTL1_IARB) { if (val & LSI_SCNTL1_IARB) {
BADF("Immediate Arbritration not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: Immediate Arbritration not implemented\n");
} }
if (val & LSI_SCNTL1_RST) { if (val & LSI_SCNTL1_RST) {
if (!(s->sstat0 & LSI_SSTAT0_RST)) { if (!(s->sstat0 & LSI_SSTAT0_RST)) {
@ -1823,7 +1809,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
break; break;
case 0x06: /* SDID */ case 0x06: /* SDID */
if ((s->ssid & 0x80) && (val & 0xf) != (s->ssid & 0xf)) { if ((s->ssid & 0x80) && (val & 0xf) != (s->ssid & 0xf)) {
BADF("Destination ID does not match SSID\n"); qemu_log_mask(LOG_GUEST_ERROR,
"lsi_scsi: Destination ID does not match SSID\n");
} }
s->sdid = val & 0xf; s->sdid = val & 0xf;
break; break;
@ -1851,7 +1838,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
lsi_update_irq(s); lsi_update_irq(s);
} }
if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) { if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) {
DPRINTF("Woken by SIGP\n"); trace_lsi_awoken();
s->waiting = 0; s->waiting = 0;
s->dsp = s->dnad; s->dsp = s->dnad;
lsi_execute_script(s); lsi_execute_script(s);
@ -1878,13 +1865,15 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
CASE_SET_REG32(temp, 0x1c) CASE_SET_REG32(temp, 0x1c)
case 0x21: /* CTEST4 */ case 0x21: /* CTEST4 */
if (val & 7) { if (val & 7) {
BADF("Unimplemented CTEST4-FBL 0x%x\n", val); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: Unimplemented CTEST4-FBL 0x%x\n", val);
} }
s->ctest4 = val; s->ctest4 = val;
break; break;
case 0x22: /* CTEST5 */ case 0x22: /* CTEST5 */
if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) { if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) {
BADF("CTEST5 DMA increment not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: CTEST5 DMA increment not implemented\n");
} }
s->ctest5 = val; s->ctest5 = val;
break; break;
@ -1941,7 +1930,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
break; break;
case 0x49: /* STIME1 */ case 0x49: /* STIME1 */
if (val & 0xf) { if (val & 0xf) {
DPRINTF("General purpose timer not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: General purpose timer not implemented\n");
/* ??? Raising the interrupt immediately seems to be sufficient /* ??? Raising the interrupt immediately seems to be sufficient
to keep the FreeBSD driver happy. */ to keep the FreeBSD driver happy. */
lsi_script_scsi_interrupt(s, 0, LSI_SIST1_GEN); lsi_script_scsi_interrupt(s, 0, LSI_SIST1_GEN);
@ -1958,13 +1948,15 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
break; break;
case 0x4e: /* STEST2 */ case 0x4e: /* STEST2 */
if (val & 1) { if (val & 1) {
BADF("Low level mode not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: Low level mode not implemented\n");
} }
s->stest2 = val; s->stest2 = val;
break; break;
case 0x4f: /* STEST3 */ case 0x4f: /* STEST3 */
if (val & 0x41) { if (val & 0x41) {
BADF("SCSI FIFO test mode not implemented\n"); qemu_log_mask(LOG_UNIMP,
"lsi_scsi: SCSI FIFO test mode not implemented\n");
} }
s->stest3 = val; s->stest3 = val;
break; break;

View File

@ -229,3 +229,65 @@ spapr_vscsi_process_login(void) "Got login, sending response !"
spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun 0x%08" PRIx64 " with no drive" spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun 0x%08" PRIx64 " with no drive"
spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d" spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d"
spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..." spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..."
# hw/scsi/lsi53c895a.c
lsi_reset(void) "Reset"
lsi_update_irq(int level, uint8_t dstat, uint8_t sist1, uint8_t sist0) "Update IRQ level %d dstat 0x%02x sist 0x%02x0x%02x"
lsi_update_irq_disconnected(void) "Handled IRQs & disconnected, looking for pending processes"
lsi_script_scsi_interrupt(uint8_t stat1, uint8_t stat0, uint8_t sist1, uint8_t sist0) "SCSI Interrupt 0x%02x0x%02x prev 0x%02x0x%02x"
lsi_script_dma_interrupt(uint8_t stat, uint8_t dstat) "DMA Interrupt 0x%x prev 0x%x"
lsi_bad_phase_jump(uint32_t dsp) "Data phase mismatch jump to 0x%"PRIX32
lsi_bad_phase_interrupt(void) "Phase mismatch interrupt"
lsi_bad_selection(uint32_t id) "Selected absent target %"PRIu32
lsi_do_dma_unavailable(void) "DMA no data available"
lsi_do_dma(uint64_t addr, int len) "DMA addr=0x%"PRIx64" len=%d"
lsi_queue_command(uint32_t tag) "Queueing tag=0x%"PRId32
lsi_add_msg_byte_error(void) "MSG IN data too long"
lsi_add_msg_byte(uint8_t data) "MSG IN 0x%02x"
lsi_reselect(int id) "Reselected target %d"
lsi_queue_req_error(void *p) "Multiple IO pending for request %p"
lsi_queue_req(uint32_t tag) "Queueing IO tag=0x%"PRIx32
lsi_command_complete(uint32_t status) "Command complete status=%"PRId32
lsi_transfer_data(uint32_t tag, uint32_t len) "Data ready tag=0x%"PRIx32" len=%"PRId32
lsi_do_command(uint32_t dbc) "Send command len=%"PRId32
lsi_do_status(uint32_t dbc, uint8_t status) "Get status len=%"PRId32" status=%d"
lsi_do_status_error(void) "Bad Status move"
lsi_do_msgin(uint32_t dbc, int len) "Message in len=%"PRId32" %d"
lsi_do_msgout(uint32_t dbc) "MSG out len=%"PRId32
lsi_do_msgout_disconnect(void) "MSG: Disconnect"
lsi_do_msgout_noop(void) "MSG: No Operation"
lsi_do_msgout_extended(uint8_t msg, uint8_t len) "Extended message 0x%x (len %d)"
lsi_do_msgout_ignored(const char *msg) "%s (ignored)"
lsi_do_msgout_simplequeue(uint8_t select_tag) "SIMPLE queue tag=0x%x"
lsi_do_msgout_abort(uint32_t tag) "MSG: ABORT TAG tag=0x%"PRId32
lsi_do_msgout_clearqueue(uint32_t tag) "MSG: CLEAR QUEUE tag=0x%"PRIx32
lsi_do_msgout_busdevicereset(uint32_t tag) "MSG: BUS DEVICE RESET tag=0x%"PRIx32
lsi_do_msgout_select(int id) "Select LUN %d"
lsi_memcpy(uint32_t dest, uint32_t src, int count) "memcpy dest 0x%"PRIx32" src 0x%"PRIx32" count %d"
lsi_wait_reselect(void) "Wait Reselect"
lsi_execute_script(uint32_t dsp, uint32_t insn, uint32_t addr) "SCRIPTS dsp=0x%"PRIx32" opcode 0x%"PRIx32" arg 0x%"PRIx32
lsi_execute_script_blockmove_delayed(void) "Delayed select timeout"
lsi_execute_script_blockmove_badphase(uint8_t phase, uint8_t expected) "Wrong phase got %d expected %d"
lsi_execute_script_io_alreadyreselected(void) "Already reselected, jumping to alternative address"
lsi_execute_script_io_selected(uint8_t id, const char *atn) "Selected target %d%s"
lsi_execute_script_io_disconnect(void) "Wait Disconnect"
lsi_execute_script_io_set(const char *atn, const char *ack, const char *tm, const char *cc) "Set%s%s%s%s"
lsi_execute_script_io_clear(const char *atn, const char *ack, const char *tm, const char *cc) "Clear%s%s%s%s"
lsi_execute_script_io_opcode(const char *opcode, int reg, const char *opname, uint8_t data8, uint32_t sfbr, const char *ssfbr) "%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s"
lsi_execute_script_tc_nop(void) "NOP"
lsi_execute_script_tc_delayedselect_timeout(void) "Delayed select timeout"
lsi_execute_script_tc_compc(int result) "Compare carry %d"
lsi_execute_script_tc_compp(uint8_t phase, int op, uint8_t insn_phase) "Compare phase %d %c= %d"
lsi_execute_script_tc_compd(uint32_t sfbr, uint8_t mask, int op, int result) "Compare data 0x%"PRIx32" & 0x%x %c= 0x%x"
lsi_execute_script_tc_jump(uint32_t addr) "Jump to 0x%"PRIx32
lsi_execute_script_tc_call(uint32_t addr) "Call 0x%"PRIx32
lsi_execute_script_tc_return(uint32_t addr) "Return to 0x%"PRIx32
lsi_execute_script_tc_interrupt(uint32_t addr) "Interrupt 0x%"PRIx32
lsi_execute_script_tc_illegal(void) "Illegal transfer control"
lsi_execute_script_tc_cc_failed(void) "Control condition failed"
lsi_execute_script_mm_load(int reg, int n, uint32_t addr, int data) "Load reg 0x%x size %d addr 0x%"PRIx32" = 0x%08x"
lsi_execute_script_mm_store(int reg, int n, uint32_t addr) "Store reg 0x%x size %d addr 0x%"PRIx32
lsi_execute_script_stop(void) "SCRIPTS execution stopped"
lsi_awoken(void) "Woken by SIGP"
lsi_reg_read(const char *name, int offset, uint8_t ret) "Read reg %s 0x%x = 0x%02x"
lsi_reg_write(const char *name, int offset, uint8_t val) "Write reg %s 0x%x = 0x%02x"