Statistics
| Branch: | Revision:

root / hw / mips_fulong2e.c @ a1bc20df

History | View | Annotate | Download (12.8 kB)

1 051c190b Huacai Chen
/*
2 051c190b Huacai Chen
 * QEMU fulong 2e mini pc support
3 051c190b Huacai Chen
 *
4 051c190b Huacai Chen
 * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
5 051c190b Huacai Chen
 * Copyright (c) 2009 chenming (chenming@rdc.faw.com.cn)
6 051c190b Huacai Chen
 * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com)
7 051c190b Huacai Chen
 * This code is licensed under the GNU GPL v2.
8 6b620ca3 Paolo Bonzini
 *
9 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
10 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
11 051c190b Huacai Chen
 */
12 051c190b Huacai Chen
13 051c190b Huacai Chen
/*
14 051c190b Huacai Chen
 * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
15 051c190b Huacai Chen
 * http://www.linux-mips.org/wiki/Fulong
16 051c190b Huacai Chen
 *
17 051c190b Huacai Chen
 * Loongson 2e user manual:
18 051c190b Huacai Chen
 * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
19 051c190b Huacai Chen
 */
20 051c190b Huacai Chen
21 051c190b Huacai Chen
#include "hw.h"
22 051c190b Huacai Chen
#include "pc.h"
23 488cb996 Gerd Hoffmann
#include "serial.h"
24 051c190b Huacai Chen
#include "fdc.h"
25 051c190b Huacai Chen
#include "net.h"
26 051c190b Huacai Chen
#include "boards.h"
27 051c190b Huacai Chen
#include "smbus.h"
28 051c190b Huacai Chen
#include "block.h"
29 051c190b Huacai Chen
#include "flash.h"
30 051c190b Huacai Chen
#include "mips.h"
31 051c190b Huacai Chen
#include "mips_cpudevs.h"
32 051c190b Huacai Chen
#include "pci.h"
33 051c190b Huacai Chen
#include "qemu-char.h"
34 051c190b Huacai Chen
#include "sysemu.h"
35 051c190b Huacai Chen
#include "audio/audio.h"
36 051c190b Huacai Chen
#include "qemu-log.h"
37 051c190b Huacai Chen
#include "loader.h"
38 051c190b Huacai Chen
#include "mips-bios.h"
39 051c190b Huacai Chen
#include "ide.h"
40 051c190b Huacai Chen
#include "elf.h"
41 051c190b Huacai Chen
#include "vt82c686.h"
42 051c190b Huacai Chen
#include "mc146818rtc.h"
43 b1277b03 Jan Kiszka
#include "i8254.h"
44 2446333c Blue Swirl
#include "blockdev.h"
45 13faf2a7 Avi Kivity
#include "exec-memory.h"
46 051c190b Huacai Chen
47 051c190b Huacai Chen
#define DEBUG_FULONG2E_INIT
48 051c190b Huacai Chen
49 051c190b Huacai Chen
#define ENVP_ADDR       0x80002000l
50 051c190b Huacai Chen
#define ENVP_NB_ENTRIES                 16
51 051c190b Huacai Chen
#define ENVP_ENTRY_SIZE                 256
52 051c190b Huacai Chen
53 051c190b Huacai Chen
#define MAX_IDE_BUS 2
54 051c190b Huacai Chen
55 051c190b Huacai Chen
/*
56 051c190b Huacai Chen
 * PMON is not part of qemu and released with BSD license, anyone
57 051c190b Huacai Chen
 * who want to build a pmon binary please first git-clone the source
58 051c190b Huacai Chen
 * from the git repository at:
59 051c190b Huacai Chen
 * http://www.loongson.cn/support/git/pmon
60 051c190b Huacai Chen
 * Then follow the "Compile Guide" available at:
61 051c190b Huacai Chen
 * http://dev.lemote.com/code/pmon
62 051c190b Huacai Chen
 *
63 051c190b Huacai Chen
 * Notes:
64 051c190b Huacai Chen
 * 1, don't use the source at http://dev.lemote.com/http_git/pmon.git
65 051c190b Huacai Chen
 * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware"
66 051c190b Huacai Chen
 * in the "Compile Guide".
67 051c190b Huacai Chen
 */
