mips_jazz.c 8.6 KB
Newer Older
A
aurel32 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
 * QEMU MIPS Jazz support
 *
 * Copyright (c) 2007-2008 Hervé Poussineau
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "hw.h"
#include "mips.h"
#include "pc.h"
#include "isa.h"
#include "fdc.h"
#include "sysemu.h"
#include "audio/audio.h"
#include "boards.h"
#include "net.h"
#include "scsi.h"
35
#include "mips-bios.h"
A
aurel32 已提交
36 37 38 39

enum jazz_model_e
{
    JAZZ_MAGNUM,
A
aurel32 已提交
40
    JAZZ_PICA61,
A
aurel32 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
};

static void main_cpu_reset(void *opaque)
{
    CPUState *env = opaque;
    cpu_reset(env);
}

static uint32_t rtc_readb(void *opaque, target_phys_addr_t addr)
{
    CPUState *env = opaque;
    return cpu_inw(env, 0x71);
}

static void rtc_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
    CPUState *env = opaque;
    cpu_outw(env, 0x71, val & 0xff);
}

static CPUReadMemoryFunc *rtc_read[3] = {
    rtc_readb,
    rtc_readb,
    rtc_readb,
};

static CPUWriteMemoryFunc *rtc_write[3] = {
    rtc_writeb,
    rtc_writeb,
    rtc_writeb,
};

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
static void dma_dummy_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
    /* Nothing to do. That is only to ensure that
     * the current DMA acknowledge cycle is completed. */
}

static CPUReadMemoryFunc *dma_dummy_read[3] = {
    NULL,
    NULL,
    NULL,
};

static CPUWriteMemoryFunc *dma_dummy_write[3] = {
    dma_dummy_writeb,
    dma_dummy_writeb,
    dma_dummy_writeb,
};

A
aurel32 已提交
91 92 93 94 95 96 97 98 99 100 101
#ifdef HAS_AUDIO
static void audio_init(qemu_irq *pic)
{
    struct soundhw *c;
    int audio_enabled = 0;

    for (c = soundhw; !audio_enabled && c->name; ++c) {
        audio_enabled = c->enabled;
    }

    if (audio_enabled) {
P
Paul Brook 已提交
102 103 104
        for (c = soundhw; c->name; ++c) {
            if (c->enabled) {
                if (c->isa) {
P
Paul Brook 已提交
105
                    c->init.init_isa(pic);
A
aurel32 已提交
106 107 108 109 110 111 112 113 114 115 116
                }
            }
        }
    }
}
#endif

#define MAGNUM_BIOS_SIZE_MAX 0x7e000
#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)

static
P
Paul Brook 已提交
117
void mips_jazz_init (ram_addr_t ram_size,
118
                     const char *cpu_model,
A
aurel32 已提交
119 120
                     enum jazz_model_e jazz_model)
{
P
Paul Brook 已提交
121
    char *filename;
A
aurel32 已提交
122 123 124
    int bios_size, n;
    CPUState *env;
    qemu_irq *rc4030, *i8259;
125
    rc4030_dma *dmas;
A
aurel32 已提交
126
    void* rc4030_opaque;
127
    int s_rtc, s_dma_dummy;
A
aurel32 已提交
128
    NICInfo *nd;
A
aurel32 已提交
129 130 131
    PITState *pit;
    BlockDriverState *fds[MAX_FD];
    qemu_irq esp_reset;
132 133
    ram_addr_t ram_offset;
    ram_addr_t bios_offset;
A
aurel32 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
        cpu_model = "24Kf";
#endif
    }
    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
149
    qemu_register_reset(main_cpu_reset, env);
A
aurel32 已提交
150 151

    /* allocate RAM */
152 153 154 155 156 157 158 159
    ram_offset = qemu_ram_alloc(ram_size);
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);

    bios_offset = qemu_ram_alloc(MAGNUM_BIOS_SIZE);
    cpu_register_physical_memory(0x1fc00000LL,
                                 MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);
    cpu_register_physical_memory(0xfff00000LL,
                                 MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);
A
aurel32 已提交
160 161

    /* load the BIOS image. */
162 163
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
P
Paul Brook 已提交
164 165 166 167 168 169 170 171
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = load_image_targphys(filename, 0xfff00000LL,
                                        MAGNUM_BIOS_SIZE);
        qemu_free(filename);
    } else {
        bios_size = -1;
    }
A
aurel32 已提交
172 173
    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
P
Paul Brook 已提交
174
                bios_name);
A
aurel32 已提交
175 176 177 178 179 180 181 182
        exit(1);
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);

    /* Chipset */
A
aurel32 已提交
183
    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas);
184
    s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL);
185
    cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);
A
aurel32 已提交
186 187 188

    /* ISA devices */
    i8259 = i8259_init(env->irq[4]);
189
    DMA_init(0);
