Commit b25cf5893f5ad07c2b8eada28250fc9cb8fb7e2a
1 parent
426cd5d6
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
Showing
1 changed file
with
32 additions
and
4 deletions
hw/lsi53c895a.c
... | ... | @@ -143,6 +143,14 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0) |
143 | 143 | #define LSI_CCNTL0_PMJCTL 0x40 |
144 | 144 | #define LSI_CCNTL0_ENPMJ 0x80 |
145 | 145 | |
146 | +#define LSI_CCNTL1_EN64DBMV 0x01 | |
147 | +#define LSI_CCNTL1_EN64TIBMV 0x02 | |
148 | +#define LSI_CCNTL1_64TIMOD 0x04 | |
149 | +#define LSI_CCNTL1_DDAC 0x08 | |
150 | +#define LSI_CCNTL1_ZMOD 0x80 | |
151 | + | |
152 | +#define LSI_CCNTL1_40BIT (LSI_CCNTL1_EN64TIBMV|LSI_CCNTL1_64TIMOD) | |
153 | + | |
146 | 154 | #define PHASE_DO 0 |
147 | 155 | #define PHASE_DI 1 |
148 | 156 | #define PHASE_CMD 2 |
... | ... | @@ -323,6 +331,13 @@ static void lsi_soft_reset(LSIState *s) |
323 | 331 | s->csbc = 0; |
324 | 332 | } |
325 | 333 | |
334 | +static int lsi_dma_40bit(LSIState *s) | |
335 | +{ | |
336 | + if ((s->ccntl1 & LSI_CCNTL1_40BIT) == LSI_CCNTL1_40BIT) | |
337 | + return 1; | |
338 | + return 0; | |
339 | +} | |
340 | + | |
326 | 341 | static uint8_t lsi_reg_readb(LSIState *s, int offset); |
327 | 342 | static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); |
328 | 343 | static void lsi_execute_script(LSIState *s); |
... | ... | @@ -449,7 +464,7 @@ static void lsi_resume_script(LSIState *s) |
449 | 464 | static void lsi_do_dma(LSIState *s, int out) |
450 | 465 | { |
451 | 466 | uint32_t count; |
452 | - uint32_t addr; | |
467 | + target_phys_addr_t addr; | |
453 | 468 | |
454 | 469 | if (!s->current_dma_len) { |
455 | 470 | /* Wait until data is available. */ |
... | ... | @@ -460,9 +475,14 @@ static void lsi_do_dma(LSIState *s, int out) |
460 | 475 | count = s->dbc; |
461 | 476 | if (count > s->current_dma_len) |
462 | 477 | count = s->current_dma_len; |
463 | - DPRINTF("DMA addr=0x%08x len=%d\n", s->dnad, count); | |
464 | 478 | |
465 | 479 | addr = s->dnad; |
480 | + if (lsi_dma_40bit(s)) | |
481 | + addr |= ((uint64_t)s->dnad64 << 32); | |
482 | + else if (s->sbms) | |
483 | + addr |= ((uint64_t)s->sbms << 32); | |
484 | + | |
485 | + DPRINTF("DMA addr=0x%" TARGET_FMT_plx " len=%d\n", addr, count); | |
466 | 486 | s->csbc += count; |
467 | 487 | s->dnad += count; |
468 | 488 | s->dbc -= count; |
... | ... | @@ -839,7 +859,7 @@ static void lsi_wait_reselect(LSIState *s) |
839 | 859 | static void lsi_execute_script(LSIState *s) |
840 | 860 | { |
841 | 861 | uint32_t insn; |
842 | - uint32_t addr; | |
862 | + uint32_t addr, addr_high; | |
843 | 863 | int opcode; |
844 | 864 | int insn_processed = 0; |
845 | 865 | |
... | ... | @@ -848,6 +868,7 @@ again: |
848 | 868 | insn_processed++; |
849 | 869 | insn = read_dword(s, s->dsp); |
850 | 870 | addr = read_dword(s, s->dsp + 4); |
871 | + addr_high = 0; | |
851 | 872 | DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr); |
852 | 873 | s->dsps = addr; |
853 | 874 | s->dcmd = insn >> 24; |
... | ... | @@ -870,9 +891,15 @@ again: |
870 | 891 | /* Table indirect addressing. */ |
871 | 892 | offset = sxt24(addr); |
872 | 893 | cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); |
873 | - s->dbc = cpu_to_le32(buf[0]); | |
894 | + /* byte count is stored in bits 0:23 only */ | |
895 | + s->dbc = cpu_to_le32(buf[0]) & 0xffffff; | |
874 | 896 | s->rbc = s->dbc; |
875 | 897 | addr = cpu_to_le32(buf[1]); |
898 | + | |
899 | + /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of | |
900 | + * table, bits [31:24] */ | |
901 | + if (lsi_dma_40bit(s)) | |
902 | + addr_high = cpu_to_le32(buf[0]) >> 24; | |
876 | 903 | } |
877 | 904 | if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { |
878 | 905 | DPRINTF("Wrong phase got %d expected %d\n", |
... | ... | @@ -881,6 +908,7 @@ again: |
881 | 908 | break; |
882 | 909 | } |
883 | 910 | s->dnad = addr; |
911 | + s->dnad64 = addr_high; | |
884 | 912 | /* ??? Set ESA. */ |
885 | 913 | s->ia = s->dsp - 8; |
886 | 914 | switch (s->sstat1 & 0x7) { | ... | ... |