68 051c190b Huacai Chen
#define FULONG_BIOSNAME "pmon_fulong2e.bin"
69 051c190b Huacai Chen
70 051c190b Huacai Chen
/* PCI SLOT in fulong 2e */
71 051c190b Huacai Chen
#define FULONG2E_VIA_SLOT        5
72 051c190b Huacai Chen
#define FULONG2E_ATI_SLOT        6
73 051c190b Huacai Chen
#define FULONG2E_RTL8139_SLOT    7
74 051c190b Huacai Chen
75 64d7e9a4 Blue Swirl
static ISADevice *pit;
76 051c190b Huacai Chen
77 051c190b Huacai Chen
static struct _loaderparams {
78 051c190b Huacai Chen
    int ram_size;
79 051c190b Huacai Chen
    const char *kernel_filename;
80 051c190b Huacai Chen
    const char *kernel_cmdline;
81 051c190b Huacai Chen
    const char *initrd_filename;
82 051c190b Huacai Chen
} loaderparams;
83 051c190b Huacai Chen
84 8b7968f7 Stefan Weil
static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
85 8b7968f7 Stefan Weil
                                        const char *string, ...)
86 051c190b Huacai Chen
{
87 051c190b Huacai Chen
    va_list ap;
88 051c190b Huacai Chen
    int32_t table_addr;
89 051c190b Huacai Chen
90 051c190b Huacai Chen
    if (index >= ENVP_NB_ENTRIES)
91 051c190b Huacai Chen
        return;
92 051c190b Huacai Chen
93 051c190b Huacai Chen
    if (string == NULL) {
94 051c190b Huacai Chen
        prom_buf[index] = 0;
95 051c190b Huacai Chen
        return;
96 051c190b Huacai Chen
    }
97 051c190b Huacai Chen
98 051c190b Huacai Chen
    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
99 051c190b Huacai Chen
    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
100 051c190b Huacai Chen
101 051c190b Huacai Chen
    va_start(ap, string);
102 051c190b Huacai Chen
    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
103 051c190b Huacai Chen
    va_end(ap);
104 051c190b Huacai Chen
}
105 051c190b Huacai Chen
106 61c56c8c Andreas Färber
static int64_t load_kernel (CPUMIPSState *env)
107 051c190b Huacai Chen
{
108 051c190b Huacai Chen
    int64_t kernel_entry, kernel_low, kernel_high;
109 051c190b Huacai Chen
    int index = 0;
110 051c190b Huacai Chen
    long initrd_size;
111 051c190b Huacai Chen
    ram_addr_t initrd_offset;
112 051c190b Huacai Chen
    uint32_t *prom_buf;
113 051c190b Huacai Chen
    long prom_size;
114 051c190b Huacai Chen
115 051c190b Huacai Chen
    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
116 051c190b Huacai Chen
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
117 051c190b Huacai Chen
                 (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
118 051c190b Huacai Chen
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
119 051c190b Huacai Chen
                loaderparams.kernel_filename);
120 051c190b Huacai Chen
        exit(1);
121 051c190b Huacai Chen
    }
122 051c190b Huacai Chen
123 051c190b Huacai Chen
    /* load initrd */
124 051c190b Huacai Chen
    initrd_size = 0;
125 051c190b Huacai Chen
    initrd_offset = 0;
126 051c190b Huacai Chen
    if (loaderparams.initrd_filename) {
127 051c190b Huacai Chen
        initrd_size = get_image_size (loaderparams.initrd_filename);
128 051c190b Huacai Chen
        if (initrd_size > 0) {
129 051c190b Huacai Chen
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
130 051c190b Huacai Chen
            if (initrd_offset + initrd_size > ram_size) {
131 051c190b Huacai Chen
                fprintf(stderr,
132 051c190b Huacai Chen
                        "qemu: memory too small for initial ram disk '%s'\n",
133 051c190b Huacai Chen
                        loaderparams.initrd_filename);
134 051c190b Huacai Chen
                exit(1);
135 051c190b Huacai Chen
            }
136 051c190b Huacai Chen
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
137 051c190b Huacai Chen
                                     initrd_offset, ram_size - initrd_offset);
138 051c190b Huacai Chen
        }
139 051c190b Huacai Chen
        if (initrd_size == (target_ulong) -1) {
140 051c190b Huacai Chen
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
141 051c190b Huacai Chen
                    loaderparams.initrd_filename);
142 051c190b Huacai Chen
            exit(1);
143 051c190b Huacai Chen
        }
