Message ID | 1289955937-24121-5-git-send-email-agraf@suse.de |
---|---|
State | New |
Headers | show |
Hi, > + if (s->sg_third_party) { > + /* We've already parsed the guest RAM PRDT. > + * This is essential for AHCI, where the PRDT is in a different > + * format than in IDE BMDMA. > + */ > + memcpy((uint8_t *)&prd, s->sg.sg, sizeof(prd)); > + s->sg.sg++; > + } else { > + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); > + bm->cur_addr += 8; > + prd.addr = le32_to_cpu(prd.addr); > + prd.size = le32_to_cpu(prd.size); > + } Does it make sense to handle this via IDEBusOps too? cheers, Gerd
On Wed, Nov 17, 2010 at 1:05 AM, Alexander Graf <agraf@suse.de> wrote: > @@ -535,12 +543,25 @@ static int dma_buf_rw(BMDMAState *bm, int is_write) > if (bm->cur_prd_len == 0) { > /* end of table (with a fail safe of one page) */ > if (bm->cur_prd_last || > - (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) > - return 0; > - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); > - bm->cur_addr += 8; > - prd.addr = le32_to_cpu(prd.addr); > - prd.size = le32_to_cpu(prd.size); > + (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) { > + s->sg.sg -= s->sg.nsg; //XXX I don't understand why s->sg.sg needs to be modified at all. Are we stashing the pointer away accross dma_buf_rw() invocations? > + return 0; > + } > + if (s->sg_third_party) { > + /* We've already parsed the guest RAM PRDT. > + * This is essential for AHCI, where the PRDT is in a different > + * format than in IDE BMDMA. > + */ > + memcpy((uint8_t *)&prd, s->sg.sg, sizeof(prd)); struct { uint32_t addr; uint32_t size; } prd; typedef struct { target_phys_addr_t base; target_phys_addr_t len; } ScatterGatherEntry; sizeof(target_phys_addr_t) != sizeof(uint32_t) for 64-bit targets prd should use a proper struct instead of redefining it inline in dma_buf_rw() and dma_buf_prepare(). That struct could either be a ScatterGatherEntry or something else that we assign s->sg.sg fields to individually. Stefan
diff --git a/hw/ide/core.c b/hw/ide/core.c index 276b853..4c15ea2 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -444,8 +444,16 @@ static int dma_buf_prepare(BMDMAState *bm, int is_write) uint32_t addr; uint32_t size; } prd; - int l, len; + int l, len, i; + if (s->sg_third_party) { + /* We already have an sglist. */ + s->io_buffer_size = 0; + for (i=0; i < s->sg.nsg; i++) { + s->io_buffer_size += s->sg.sg[i].len; + } + return s->io_buffer_size != 0; + } qemu_sglist_init(&s->sg, s->nsector / (IDE_PAGE_SIZE / 512) + 1); s->io_buffer_size = 0; for(;;) { @@ -535,12 +543,25 @@ static int dma_buf_rw(BMDMAState *bm, int is_write) if (bm->cur_prd_len == 0) { /* end of table (with a fail safe of one page) */ if (bm->cur_prd_last || - (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) - return 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); - bm->cur_addr += 8; - prd.addr = le32_to_cpu(prd.addr); - prd.size = le32_to_cpu(prd.size); + (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) { + s->sg.sg -= s->sg.nsg; //XXX + return 0; + } + if (s->sg_third_party) { + /* We've already parsed the guest RAM PRDT. + * This is essential for AHCI, where the PRDT is in a different + * format than in IDE BMDMA. + */ + memcpy((uint8_t *)&prd, s->sg.sg, sizeof(prd)); + s->sg.sg++; + } else { + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + bm->cur_addr += 8; + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); + } + + len = prd.size & 0xfffe; if (len == 0) len = 0x10000; @@ -2715,6 +2736,9 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, } else { pstrcpy(s->version, sizeof(s->version), QEMU_VERSION); } + + s->sg_third_party = 0; + ide_reset(s); bdrv_set_removable(bs, s->drive_kind == IDE_CD); return 0; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 19e5efb..005283c 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -422,6 +422,7 @@ struct IDEState { /* ATA DMA state */ int io_buffer_size; QEMUSGList sg; + int sg_third_party; /* PIO transfer handling */ int req_nb_sectors; /* number of sectors per interrupt */ EndTransferFunc *end_transfer_func;