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