144 051c190b Huacai Chen
    }
145 051c190b Huacai Chen
146 051c190b Huacai Chen
    /* Setup prom parameters. */
147 051c190b Huacai Chen
    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
148 7267c094 Anthony Liguori
    prom_buf = g_malloc(prom_size);
149 051c190b Huacai Chen
150 1ed1139d Stefan Weil
    prom_set(prom_buf, index++, "%s", loaderparams.kernel_filename);
151 051c190b Huacai Chen
    if (initrd_size > 0) {
152 1ed1139d Stefan Weil
        prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
153 051c190b Huacai Chen
                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
154 051c190b Huacai Chen
                 loaderparams.kernel_cmdline);
155 051c190b Huacai Chen
    } else {
156 1ed1139d Stefan Weil
        prom_set(prom_buf, index++, "%s", loaderparams.kernel_cmdline);
157 051c190b Huacai Chen
    }
158 051c190b Huacai Chen
159 051c190b Huacai Chen
    /* Setup minimum environment variables */
160 051c190b Huacai Chen
    prom_set(prom_buf, index++, "busclock=33000000");
161 051c190b Huacai Chen
    prom_set(prom_buf, index++, "cpuclock=100000000");
162 051c190b Huacai Chen
    prom_set(prom_buf, index++, "memsize=%i", loaderparams.ram_size/1024/1024);
163 051c190b Huacai Chen
    prom_set(prom_buf, index++, "modetty0=38400n8r");
164 051c190b Huacai Chen
    prom_set(prom_buf, index++, NULL);
165 051c190b Huacai Chen
166 051c190b Huacai Chen
    rom_add_blob_fixed("prom", prom_buf, prom_size,
167 051c190b Huacai Chen
                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
168 051c190b Huacai Chen
169 051c190b Huacai Chen
    return kernel_entry;
170 051c190b Huacai Chen
}
171 051c190b Huacai Chen
172 61c56c8c Andreas Färber
static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr)
173 051c190b Huacai Chen
{
174 051c190b Huacai Chen
    uint32_t *p;
175 051c190b Huacai Chen
176 051c190b Huacai Chen
    /* Small bootloader */
177 051c190b Huacai Chen
    p = (uint32_t *) base;
178 051c190b Huacai Chen
179 051c190b Huacai Chen
    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
180 051c190b Huacai Chen
    stl_raw(p++, 0x00000000);                                      /* nop */
181 051c190b Huacai Chen
182 051c190b Huacai Chen
    /* Second part of the bootloader */
183 051c190b Huacai Chen
    p = (uint32_t *) (base + 0x040);
184 051c190b Huacai Chen
185 051c190b Huacai Chen
    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
186 051c190b Huacai Chen
    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
187 051c190b Huacai Chen
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
188 051c190b Huacai Chen
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
189 051c190b Huacai Chen
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
190 051c190b Huacai Chen
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
191 051c190b Huacai Chen
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
192 051c190b Huacai Chen
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
193 051c190b Huacai Chen
    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
194 051c190b Huacai Chen
    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
195 051c190b Huacai Chen
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
196 051c190b Huacai Chen
    stl_raw(p++, 0x00000000);                                      /* nop */
197 051c190b Huacai Chen
}
198 051c190b Huacai Chen
199 051c190b Huacai Chen
200 051c190b Huacai Chen
static void main_cpu_reset(void *opaque)
201 051c190b Huacai Chen
{
202 800cf598 Andreas Färber
    MIPSCPU *cpu = opaque;
203 800cf598 Andreas Färber
    CPUMIPSState *env = &cpu->env;
204 051c190b Huacai Chen
205 800cf598 Andreas Färber
    cpu_reset(CPU(cpu));
206 051c190b Huacai Chen
    /* TODO: 2E reset stuff */
207 051c190b Huacai Chen
    if (loaderparams.kernel_filename) {
208 051c190b Huacai Chen
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
209 051c190b Huacai Chen
    }
210 051c190b Huacai Chen
}
211 051c190b Huacai Chen
212 051c190b Huacai Chen
uint8_t eeprom_spd[0x80] = {
213 051c190b Huacai Chen
    0x80,0x08,0x07,0x0d,0x09,0x02,0x40,0x00,0x04,0x70,
214 051c190b Huacai Chen
    0x70,0x00,0x82,0x10,0x00,0x01,0x0e,0x04,0x0c,0x01,
215 051c190b Huacai Chen
    0x02,0x20,0x80,0x75,0x70,0x00,0x00,0x50,0x3c,0x50,
216 051c190b Huacai Chen
    0x2d,0x20,0xb0,0xb0,0x50,0x50,0x00,0x00,0x00,0x00,
217 051c190b Huacai Chen
    0x00,0x41,0x48,0x3c,0x32,0x75,0x00,0x00,0x00,0x00,
218 051c190b Huacai Chen
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
219 051c190b Huacai Chen
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
220 051c190b Huacai Chen
    0x00,0x00,0x00,0x9c,0x7b,0x07,0x00,0x00,0x00,0x00,
221 051c190b Huacai Chen
    0x00,0x00,0x00,0x00,0x48,0x42,0x35,0x34,0x41,0x32,
222 051c190b Huacai Chen
    0x35,0x36,0x38,0x4b,0x4e,0x2d,0x41,0x37,0x35,0x42,
223 051c190b Huacai Chen
    0x20,0x30,0x20
224 051c190b Huacai Chen
};
225 051c190b Huacai Chen
226 051c190b Huacai Chen
/* Audio support */
227 051c190b Huacai Chen
static void audio_init (PCIBus *pci_bus)
228 051c190b Huacai Chen
{
229 7899f799 Isaku Yamahata
    vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
230 7899f799 Isaku Yamahata
    vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
231 051c190b Huacai Chen
}
232 051c190b Huacai Chen
233 051c190b Huacai Chen
/* Network support */
234 051c190b Huacai Chen
static void network_init (void)
235 051c190b Huacai Chen
{
236 051c190b Huacai Chen
    int i;
237 051c190b Huacai Chen
238 051c190b Huacai Chen
    for(i = 0; i < nb_nics; i++) {
239 051c190b Huacai Chen
        NICInfo *nd = &nd_table[i];
240 051c190b Huacai Chen
        const char *default_devaddr = NULL;
241 051c190b Huacai Chen
242 051c190b Huacai Chen
        if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
243 051c190b Huacai Chen
            /* The fulong board has a RTL8139 card using PCI SLOT 7 */
244 051c190b Huacai Chen
            default_devaddr = "07";
245 051c190b Huacai Chen
        }
246 051c190b Huacai Chen
247 051c190b Huacai Chen
        pci_nic_init_nofail(nd, "rtl8139", default_devaddr);
248 051c190b Huacai Chen
    }
