Commit e3007e6677fd5723dac5a10033319aa0f8dfaf64
1 parent
28ce5ce6
PowerPC: IDE DB-DMA support
This patches allows powermac IDE interface to use DB-DMA. This implementation uses only synchronous I/O. Signed-off-by: Laurent Vivier <Laurent@lvivier.info> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6489 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
156 additions
and
23 deletions
hw/ide.c
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | #include "qemu-timer.h" |
32 | 32 | #include "sysemu.h" |
33 | 33 | #include "ppc_mac.h" |
34 | +#include "mac_dbdma.h" | |
34 | 35 | #include "sh.h" |
35 | 36 | |
36 | 37 | /* debug IDE devices */ |
... | ... | @@ -437,6 +438,8 @@ typedef struct IDEState { |
437 | 438 | uint32_t mdata_size; |
438 | 439 | uint8_t *mdata_storage; |
439 | 440 | int media_changed; |
441 | + /* for pmac */ | |
442 | + int is_read; | |
440 | 443 | } IDEState; |
441 | 444 | |
442 | 445 | /* XXX: DVDs that could fit on a CD will be reported as a CD */ |
... | ... | @@ -1094,6 +1097,7 @@ static void ide_sector_read_dma(IDEState *s) |
1094 | 1097 | s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; |
1095 | 1098 | s->io_buffer_index = 0; |
1096 | 1099 | s->io_buffer_size = 0; |
1100 | + s->is_read = 1; | |
1097 | 1101 | ide_dma_start(s, ide_read_dma_cb); |
1098 | 1102 | } |
1099 | 1103 | |
... | ... | @@ -1222,6 +1226,7 @@ static void ide_sector_write_dma(IDEState *s) |
1222 | 1226 | s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; |
1223 | 1227 | s->io_buffer_index = 0; |
1224 | 1228 | s->io_buffer_size = 0; |
1229 | + s->is_read = 0; | |
1225 | 1230 | ide_dma_start(s, ide_write_dma_cb); |
1226 | 1231 | } |
1227 | 1232 | |
... | ... | @@ -3473,21 +3478,130 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, |
3473 | 3478 | register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d); |
3474 | 3479 | } |
3475 | 3480 | |
3481 | +#if defined(TARGET_PPC) | |
3476 | 3482 | /***********************************************************/ |
3477 | 3483 | /* MacIO based PowerPC IDE */ |
3478 | 3484 | |
3485 | +typedef struct MACIOIDEState { | |
3486 | + IDEState ide_if[2]; | |
3487 | + void *dbdma; | |
3488 | + int stream_index; | |
3489 | +} MACIOIDEState; | |
3490 | + | |
3491 | +static int pmac_atapi_read(DBDMA_transfer *info, DBDMA_transfer_cb cb) | |
3492 | +{ | |
3493 | + MACIOIDEState *m = info->opaque; | |
3494 | + IDEState *s = m->ide_if->cur_drive; | |
3495 | + int ret; | |
3496 | + | |
3497 | + if (s->lba == -1) | |
3498 | + return 0; | |
3499 | + | |
3500 | + info->buf_pos = 0; | |
3501 | + | |
3502 | + while (info->buf_pos < info->len && s->packet_transfer_size > 0) { | |
3503 | + | |
3504 | + ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); | |
3505 | + if (ret < 0) { | |
3506 | + ide_transfer_stop(s); | |
3507 | + ide_atapi_io_error(s, ret); | |
3508 | + return info->buf_pos; | |
3509 | + } | |
3510 | + | |
3511 | + info->buf = s->io_buffer + m->stream_index; | |
3512 | + | |
3513 | + info->buf_len = s->cd_sector_size; | |
3514 | + if (info->buf_pos + info->buf_len > info->len) | |
3515 | + info->buf_len = info->len - info->buf_pos; | |
3516 | + | |
3517 | + cb(info); | |
3518 | + | |
3519 | + /* db-dma can ask for 512 bytes whereas block size is 2048... */ | |
3520 | + | |
3521 | + m->stream_index += info->buf_len; | |
3522 | + s->lba += m->stream_index / s->cd_sector_size; | |
3523 | + m->stream_index %= s->cd_sector_size; | |
3524 | + | |
3525 | + info->buf_pos += info->buf_len; | |
3526 | + s->packet_transfer_size -= info->buf_len; | |
3527 | + } | |
3528 | + if (s->packet_transfer_size <= 0) { | |
3529 | + s->status = READY_STAT | SEEK_STAT; | |
3530 | + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | |
3531 | + | ATAPI_INT_REASON_CD; | |
3532 | + ide_set_irq(s); | |
3533 | + } | |
3534 | + | |
3535 | + return info->buf_pos; | |
3536 | +} | |
3537 | + | |
3538 | +static int pmac_ide_transfer(DBDMA_transfer *info, | |
3539 | + DBDMA_transfer_cb cb) | |
3540 | +{ | |
3541 | + MACIOIDEState *m = info->opaque; | |
3542 | + IDEState *s = m->ide_if->cur_drive; | |
3543 | + int64_t sector_num; | |
3544 | + int ret, n; | |
3545 | + | |
3546 | + if (s->is_cdrom) | |
3547 | + return pmac_atapi_read(info, cb); | |
3548 | + | |
3549 | + info->buf = s->io_buffer; | |
3550 | + info->buf_pos = 0; | |
3551 | + while (info->buf_pos < info->len && s->nsector > 0) { | |
3552 | + | |
3553 | + sector_num = ide_get_sector(s); | |
3554 | + | |
3555 | + n = s->nsector; | |
3556 | + if (n > IDE_DMA_BUF_SECTORS) | |
3557 | + n = IDE_DMA_BUF_SECTORS; | |
3558 | + | |
3559 | + info->buf_len = n << 9; | |
3560 | + if (info->buf_pos + info->buf_len > info->len) | |
3561 | + info->buf_len = info->len - info->buf_pos; | |
3562 | + n = info->buf_len >> 9; | |
3563 | + | |
3564 | + if (s->is_read) { | |
3565 | + ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); | |
3566 | + if (ret == 0) | |
3567 | + cb(info); | |
3568 | + } else { | |
3569 | + cb(info); | |
3570 | + ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); | |
3571 | + } | |
3572 | + | |
3573 | + if (ret != 0) { | |
3574 | + ide_rw_error(s); | |
3575 | + return info->buf_pos; | |
3576 | + } | |
3577 | + | |
3578 | + info->buf_pos += n << 9; | |
3579 | + ide_set_sector(s, sector_num + n); | |
3580 | + s->nsector -= n; | |
3581 | + } | |
3582 | + | |
3583 | + if (s->nsector <= 0) { | |
3584 | + s->status = READY_STAT | SEEK_STAT; | |
3585 | + ide_set_irq(s); | |
3586 | + } | |
3587 | + | |
3588 | + return info->buf_pos; | |
3589 | +} | |
3590 | + | |
3479 | 3591 | /* PowerMac IDE memory IO */ |
3480 | 3592 | static void pmac_ide_writeb (void *opaque, |
3481 | 3593 | target_phys_addr_t addr, uint32_t val) |
3482 | 3594 | { |
3595 | + MACIOIDEState *d = opaque; | |
3596 | + | |
3483 | 3597 | addr = (addr & 0xFFF) >> 4; |
3484 | 3598 | switch (addr) { |
3485 | 3599 | case 1 ... 7: |
3486 | - ide_ioport_write(opaque, addr, val); | |
3600 | + ide_ioport_write(d->ide_if, addr, val); | |
3487 | 3601 | break; |
3488 | 3602 | case 8: |
3489 | 3603 | case 22: |
3490 | - ide_cmd_write(opaque, 0, val); | |
3604 | + ide_cmd_write(d->ide_if, 0, val); | |
3491 | 3605 | break; |
3492 | 3606 | default: |
3493 | 3607 | break; |
... | ... | @@ -3497,15 +3611,16 @@ static void pmac_ide_writeb (void *opaque, |
3497 | 3611 | static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) |
3498 | 3612 | { |
3499 | 3613 | uint8_t retval; |
3614 | + MACIOIDEState *d = opaque; | |
3500 | 3615 | |
3501 | 3616 | addr = (addr & 0xFFF) >> 4; |
3502 | 3617 | switch (addr) { |
3503 | 3618 | case 1 ... 7: |
3504 | - retval = ide_ioport_read(opaque, addr); | |
3619 | + retval = ide_ioport_read(d->ide_if, addr); | |
3505 | 3620 | break; |
3506 | 3621 | case 8: |
3507 | 3622 | case 22: |
3508 | - retval = ide_status_read(opaque, 0); | |
3623 | + retval = ide_status_read(d->ide_if, 0); | |
3509 | 3624 | break; |
3510 | 3625 | default: |
3511 | 3626 | retval = 0xFF; |
... | ... | @@ -3517,22 +3632,25 @@ static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) |
3517 | 3632 | static void pmac_ide_writew (void *opaque, |
3518 | 3633 | target_phys_addr_t addr, uint32_t val) |
3519 | 3634 | { |
3635 | + MACIOIDEState *d = opaque; | |
3636 | + | |
3520 | 3637 | addr = (addr & 0xFFF) >> 4; |
3521 | 3638 | #ifdef TARGET_WORDS_BIGENDIAN |
3522 | 3639 | val = bswap16(val); |
3523 | 3640 | #endif |
3524 | 3641 | if (addr == 0) { |
3525 | - ide_data_writew(opaque, 0, val); | |
3642 | + ide_data_writew(d->ide_if, 0, val); | |
3526 | 3643 | } |
3527 | 3644 | } |
3528 | 3645 | |
3529 | 3646 | static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) |
3530 | 3647 | { |
3531 | 3648 | uint16_t retval; |
3649 | + MACIOIDEState *d = opaque; | |
3532 | 3650 | |
3533 | 3651 | addr = (addr & 0xFFF) >> 4; |
3534 | 3652 | if (addr == 0) { |
3535 | - retval = ide_data_readw(opaque, 0); | |
3653 | + retval = ide_data_readw(d->ide_if, 0); | |
3536 | 3654 | } else { |
3537 | 3655 | retval = 0xFFFF; |
3538 | 3656 | } |
... | ... | @@ -3545,22 +3663,25 @@ static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) |
3545 | 3663 | static void pmac_ide_writel (void *opaque, |
3546 | 3664 | target_phys_addr_t addr, uint32_t val) |
3547 | 3665 | { |
3666 | + MACIOIDEState *d = opaque; | |
3667 | + | |
3548 | 3668 | addr = (addr & 0xFFF) >> 4; |
3549 | 3669 | #ifdef TARGET_WORDS_BIGENDIAN |
3550 | 3670 | val = bswap32(val); |
3551 | 3671 | #endif |
3552 | 3672 | if (addr == 0) { |
3553 | - ide_data_writel(opaque, 0, val); | |
3673 | + ide_data_writel(d->ide_if, 0, val); | |
3554 | 3674 | } |
3555 | 3675 | } |
3556 | 3676 | |
3557 | 3677 | static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr) |
3558 | 3678 | { |
3559 | 3679 | uint32_t retval; |
3680 | + MACIOIDEState *d = opaque; | |
3560 | 3681 | |
3561 | 3682 | addr = (addr & 0xFFF) >> 4; |
3562 | 3683 | if (addr == 0) { |
3563 | - retval = ide_data_readl(opaque, 0); | |
3684 | + retval = ide_data_readl(d->ide_if, 0); | |
3564 | 3685 | } else { |
3565 | 3686 | retval = 0xFFFFFFFF; |
3566 | 3687 | } |
... | ... | @@ -3584,7 +3705,8 @@ static CPUReadMemoryFunc *pmac_ide_read[] = { |
3584 | 3705 | |
3585 | 3706 | static void pmac_ide_save(QEMUFile *f, void *opaque) |
3586 | 3707 | { |
3587 | - IDEState *s = (IDEState *)opaque; | |
3708 | + MACIOIDEState *d = opaque; | |
3709 | + IDEState *s = d->ide_if; | |
3588 | 3710 | uint8_t drive1_selected; |
3589 | 3711 | unsigned int i; |
3590 | 3712 | |
... | ... | @@ -3601,7 +3723,8 @@ static void pmac_ide_save(QEMUFile *f, void *opaque) |
3601 | 3723 | |
3602 | 3724 | static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id) |
3603 | 3725 | { |
3604 | - IDEState *s = (IDEState *)opaque; | |
3726 | + MACIOIDEState *d = opaque; | |
3727 | + IDEState *s = d->ide_if; | |
3605 | 3728 | uint8_t drive1_selected; |
3606 | 3729 | unsigned int i; |
3607 | 3730 | |
... | ... | @@ -3622,7 +3745,8 @@ static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id) |
3622 | 3745 | |
3623 | 3746 | static void pmac_ide_reset(void *opaque) |
3624 | 3747 | { |
3625 | - IDEState *s = (IDEState *)opaque; | |
3748 | + MACIOIDEState *d = opaque; | |
3749 | + IDEState *s = d->ide_if; | |
3626 | 3750 | |
3627 | 3751 | ide_reset(&s[0]); |
3628 | 3752 | ide_reset(&s[1]); |
... | ... | @@ -3631,21 +3755,29 @@ static void pmac_ide_reset(void *opaque) |
3631 | 3755 | /* hd_table must contain 4 block drivers */ |
3632 | 3756 | /* PowerMac uses memory mapped registers, not I/O. Return the memory |
3633 | 3757 | I/O index to access the ide. */ |
3634 | -int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq) | |
3758 | +int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq, | |
3759 | + void *dbdma, int channel, qemu_irq dma_irq) | |
3635 | 3760 | { |
3636 | - IDEState *ide_if; | |
3761 | + MACIOIDEState *d; | |
3637 | 3762 | int pmac_ide_memory; |
3638 | 3763 | |
3639 | - ide_if = qemu_mallocz(sizeof(IDEState) * 2); | |
3640 | - ide_init2(&ide_if[0], hd_table[0], hd_table[1], irq); | |
3764 | + d = qemu_mallocz(sizeof(MACIOIDEState)); | |
3765 | + ide_init2(d->ide_if, hd_table[0], hd_table[1], irq); | |
3766 | + | |
3767 | + if (dbdma) { | |
3768 | + d->dbdma = dbdma; | |
3769 | + DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, d); | |
3770 | + } | |
3641 | 3771 | |
3642 | 3772 | pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, |
3643 | - pmac_ide_write, &ide_if[0]); | |
3644 | - register_savevm("ide", 0, 1, pmac_ide_save, pmac_ide_load, &ide_if[0]); | |
3645 | - qemu_register_reset(pmac_ide_reset, &ide_if[0]); | |
3646 | - pmac_ide_reset(&ide_if[0]); | |
3773 | + pmac_ide_write, d); | |
3774 | + register_savevm("ide", 0, 1, pmac_ide_save, pmac_ide_load, d); | |
3775 | + qemu_register_reset(pmac_ide_reset, d); | |
3776 | + pmac_ide_reset(d); | |
3777 | + | |
3647 | 3778 | return pmac_ide_memory; |
3648 | 3779 | } |
3780 | +#endif /* TARGET_PPC */ | |
3649 | 3781 | |
3650 | 3782 | /***********************************************************/ |
3651 | 3783 | /* MMIO based ide port | ... | ... |
hw/ppc_chrp.c
... | ... | @@ -284,8 +284,8 @@ static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size, |
284 | 284 | } |
285 | 285 | dbdma = DBDMA_init(&dbdma_mem_index); |
286 | 286 | #if 1 |
287 | - ide_mem_index[0] = pmac_ide_init(&hd[0], pic[0x13]); | |
288 | - ide_mem_index[1] = pmac_ide_init(&hd[2], pic[0x14]); | |
287 | + ide_mem_index[0] = pmac_ide_init(&hd[0], pic[0x13], dbdma, 0x14, pic[0x01]); | |
288 | + ide_mem_index[1] = pmac_ide_init(&hd[2], pic[0x14], dbdma, 0x16, pic[0x02]); | |
289 | 289 | #else |
290 | 290 | pci_cmd646_ide_init(pci_bus, &hd[0], 0); |
291 | 291 | #endif | ... | ... |
hw/ppc_mac.h
... | ... | @@ -48,7 +48,8 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index, |
48 | 48 | int nb_ide, int *ide_mem_index, int escc_mem_index); |
49 | 49 | |
50 | 50 | /* NewWorld PowerMac IDE */ |
51 | -int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq); | |
51 | +int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq, | |
52 | + void *dbdma, int channel, qemu_irq dma_irq); | |
52 | 53 | |
53 | 54 | /* Heathrow PIC */ |
54 | 55 | qemu_irq *heathrow_pic_init(int *pmem_index, | ... | ... |
hw/ppc_oldworld.c
... | ... | @@ -349,7 +349,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size, |
349 | 349 | dbdma = DBDMA_init(&dbdma_mem_index); |
350 | 350 | |
351 | 351 | ide_mem_index[0] = -1; |
352 | - ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D]); | |
352 | + ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]); | |
353 | 353 | |
354 | 354 | /* cuda also initialize ADB */ |
355 | 355 | cuda_init(&cuda_mem_index, pic[0x12]); | ... | ... |