Revision b8842209 hw/ide.c
b/hw/ide.c | ||
---|---|---|
31 | 31 |
#include "block_int.h" |
32 | 32 |
#include "qemu-timer.h" |
33 | 33 |
#include "sysemu.h" |
34 |
#include "ppc_mac.h" |
|
35 |
#include "mac_dbdma.h" |
|
36 | 34 |
#include "sh.h" |
37 | 35 |
#include "dma.h" |
38 | 36 |
#include "ide-internal.h" |
... | ... | |
2701 | 2699 |
} |
2702 | 2700 |
} |
2703 | 2701 |
|
2704 |
#if defined(TARGET_PPC) |
|
2705 |
/***********************************************************/ |
|
2706 |
/* MacIO based PowerPC IDE */ |
|
2707 |
|
|
2708 |
typedef struct MACIOIDEState { |
|
2709 |
IDEBus bus; |
|
2710 |
BlockDriverAIOCB *aiocb; |
|
2711 |
} MACIOIDEState; |
|
2712 |
|
|
2713 |
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) |
|
2714 |
{ |
|
2715 |
DBDMA_io *io = opaque; |
|
2716 |
MACIOIDEState *m = io->opaque; |
|
2717 |
IDEState *s = idebus_active_if(&m->bus); |
|
2718 |
|
|
2719 |
if (ret < 0) { |
|
2720 |
m->aiocb = NULL; |
|
2721 |
qemu_sglist_destroy(&s->sg); |
|
2722 |
ide_atapi_io_error(s, ret); |
|
2723 |
io->dma_end(opaque); |
|
2724 |
return; |
|
2725 |
} |
|
2726 |
|
|
2727 |
if (s->io_buffer_size > 0) { |
|
2728 |
m->aiocb = NULL; |
|
2729 |
qemu_sglist_destroy(&s->sg); |
|
2730 |
|
|
2731 |
s->packet_transfer_size -= s->io_buffer_size; |
|
2732 |
|
|
2733 |
s->io_buffer_index += s->io_buffer_size; |
|
2734 |
s->lba += s->io_buffer_index >> 11; |
|
2735 |
s->io_buffer_index &= 0x7ff; |
|
2736 |
} |
|
2737 |
|
|
2738 |
if (s->packet_transfer_size <= 0) |
|
2739 |
ide_atapi_cmd_ok(s); |
|
2740 |
|
|
2741 |
if (io->len == 0) { |
|
2742 |
io->dma_end(opaque); |
|
2743 |
return; |
|
2744 |
} |
|
2745 |
|
|
2746 |
/* launch next transfer */ |
|
2747 |
|
|
2748 |
s->io_buffer_size = io->len; |
|
2749 |
|
|
2750 |
qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1); |
|
2751 |
qemu_sglist_add(&s->sg, io->addr, io->len); |
|
2752 |
io->addr += io->len; |
|
2753 |
io->len = 0; |
|
2754 |
|
|
2755 |
m->aiocb = dma_bdrv_read(s->bs, &s->sg, |
|
2756 |
(int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), |
|
2757 |
pmac_ide_atapi_transfer_cb, io); |
|
2758 |
if (!m->aiocb) { |
|
2759 |
qemu_sglist_destroy(&s->sg); |
|
2760 |
/* Note: media not present is the most likely case */ |
|
2761 |
ide_atapi_cmd_error(s, SENSE_NOT_READY, |
|
2762 |
ASC_MEDIUM_NOT_PRESENT); |
|
2763 |
io->dma_end(opaque); |
|
2764 |
return; |
|
2765 |
} |
|
2766 |
} |
|
2767 |
|
|
2768 |
static void pmac_ide_transfer_cb(void *opaque, int ret) |
|
2769 |
{ |
|
2770 |
DBDMA_io *io = opaque; |
|
2771 |
MACIOIDEState *m = io->opaque; |
|
2772 |
IDEState *s = idebus_active_if(&m->bus); |
|
2773 |
int n; |
|
2774 |
int64_t sector_num; |
|
2775 |
|
|
2776 |
if (ret < 0) { |
|
2777 |
m->aiocb = NULL; |
|
2778 |
qemu_sglist_destroy(&s->sg); |
|
2779 |
ide_dma_error(s); |
|
2780 |
io->dma_end(io); |
|
2781 |
return; |
|
2782 |
} |
|
2783 |
|
|
2784 |
sector_num = ide_get_sector(s); |
|
2785 |
if (s->io_buffer_size > 0) { |
|
2786 |
m->aiocb = NULL; |
|
2787 |
qemu_sglist_destroy(&s->sg); |
|
2788 |
n = (s->io_buffer_size + 0x1ff) >> 9; |
|
2789 |
sector_num += n; |
|
2790 |
ide_set_sector(s, sector_num); |
|
2791 |
s->nsector -= n; |
|
2792 |
} |
|
2793 |
|
|
2794 |
/* end of transfer ? */ |
|
2795 |
if (s->nsector == 0) { |
|
2796 |
s->status = READY_STAT | SEEK_STAT; |
|
2797 |
ide_set_irq(s); |
|
2798 |
} |
|
2799 |
|
|
2800 |
/* end of DMA ? */ |
|
2801 |
|
|
2802 |
if (io->len == 0) { |
|
2803 |
io->dma_end(io); |
|
2804 |
return; |
|
2805 |
} |
|
2806 |
|
|
2807 |
/* launch next transfer */ |
|
2808 |
|
|
2809 |
s->io_buffer_index = 0; |
|
2810 |
s->io_buffer_size = io->len; |
|
2811 |
|
|
2812 |
qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1); |
|
2813 |
qemu_sglist_add(&s->sg, io->addr, io->len); |
|
2814 |
io->addr += io->len; |
|
2815 |
io->len = 0; |
|
2816 |
|
|
2817 |
if (s->is_read) |
|
2818 |
m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, |
|
2819 |
pmac_ide_transfer_cb, io); |
|
2820 |
else |
|
2821 |
m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, |
|
2822 |
pmac_ide_transfer_cb, io); |
|
2823 |
if (!m->aiocb) |
|
2824 |
pmac_ide_transfer_cb(io, -1); |
|
2825 |
} |
|
2826 |
|
|
2827 |
static void pmac_ide_transfer(DBDMA_io *io) |
|
2828 |
{ |
|
2829 |
MACIOIDEState *m = io->opaque; |
|
2830 |
IDEState *s = idebus_active_if(&m->bus); |
|
2831 |
|
|
2832 |
s->io_buffer_size = 0; |
|
2833 |
if (s->is_cdrom) { |
|
2834 |
pmac_ide_atapi_transfer_cb(io, 0); |
|
2835 |
return; |
|
2836 |
} |
|
2837 |
|
|
2838 |
pmac_ide_transfer_cb(io, 0); |
|
2839 |
} |
|
2840 |
|
|
2841 |
static void pmac_ide_flush(DBDMA_io *io) |
|
2842 |
{ |
|
2843 |
MACIOIDEState *m = io->opaque; |
|
2844 |
|
|
2845 |
if (m->aiocb) |
|
2846 |
qemu_aio_flush(); |
|
2847 |
} |
|
2848 |
|
|
2849 |
/* PowerMac IDE memory IO */ |
|
2850 |
static void pmac_ide_writeb (void *opaque, |
|
2851 |
target_phys_addr_t addr, uint32_t val) |
|
2852 |
{ |
|
2853 |
MACIOIDEState *d = opaque; |
|
2854 |
|
|
2855 |
addr = (addr & 0xFFF) >> 4; |
|
2856 |
switch (addr) { |
|
2857 |
case 1 ... 7: |
|
2858 |
ide_ioport_write(&d->bus, addr, val); |
|
2859 |
break; |
|
2860 |
case 8: |
|
2861 |
case 22: |
|
2862 |
ide_cmd_write(&d->bus, 0, val); |
|
2863 |
break; |
|
2864 |
default: |
|
2865 |
break; |
|
2866 |
} |
|
2867 |
} |
|
2868 |
|
|
2869 |
static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) |
|
2870 |
{ |
|
2871 |
uint8_t retval; |
|
2872 |
MACIOIDEState *d = opaque; |
|
2873 |
|
|
2874 |
addr = (addr & 0xFFF) >> 4; |
|
2875 |
switch (addr) { |
|
2876 |
case 1 ... 7: |
|
2877 |
retval = ide_ioport_read(&d->bus, addr); |
|
2878 |
break; |
|
2879 |
case 8: |
|
2880 |
case 22: |
|
2881 |
retval = ide_status_read(&d->bus, 0); |
|
2882 |
break; |
|
2883 |
default: |
|
2884 |
retval = 0xFF; |
|
2885 |
break; |
|
2886 |
} |
|
2887 |
return retval; |
|
2888 |
} |
|
2889 |
|
|
2890 |
static void pmac_ide_writew (void *opaque, |
|
2891 |
target_phys_addr_t addr, uint32_t val) |
|
2892 |
{ |
|
2893 |
MACIOIDEState *d = opaque; |
|
2894 |
|
|
2895 |
addr = (addr & 0xFFF) >> 4; |
|
2896 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
2897 |
val = bswap16(val); |
|
2898 |
#endif |
|
2899 |
if (addr == 0) { |
|
2900 |
ide_data_writew(&d->bus, 0, val); |
|
2901 |
} |
|
2902 |
} |
|
2903 |
|
|
2904 |
static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) |
|
2905 |
{ |
|
2906 |
uint16_t retval; |
|
2907 |
MACIOIDEState *d = opaque; |
|
2908 |
|
|
2909 |
addr = (addr & 0xFFF) >> 4; |
|
2910 |
if (addr == 0) { |
|
2911 |
retval = ide_data_readw(&d->bus, 0); |
|
2912 |
} else { |
|
2913 |
retval = 0xFFFF; |
|
2914 |
} |
|
2915 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
2916 |
retval = bswap16(retval); |
|
2917 |
#endif |
|
2918 |
return retval; |
|
2919 |
} |
|
2920 |
|
|
2921 |
static void pmac_ide_writel (void *opaque, |
|
2922 |
target_phys_addr_t addr, uint32_t val) |
|
2923 |
{ |
|
2924 |
MACIOIDEState *d = opaque; |
|
2925 |
|
|
2926 |
addr = (addr & 0xFFF) >> 4; |
|
2927 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
2928 |
val = bswap32(val); |
|
2929 |
#endif |
|
2930 |
if (addr == 0) { |
|
2931 |
ide_data_writel(&d->bus, 0, val); |
|
2932 |
} |
|
2933 |
} |
|
2934 |
|
|
2935 |
static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr) |
|
2936 |
{ |
|
2937 |
uint32_t retval; |
|
2938 |
MACIOIDEState *d = opaque; |
|
2939 |
|
|
2940 |
addr = (addr & 0xFFF) >> 4; |
|
2941 |
if (addr == 0) { |
|
2942 |
retval = ide_data_readl(&d->bus, 0); |
|
2943 |
} else { |
|
2944 |
retval = 0xFFFFFFFF; |
|
2945 |
} |
|
2946 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
2947 |
retval = bswap32(retval); |
|
2948 |
#endif |
|
2949 |
return retval; |
|
2950 |
} |
|
2951 |
|
|
2952 |
static CPUWriteMemoryFunc * const pmac_ide_write[] = { |
|
2953 |
pmac_ide_writeb, |
|
2954 |
pmac_ide_writew, |
|
2955 |
pmac_ide_writel, |
|
2956 |
}; |
|
2957 |
|
|
2958 |
static CPUReadMemoryFunc * const pmac_ide_read[] = { |
|
2959 |
pmac_ide_readb, |
|
2960 |
pmac_ide_readw, |
|
2961 |
pmac_ide_readl, |
|
2962 |
}; |
|
2963 |
|
|
2964 |
static void pmac_ide_save(QEMUFile *f, void *opaque) |
|
2965 |
{ |
|
2966 |
MACIOIDEState *d = opaque; |
|
2967 |
unsigned int i; |
|
2968 |
|
|
2969 |
/* per IDE interface data */ |
|
2970 |
idebus_save(f, &d->bus); |
|
2971 |
|
|
2972 |
/* per IDE drive data */ |
|
2973 |
for(i = 0; i < 2; i++) { |
|
2974 |
ide_save(f, &d->bus.ifs[i]); |
|
2975 |
} |
|
2976 |
} |
|
2977 |
|
|
2978 |
static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id) |
|
2979 |
{ |
|
2980 |
MACIOIDEState *d = opaque; |
|
2981 |
unsigned int i; |
|
2982 |
|
|
2983 |
if (version_id != 1 && version_id != 3) |
|
2984 |
return -EINVAL; |
|
2985 |
|
|
2986 |
/* per IDE interface data */ |
|
2987 |
idebus_load(f, &d->bus, version_id); |
|
2988 |
|
|
2989 |
/* per IDE drive data */ |
|
2990 |
for(i = 0; i < 2; i++) { |
|
2991 |
ide_load(f, &d->bus.ifs[i], version_id); |
|
2992 |
} |
|
2993 |
return 0; |
|
2994 |
} |
|
2995 |
|
|
2996 |
static void pmac_ide_reset(void *opaque) |
|
2997 |
{ |
|
2998 |
MACIOIDEState *d = opaque; |
|
2999 |
|
|
3000 |
ide_reset(d->bus.ifs +0); |
|
3001 |
ide_reset(d->bus.ifs +1); |
|
3002 |
} |
|
3003 |
|
|
3004 |
/* hd_table must contain 4 block drivers */ |
|
3005 |
/* PowerMac uses memory mapped registers, not I/O. Return the memory |
|
3006 |
I/O index to access the ide. */ |
|
3007 |
int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq, |
|
3008 |
void *dbdma, int channel, qemu_irq dma_irq) |
|
3009 |
{ |
|
3010 |
MACIOIDEState *d; |
|
3011 |
int pmac_ide_memory; |
|
3012 |
|
|
3013 |
d = qemu_mallocz(sizeof(MACIOIDEState)); |
|
3014 |
ide_init2(&d->bus, hd_table[0], hd_table[1], irq); |
|
3015 |
|
|
3016 |
if (dbdma) |
|
3017 |
DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d); |
|
3018 |
|
|
3019 |
pmac_ide_memory = cpu_register_io_memory(pmac_ide_read, |
|
3020 |
pmac_ide_write, d); |
|
3021 |
register_savevm("ide", 0, 3, pmac_ide_save, pmac_ide_load, d); |
|
3022 |
qemu_register_reset(pmac_ide_reset, d); |
|
3023 |
pmac_ide_reset(d); |
|
3024 |
|
|
3025 |
return pmac_ide_memory; |
|
3026 |
} |
|
3027 |
#endif /* TARGET_PPC */ |
|
3028 |
|
|
3029 | 2702 |
/***********************************************************/ |
3030 | 2703 |
/* MMIO based ide port |
3031 | 2704 |
* This emulates IDE device connected directly to the CPU bus without |
Also available in: Unified diff