Add 40-bit DMA support to LSI scsi emulation (Ryan Harper)
This patch fixes Linux machines configured with > 4G of ram and using a SCSI device. Signed-off-by: Ryan Harper <ryanh@us.ibm.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5750 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
426cd5d6d2
commit
b25cf5893f
@ -143,6 +143,14 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0)
|
||||
#define LSI_CCNTL0_PMJCTL 0x40
|
||||
#define LSI_CCNTL0_ENPMJ 0x80
|
||||
|
||||
#define LSI_CCNTL1_EN64DBMV 0x01
|
||||
#define LSI_CCNTL1_EN64TIBMV 0x02
|
||||
#define LSI_CCNTL1_64TIMOD 0x04
|
||||
#define LSI_CCNTL1_DDAC 0x08
|
||||
#define LSI_CCNTL1_ZMOD 0x80
|
||||
|
||||
#define LSI_CCNTL1_40BIT (LSI_CCNTL1_EN64TIBMV|LSI_CCNTL1_64TIMOD)
|
||||
|
||||
#define PHASE_DO 0
|
||||
#define PHASE_DI 1
|
||||
#define PHASE_CMD 2
|
||||
@ -323,6 +331,13 @@ static void lsi_soft_reset(LSIState *s)
|
||||
s->csbc = 0;
|
||||
}
|
||||
|
||||
static int lsi_dma_40bit(LSIState *s)
|
||||
{
|
||||
if ((s->ccntl1 & LSI_CCNTL1_40BIT) == LSI_CCNTL1_40BIT)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t lsi_reg_readb(LSIState *s, int offset);
|
||||
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
|
||||
static void lsi_execute_script(LSIState *s);
|
||||
@ -449,7 +464,7 @@ static void lsi_resume_script(LSIState *s)
|
||||
static void lsi_do_dma(LSIState *s, int out)
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t addr;
|
||||
target_phys_addr_t addr;
|
||||
|
||||
if (!s->current_dma_len) {
|
||||
/* Wait until data is available. */
|
||||
@ -460,9 +475,14 @@ static void lsi_do_dma(LSIState *s, int out)
|
||||
count = s->dbc;
|
||||
if (count > s->current_dma_len)
|
||||
count = s->current_dma_len;
|
||||
DPRINTF("DMA addr=0x%08x len=%d\n", s->dnad, count);
|
||||
|
||||
addr = s->dnad;
|
||||
if (lsi_dma_40bit(s))
|
||||
addr |= ((uint64_t)s->dnad64 << 32);
|
||||
else if (s->sbms)
|
||||
addr |= ((uint64_t)s->sbms << 32);
|
||||
|
||||
DPRINTF("DMA addr=0x%" TARGET_FMT_plx " len=%d\n", addr, count);
|
||||
s->csbc += count;
|
||||
s->dnad += count;
|
||||
s->dbc -= count;
|
||||
@ -839,7 +859,7 @@ static void lsi_wait_reselect(LSIState *s)
|
||||
static void lsi_execute_script(LSIState *s)
|
||||
{
|
||||
uint32_t insn;
|
||||
uint32_t addr;
|
||||
uint32_t addr, addr_high;
|
||||
int opcode;
|
||||
int insn_processed = 0;
|
||||
|
||||
@ -848,6 +868,7 @@ again:
|
||||
insn_processed++;
|
||||
insn = read_dword(s, s->dsp);
|
||||
addr = read_dword(s, s->dsp + 4);
|
||||
addr_high = 0;
|
||||
DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
|
||||
s->dsps = addr;
|
||||
s->dcmd = insn >> 24;
|
||||
@ -870,9 +891,15 @@ again:
|
||||
/* Table indirect addressing. */
|
||||
offset = sxt24(addr);
|
||||
cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
|
||||
s->dbc = cpu_to_le32(buf[0]);
|
||||
/* byte count is stored in bits 0:23 only */
|
||||
s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
|
||||
s->rbc = s->dbc;
|
||||
addr = cpu_to_le32(buf[1]);
|
||||
|
||||
/* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of
|
||||
* table, bits [31:24] */
|
||||
if (lsi_dma_40bit(s))
|
||||
addr_high = cpu_to_le32(buf[0]) >> 24;
|
||||
}
|
||||
if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
|
||||
DPRINTF("Wrong phase got %d expected %d\n",
|
||||
@ -881,6 +908,7 @@ again:
|
||||
break;
|
||||
}
|
||||
s->dnad = addr;
|
||||
s->dnad64 = addr_high;
|
||||
/* ??? Set ESA. */
|
||||
s->ia = s->dsp - 8;
|
||||
switch (s->sstat1 & 0x7) {
|
||||
|
Loading…
Reference in New Issue
Block a user