249 051c190b Huacai Chen
}
250 051c190b Huacai Chen
251 051c190b Huacai Chen
static void cpu_request_exit(void *opaque, int irq, int level)
252 051c190b Huacai Chen
{
253 61c56c8c Andreas Färber
    CPUMIPSState *env = cpu_single_env;
254 051c190b Huacai Chen
255 051c190b Huacai Chen
    if (env && level) {
256 051c190b Huacai Chen
        cpu_exit(env);
257 051c190b Huacai Chen
    }
258 051c190b Huacai Chen
}
259 051c190b Huacai Chen
260 5f072e1f Eduardo Habkost
static void mips_fulong2e_init(QEMUMachineInitArgs *args)
261 051c190b Huacai Chen
{
262 5f072e1f Eduardo Habkost
    ram_addr_t ram_size = args->ram_size;
263 5f072e1f Eduardo Habkost
    const char *cpu_model = args->cpu_model;
264 5f072e1f Eduardo Habkost
    const char *kernel_filename = args->kernel_filename;
265 5f072e1f Eduardo Habkost
    const char *kernel_cmdline = args->kernel_cmdline;
266 5f072e1f Eduardo Habkost
    const char *initrd_filename = args->initrd_filename;
267 051c190b Huacai Chen
    char *filename;
268 13faf2a7 Avi Kivity
    MemoryRegion *address_space_mem = get_system_memory();
269 13faf2a7 Avi Kivity
    MemoryRegion *ram = g_new(MemoryRegion, 1);
270 13faf2a7 Avi Kivity
    MemoryRegion *bios = g_new(MemoryRegion, 1);
271 093209cd Blue Swirl
    long bios_size;
272 051c190b Huacai Chen
    int64_t kernel_entry;
273 051c190b Huacai Chen
    qemu_irq *i8259;
274 051c190b Huacai Chen
    qemu_irq *cpu_exit_irq;
275 051c190b Huacai Chen
    PCIBus *pci_bus;
276 48a18b3c Hervé Poussineau
    ISABus *isa_bus;
277 051c190b Huacai Chen
    i2c_bus *smbus;
278 051c190b Huacai Chen
    int i;
279 051c190b Huacai Chen
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
280 f0f80366 Andreas Färber
    MIPSCPU *cpu;
281 61c56c8c Andreas Färber
    CPUMIPSState *env;
282 051c190b Huacai Chen
283 051c190b Huacai Chen
    /* init CPUs */
284 051c190b Huacai Chen
    if (cpu_model == NULL) {
285 051c190b Huacai Chen
        cpu_model = "Loongson-2E";
286 051c190b Huacai Chen
    }
287 f0f80366 Andreas Färber
    cpu = cpu_mips_init(cpu_model);
288 f0f80366 Andreas Färber
    if (cpu == NULL) {
289 051c190b Huacai Chen
        fprintf(stderr, "Unable to find CPU definition\n");
290 051c190b Huacai Chen
        exit(1);
291 051c190b Huacai Chen
    }
292 f0f80366 Andreas Färber
    env = &cpu->env;
293 051c190b Huacai Chen
294 800cf598 Andreas Färber
    qemu_register_reset(main_cpu_reset, cpu);
295 051c190b Huacai Chen
296 051c190b Huacai Chen
    /* fulong 2e has 256M ram. */
297 051c190b Huacai Chen
    ram_size = 256 * 1024 * 1024;
298 051c190b Huacai Chen
299 051c190b Huacai Chen
    /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */
300 051c190b Huacai Chen
    bios_size = 1024 * 1024;
301 051c190b Huacai Chen
302 051c190b Huacai Chen
    /* allocate RAM */
303 c5705a77 Avi Kivity
    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
304 c5705a77 Avi Kivity
    vmstate_register_ram_global(ram);
305 c5705a77 Avi Kivity
    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
306 c5705a77 Avi Kivity
    vmstate_register_ram_global(bios);
307 13faf2a7 Avi Kivity
    memory_region_set_readonly(bios, true);
308 051c190b Huacai Chen
309 13faf2a7 Avi Kivity
    memory_region_add_subregion(address_space_mem, 0, ram);
310 13faf2a7 Avi Kivity
    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
311 051c190b Huacai Chen
312 051c190b Huacai Chen
    /* We do not support flash operation, just loading pmon.bin as raw BIOS.
313 051c190b Huacai Chen
     * Please use -L to set the BIOS path and -bios to set bios name. */
314 051c190b Huacai Chen
315 051c190b Huacai Chen
    if (kernel_filename) {
316 051c190b Huacai Chen
        loaderparams.ram_size = ram_size;
317 051c190b Huacai Chen
        loaderparams.kernel_filename = kernel_filename;
318 051c190b Huacai Chen
        loaderparams.kernel_cmdline = kernel_cmdline;
319 051c190b Huacai Chen
        loaderparams.initrd_filename = initrd_filename;
320 051c190b Huacai Chen
        kernel_entry = load_kernel (env);
321 13faf2a7 Avi Kivity
        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
322 051c190b Huacai Chen
    } else {
323 33dd2983 Aurelien Jarno
        if (bios_name == NULL) {
324 33dd2983 Aurelien Jarno
                bios_name = FULONG_BIOSNAME;
325 051c190b Huacai Chen
        }
326 051c190b Huacai Chen
        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
327 051c190b Huacai Chen
        if (filename) {
328 051c190b Huacai Chen
            bios_size = load_image_targphys(filename, 0x1fc00000LL,
329 051c190b Huacai Chen
                                            BIOS_SIZE);
330 7267c094 Anthony Liguori
            g_free(filename);
331 051c190b Huacai Chen
        } else {
332 051c190b Huacai Chen
            bios_size = -1;
333 051c190b Huacai Chen
        }
334 051c190b Huacai Chen
335 33dd2983 Aurelien Jarno
        if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
336 33dd2983 Aurelien Jarno
            fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
337 051c190b Huacai Chen
            exit(1);
338 33dd2983 Aurelien Jarno
        }
339 051c190b Huacai Chen
    }
