mips_r4k.c 7.6 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * QEMU/MIPS pseudo-board
 *
 * emulates a simple machine with ISA-like bus.
 * ISA IO space mapped to the 0x14000000 (PHYS) and
 * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
 * All peripherial devices are attached to this "bus" with
 * the standard PC ISA addresses.
*/
B
bellard 已提交
10 11
#include "vl.h"

T
ths 已提交
12
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
13
#define BIOS_FILENAME "mips_bios.bin"
14 15 16
#else
#define BIOS_FILENAME "mipsel_bios.bin"
#endif
T
ths 已提交
17

T
ths 已提交
18
#ifdef TARGET_MIPS64
T
ths 已提交
19
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
T
ths 已提交
20
#else
T
ths 已提交
21
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
T
ths 已提交
22
#endif
B
bellard 已提交
23

T
ths 已提交
24
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
B
bellard 已提交
25

P
pbrook 已提交
26 27 28 29
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };

T
ths 已提交
30 31 32
static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };

B
bellard 已提交
33 34
extern FILE *logfile;

35
static PITState *pit; /* PIT i8254 */
B
bellard 已提交
36

37
/*i8254 PIT is attached to the IRQ0 at PIC i8259 */
B
bellard 已提交
38

39 40 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
static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
			      uint32_t val)
{
    if ((addr & 0xffff) == 0 && val == 42)
        qemu_system_reset_request ();
    else if ((addr & 0xffff) == 4 && val == 42)
        qemu_system_shutdown_request ();
}

static uint32_t mips_qemu_readl (void *opaque, target_phys_addr_t addr)
{
    return 0;
}

static CPUWriteMemoryFunc *mips_qemu_write[] = {
    &mips_qemu_writel,
    &mips_qemu_writel,
    &mips_qemu_writel,
};

static CPUReadMemoryFunc *mips_qemu_read[] = {
    &mips_qemu_readl,
    &mips_qemu_readl,
    &mips_qemu_readl,
};

static int mips_qemu_iomemtype = 0;

T
ths 已提交
67 68 69 70
static void load_kernel (CPUState *env, int ram_size,
                         const char *kernel_filename,
                         const char *kernel_cmdline,
                         const char *initrd_filename)
71
{
T
ths 已提交
72
    int64_t entry, kernel_low, kernel_high;
73
    long kernel_size, initrd_size;
T
ths 已提交
74
    ram_addr_t initrd_offset;
75

T
ths 已提交
76 77
    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND,
                           &entry, &kernel_low, &kernel_high);
78 79
    if (kernel_size >= 0) {
        if ((entry & ~0x7fffffffULL) == 0x80000000)
T
ths 已提交
80
            entry = (int32_t)entry;
81
        env->PC[env->current_tc] = entry;
82
    } else {
83 84 85
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
                kernel_filename);
        exit(1);
86 87 88 89
    }

    /* load initrd */
    initrd_size = 0;
T
ths 已提交
90
    initrd_offset = 0;
91
    if (initrd_filename) {
T
ths 已提交
92 93 94 95 96 97 98 99 100 101 102 103
        initrd_size = get_image_size (initrd_filename);
        if (initrd_size > 0) {
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
            if (initrd_offset + initrd_size > ram_size) {
                fprintf(stderr,
                        "qemu: memory too small for initial ram disk '%s'\n",
                        initrd_filename);
                exit(1);
            }
            initrd_size = load_image(initrd_filename,
                                     phys_ram_base + initrd_offset);
        }
104 105 106 107 108 109 110 111 112 113 114
        if (initrd_size == (target_ulong) -1) {
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                    initrd_filename);
            exit(1);
        }
    }

    /* Store command line.  */
    if (initrd_size > 0) {
        int ret;
        ret = sprintf(phys_ram_base + (16 << 20) - 256,
T
ths 已提交
115
                      "rd_start=0x" TARGET_FMT_lx " rd_size=%li ",
T
ths 已提交
116
                      PHYS_TO_VIRT((uint32_t)initrd_offset),
117 118 119 120 121 122 123
                      initrd_size);
        strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
    }
    else {
        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
    }

