Statistics
| Branch: | Revision:

root / hw / mips_fulong2e.c @ b41e95d3

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