340 051c190b Huacai Chen
341 051c190b Huacai Chen
    /* Init internal devices */
342 051c190b Huacai Chen
    cpu_mips_irq_init_cpu(env);
343 051c190b Huacai Chen
    cpu_mips_clock_init(env);
344 051c190b Huacai Chen
345 051c190b Huacai Chen
    /* North bridge, Bonito --> IP2 */
346 051c190b Huacai Chen
    pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
347 051c190b Huacai Chen
348 051c190b Huacai Chen
    /* South bridge */
349 75717903 Isaku Yamahata
    ide_drive_get(hd, MAX_IDE_BUS);
350 051c190b Huacai Chen
351 c9940edb Hervé Poussineau
    isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
352 c9940edb Hervé Poussineau
    if (!isa_bus) {
353 b2bedb21 Stefan Weil
        fprintf(stderr, "vt82c686b_init error\n");
354 051c190b Huacai Chen
        exit(1);
355 051c190b Huacai Chen
    }
356 051c190b Huacai Chen
357 7e17a217 Jan Kiszka
    /* Interrupt controller */
358 7e17a217 Jan Kiszka
    /* The 8259 -> IP5  */
359 48a18b3c Hervé Poussineau
    i8259 = i8259_init(isa_bus, env->irq[5]);
360 48a18b3c Hervé Poussineau
    isa_bus_irqs(isa_bus, i8259);