T
ths 已提交
124 125
    *(int32_t *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
    *(int32_t *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
126 127 128 129 130 131
}

static void main_cpu_reset(void *opaque)
{
    CPUState *env = opaque;
    cpu_reset(env);
T
ths 已提交
132
    cpu_mips_register(env, NULL);
133 134 135 136 137

    if (env->kernel_filename)
        load_kernel (env, env->ram_size, env->kernel_filename,
                     env->kernel_cmdline, env->initrd_filename);
}
B
bellard 已提交
138

139
static
140
void mips_r4k_init (int ram_size, int vga_ram_size, const char *boot_device,
B
bellard 已提交
141 142
                    DisplayState *ds, const char **fd_filename, int snapshot,
                    const char *kernel_filename, const char *kernel_cmdline,
143
                    const char *initrd_filename, const char *cpu_model)
B
bellard 已提交
144 145 146
{
    char buf[1024];
    unsigned long bios_offset;
147
    int bios_size;
B
bellard 已提交
148
    CPUState *env;
T
ths 已提交
149
    RTCState *rtc_state;
P
pbrook 已提交
150
    int i;
151
    mips_def_t *def;
P
pbrook 已提交
152
    qemu_irq *i8259;
B
bellard 已提交
153

154 155
    /* init CPUs */
    if (cpu_model == NULL) {
T
ths 已提交
156
#ifdef TARGET_MIPS64
157 158
        cpu_model = "R4000";
#else
159
        cpu_model = "24Kf";
160 161 162 163
#endif
    }
    if (mips_find_by_name(cpu_model, &def) != 0)
        def = NULL;
B
bellard 已提交
164
    env = cpu_init();
165
    cpu_mips_register(env, def);
B
bellard 已提交
166
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
167
    qemu_register_reset(main_cpu_reset, env);
B
bellard 已提交
168

B
bellard 已提交
169 170
    /* allocate RAM */
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
B
bellard 已提交
171

172 173
    if (!mips_qemu_iomemtype) {
        mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
174
                                                     mips_qemu_write, NULL);
175 176 177
    }
    cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);

B
bellard 已提交
178 179 180 181
    /* Try to load a BIOS image. If this fails, we continue regardless,
       but initialize the hardware ourselves. When a kernel gets
       preloaded we also initialize the hardware, since the BIOS wasn't
       run. */
B
bellard 已提交
182
    bios_offset = ram_size + vga_ram_size;
183 184 185
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
186
    bios_size = load_image(buf, phys_ram_base + bios_offset);
T
ths 已提交
187
    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
T
ths 已提交
188
	cpu_register_physical_memory(0x1fc00000,
B
bellard 已提交
189 190 191 192 193
				     BIOS_SIZE, bios_offset | IO_MEM_ROM);
    } else {
	/* not fatal */
        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
		buf);
B
bellard 已提交
194
    }
B
bellard 已提交
195 196

    if (kernel_filename) {
197 198 199 200 201 202
        load_kernel (env, ram_size, kernel_filename, kernel_cmdline,
		     initrd_filename);
	env->ram_size = ram_size;
	env->kernel_filename = kernel_filename;
	env->kernel_cmdline = kernel_cmdline;
	env->initrd_filename = initrd_filename;
B
bellard 已提交
203 204
    }

205
    /* Init CPU internal devices */
P
pbrook 已提交
206
    cpu_mips_irq_init_cpu(env);
B
bellard 已提交
207
    cpu_mips_clock_init(env);
B
bellard 已提交
208 209
    cpu_mips_irqctrl_init();

P
pbrook 已提交
210 211 212 213
    /* The PIC is attached to the MIPS CPU INT0 pin */
    i8259 = i8259_init(env->irq[2]);

    rtc_state = rtc_init(0x70, i8259[8]);
T
ths 已提交
214

B
bellard 已提交
215
    /* Register 64 KB of ISA IO space at 0x14000000 */
P
pbrook 已提交
216
    isa_mmio_init(0x14000000, 0x00010000);
B
bellard 已提交
217 218
    isa_mem_base = 0x10000000;

P
pbrook 已提交
219
    pit = pit_init(0x40, i8259[0]);
T
ths 已提交
220

T
ths 已提交
221 222
    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
        if (serial_hds[i]) {
P
pbrook 已提交
223
            serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]);
T
ths 已提交
224 225 226
        }
    }

227
    isa_vga_init(ds, phys_ram_base + ram_size, ram_size,
B
bellard 已提交
228
                 vga_ram_size);
B
bellard 已提交
229

230 231 232
    if (nd_table[0].vlan) {
        if (nd_table[0].model == NULL
            || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
P
pbrook 已提交
233
            isa_ne2000_init(0x300, i8259[9], &nd_table[0]);
234 235 236
        } else if (strcmp(nd_table[0].model, "?") == 0) {
            fprintf(stderr, "qemu: Supported NICs: ne2k_isa\n");
            exit (1);
237 238 239 240 241
        } else {
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
            exit (1);
        }
    }
P
pbrook 已提交
242 243

    for(i = 0; i < 2; i++)
P
pbrook 已提交
244
        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
P
pbrook 已提交
245
                     bs_table[2 * i], bs_table[2 * i + 1]);
246

P
pbrook 已提交
247
    i8042_init(i8259[1], i8259[12], 0x60);
T
ths 已提交
248
    ds1225y_init(0x9000, "nvram");
B
bellard 已提交
249 250 251 252 253 254 255
}

QEMUMachine mips_machine = {
    "mips",
    "mips r4k platform",
    mips_r4k_init,
};