A
aurel32 已提交
190 191 192 193 194 195 196 197 198 199
    pit = pit_init(0x40, i8259[0]);
    pcspk_init(pit);

    /* ISA IO space at 0x90000000 */
    isa_mmio_init(0x90000000, 0x01000000);
    isa_mem_base = 0x11000000;

    /* Video card */
    switch (jazz_model) {
    case JAZZ_MAGNUM:
P
Paul Brook 已提交
200
        g364fb_mm_init(0x40000000, 0x60000000, 0, rc4030[3]);
A
aurel32 已提交
201
        break;
A
aurel32 已提交
202
    case JAZZ_PICA61:
P
Paul Brook 已提交
203
        isa_vga_mm_init(0x40000000, 0x60000000, 0);
A
aurel32 已提交
204
        break;
A
aurel32 已提交
205 206 207 208 209
    default:
        break;
    }

    /* Network controller */
A
aurel32 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    for (n = 0; n < nb_nics; n++) {
        nd = &nd_table[n];
        if (!nd->model)
            nd->model = "dp83932";
        if (strcmp(nd->model, "dp83932") == 0) {
            dp83932_init(nd, 0x80001000, 2, rc4030[4],
                         rc4030_opaque, rc4030_dma_memory_rw);
            break;
        } else if (strcmp(nd->model, "?") == 0) {
            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
            exit(1);
        } else {
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
            exit(1);
        }
    }
A
aurel32 已提交
226 227

    /* SCSI adapter */
P
Paul Brook 已提交
228 229 230
    esp_init(0x80002000, 0,
             rc4030_dma_read, rc4030_dma_write, dmas[0],
             rc4030[5], &esp_reset);
A
aurel32 已提交
231 232 233 234 235 236 237

    /* Floppy */
    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
        fprintf(stderr, "qemu: too many floppy drives\n");
        exit(1);
    }
    for (n = 0; n < MAX_FD; n++) {
G
Gerd Hoffmann 已提交
238 239
        DriveInfo *dinfo = drive_get(IF_FLOPPY, 0, n);
        fds[n] = dinfo ? dinfo->bdrv : NULL;
A
aurel32 已提交
240 241 242 243
    }
    fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds);

    /* Real time clock */
244
    rtc_init(0x70, i8259[8], 1980);
245
    s_rtc = cpu_register_io_memory(rtc_read, rtc_write, env);
A
aurel32 已提交
246 247 248
    cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);

    /* Keyboard (i8042) */
A
aurel32 已提交
249
    i8042_mm_init(rc4030[6], rc4030[7], 0x80005000, 0x1000, 0x1);
A
aurel32 已提交
250 251 252

    /* Serial ports */
    if (serial_hds[0])
A
aurel32 已提交
253
        serial_mm_init(0x80006000, 0, rc4030[8], 8000000/16, serial_hds[0], 1);
A
aurel32 已提交
254
    if (serial_hds[1])
A
aurel32 已提交
255
        serial_mm_init(0x80007000, 0, rc4030[9], 8000000/16, serial_hds[1], 1);
A
aurel32 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

    /* Parallel port */
    if (parallel_hds[0])
        parallel_mm_init(0x80008000, 0, rc4030[0], parallel_hds[0]);

    /* Sound card */
    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
#ifdef HAS_AUDIO
    audio_init(i8259);
#endif

    /* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */
    ds1225y_init(0x80009000, "nvram");

    /* LED indicator */
271
    jazz_led_init(0x8000f000);
A
aurel32 已提交
272 273 274
}

static
P
Paul Brook 已提交
275
void mips_magnum_init (ram_addr_t ram_size,
276
                       const char *boot_device,
A
aurel32 已提交
277 278 279
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename, const char *cpu_model)
{
P
Paul Brook 已提交
280
    mips_jazz_init(ram_size, cpu_model, JAZZ_MAGNUM);
A
aurel32 已提交
281 282
}

A
aurel32 已提交
283
static
P
Paul Brook 已提交
284
void mips_pica61_init (ram_addr_t ram_size,
285
                       const char *boot_device,
A
aurel32 已提交
286 287 288
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename, const char *cpu_model)
{
P
Paul Brook 已提交
289
    mips_jazz_init(ram_size, cpu_model, JAZZ_PICA61);
A
aurel32 已提交
290 291
}

292
static QEMUMachine mips_magnum_machine = {
293 294 295
    .name = "magnum",
    .desc = "MIPS Magnum",
    .init = mips_magnum_init,
296
    .use_scsi = 1,
A
aurel32 已提交
297
};
A
aurel32 已提交
298

299
static QEMUMachine mips_pica61_machine = {
300 301 302
    .name = "pica61",
    .desc = "Acer Pica 61",
    .init = mips_pica61_init,
303
    .use_scsi = 1,
A
aurel32 已提交
304
};
305 306 307 308 309 310 311 312

static void mips_jazz_machine_init(void)
{
    qemu_register_machine(&mips_magnum_machine);
    qemu_register_machine(&mips_pica61_machine);
}

machine_init(mips_jazz_machine_init);