Statistics
| Branch: | Revision:

root / hw / mips_fulong2e.c @ 09f1bbcd

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