diff options
author | Christoph Hellwig <hch@lst.de> | 2010-12-20 13:45:48 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2011-01-24 11:08:50 +0100 |
commit | cd369c4634e58a99fb82f076e6117bfdf0012b8e (patch) | |
tree | f5eee0d38844ef367c06b1d0a04e97dbdda20eae /hw | |
parent | 8b6b2afcf85dd5ff33075e93a2e30fbea34c5a55 (diff) |
ide: factor dma handling helpers
Factor the DMA I/O path that is duplicated between read and write
commands, into common helpers using the s->is_read flag added for
the macio ATA controller.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/ide/core.c | 103 | ||||
-rw-r--r-- | hw/ide/internal.h | 4 | ||||
-rw-r--r-- | hw/ide/pci.c | 9 |
3 files changed, 36 insertions, 80 deletions
diff --git a/hw/ide/core.c b/hw/ide/core.c index 9496e990b9..e93dd4616c 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -487,16 +487,18 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) return 1; } -void ide_read_dma_cb(void *opaque, int ret) +void ide_dma_cb(void *opaque, int ret) { IDEState *s = opaque; int n; int64_t sector_num; if (ret < 0) { - if (ide_handle_rw_error(s, -ret, - BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ)) - { + int op = BM_STATUS_DMA_RETRY; + + if (s->is_read) + op |= BM_STATUS_RETRY_READ; + if (ide_handle_rw_error(s, -ret, op)) { return; } } @@ -504,7 +506,7 @@ void ide_read_dma_cb(void *opaque, int ret) n = s->io_buffer_size >> 9; sector_num = ide_get_sector(s); if (n > 0) { - dma_buf_commit(s, 1); + dma_buf_commit(s, s->is_read); sector_num += n; ide_set_sector(s, sector_num); s->nsector -= n; @@ -514,32 +516,44 @@ void ide_read_dma_cb(void *opaque, int ret) if (s->nsector == 0) { s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); - eot: - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); - ide_set_inactive(s); - return; + goto eot; } /* launch next transfer */ n = s->nsector; - s->io_buffer_index = 0; + if (s->is_read) + s->io_buffer_index = 0; s->io_buffer_size = n * 512; - if (s->bus->dma->ops->prepare_buf(s->bus->dma, 1) == 0) + if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0) goto eot; + #ifdef DEBUG_AIO - printf("aio_read: sector_num=%" PRId64 " n=%d\n", sector_num, n); + printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n", + sector_num, n, s->is_read); #endif - s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, ide_read_dma_cb, s); - ide_dma_submit_check(s, ide_read_dma_cb); + + if (s->is_read) { + s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, + ide_dma_cb, s); + } else { + s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, + ide_dma_cb, s); + } + ide_dma_submit_check(s, ide_dma_cb); + return; + +eot: + s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); + ide_set_inactive(s); } -static void ide_sector_read_dma(IDEState *s) +static void ide_sector_start_dma(IDEState *s, int is_read) { s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; s->io_buffer_index = 0; s->io_buffer_size = 0; - s->is_read = 1; - s->bus->dma->ops->start_dma(s->bus->dma, s, ide_read_dma_cb); + s->is_read = is_read; + s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb); } static void ide_sector_write_timer_cb(void *opaque) @@ -594,57 +608,6 @@ void ide_sector_write(IDEState *s) } } -void ide_write_dma_cb(void *opaque, int ret) -{ - IDEState *s = opaque; - int n; - int64_t sector_num; - - if (ret < 0) { - if (ide_handle_rw_error(s, -ret, BM_STATUS_DMA_RETRY)) - return; - } - - n = s->io_buffer_size >> 9; - sector_num = ide_get_sector(s); - if (n > 0) { - dma_buf_commit(s, 0); - sector_num += n; - ide_set_sector(s, sector_num); - s->nsector -= n; - } - - /* end of transfer ? */ - if (s->nsector == 0) { - s->status = READY_STAT | SEEK_STAT; - ide_set_irq(s->bus); - eot: - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); - ide_set_inactive(s); - return; - } - - n = s->nsector; - s->io_buffer_size = n * 512; - /* launch next transfer */ - if (s->bus->dma->ops->prepare_buf(s->bus->dma, 0) == 0) - goto eot; -#ifdef DEBUG_AIO - printf("aio_write: sector_num=%" PRId64 " n=%d\n", sector_num, n); -#endif - s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, ide_write_dma_cb, s); - ide_dma_submit_check(s, ide_write_dma_cb); -} - -static void ide_sector_write_dma(IDEState *s) -{ - s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; - s->io_buffer_index = 0; - s->io_buffer_size = 0; - s->is_read = 0; - s->bus->dma->ops->start_dma(s->bus->dma, s, ide_write_dma_cb); -} - void ide_atapi_cmd_ok(IDEState *s) { s->error = 0; @@ -1858,7 +1821,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) if (!s->bs) goto abort_cmd; ide_cmd_lba48_transform(s, lba48); - ide_sector_read_dma(s); + ide_sector_start_dma(s, 1); break; case WIN_WRITEDMA_EXT: lba48 = 1; @@ -1867,7 +1830,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) if (!s->bs) goto abort_cmd; ide_cmd_lba48_transform(s, lba48); - ide_sector_write_dma(s); + ide_sector_start_dma(s, 0); s->media_changed = 1; break; case WIN_READ_NATIVE_MAX_EXT: diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 697c3b4dc1..d533fb63b3 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -439,7 +439,6 @@ struct IDEState { uint32_t mdata_size; uint8_t *mdata_storage; int media_changed; - /* for pmac */ int is_read; /* SMART */ uint8_t smart_enabled; @@ -560,8 +559,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); void ide_exec_cmd(IDEBus *bus, uint32_t val); -void ide_read_dma_cb(void *opaque, int ret); -void ide_write_dma_cb(void *opaque, int ret); +void ide_dma_cb(void *opaque, int ret); void ide_sector_write(IDEState *s); void ide_sector_read(IDEState *s); void ide_flush_cache(IDEState *s); diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 510b2de597..987caffa3a 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -178,14 +178,9 @@ static void bmdma_restart_dma(BMDMAState *bm, int is_read) s->io_buffer_index = 0; s->io_buffer_size = 0; s->nsector = bm->nsector; + s->is_read = is_read; bm->cur_addr = bm->addr; - - if (is_read) { - bm->dma_cb = ide_read_dma_cb; - } else { - bm->dma_cb = ide_write_dma_cb; - } - + bm->dma_cb = ide_dma_cb; bmdma_start_dma(&bm->dma, s, bm->dma_cb); } |