361 7e17a217 Jan Kiszka
362 7899f799 Isaku Yamahata
    vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
363 afb9a60e Gerd Hoffmann
    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2),
364 afb9a60e Gerd Hoffmann
                      "vt82c686b-usb-uhci");
365 afb9a60e Gerd Hoffmann
    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3),
366 afb9a60e Gerd Hoffmann
                      "vt82c686b-usb-uhci");
367 051c190b Huacai Chen
368 7899f799 Isaku Yamahata
    smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
369 051c190b Huacai Chen
                              0xeee1, NULL);
370 051c190b Huacai Chen
    /* TODO: Populate SPD eeprom data.  */
371 a88df0b9 Isaku Yamahata
    smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
372 051c190b Huacai Chen
373 051c190b Huacai Chen
    /* init other devices */
374 319ba9f5 Jan Kiszka
    pit = pit_init(isa_bus, 0x40, 0, NULL);
375 051c190b Huacai Chen
    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
376 051c190b Huacai Chen
    DMA_init(0, cpu_exit_irq);
377 051c190b Huacai Chen
378 051c190b Huacai Chen
    /* Super I/O */
379 48a18b3c Hervé Poussineau
    isa_create_simple(isa_bus, "i8042");
380 051c190b Huacai Chen
381 48a18b3c Hervé Poussineau
    rtc_init(isa_bus, 2000, NULL);
382 051c190b Huacai Chen
383 051c190b Huacai Chen
    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
384 051c190b Huacai Chen
        if (serial_hds[i]) {
385 48a18b3c Hervé Poussineau
            serial_isa_init(isa_bus, i, serial_hds[i]);
386 051c190b Huacai Chen
        }
387 051c190b Huacai Chen
    }
388 051c190b Huacai Chen
389 051c190b Huacai Chen
    if (parallel_hds[0]) {
390 48a18b3c Hervé Poussineau
        parallel_init(isa_bus, 0, parallel_hds[0]);
391 051c190b Huacai Chen
    }
392 051c190b Huacai Chen
393 051c190b Huacai Chen
    /* Sound card */
394 051c190b Huacai Chen
    audio_init(pci_bus);
395 051c190b Huacai Chen
    /* Network card */
396 051c190b Huacai Chen
    network_init();
397 051c190b Huacai Chen
}
398 051c190b Huacai Chen
399 da665c99 Stefan Weil
static QEMUMachine mips_fulong2e_machine = {
400 051c190b Huacai Chen
    .name = "fulong2e",
401 051c190b Huacai Chen
    .desc = "Fulong 2e mini pc",
402 051c190b Huacai Chen
    .init = mips_fulong2e_init,
403 051c190b Huacai Chen
};
404 051c190b Huacai Chen
405 051c190b Huacai Chen
static void mips_fulong2e_machine_init(void)
406 051c190b Huacai Chen
{
407 051c190b Huacai Chen
    qemu_register_machine(&mips_fulong2e_machine);
408 051c190b Huacai Chen
}
409 051c190b Huacai Chen
410 051c190b Huacai Chen
machine_init(mips_fulong2e_machine_init);