Statistics
| Branch: | Revision:

root / hw / mips_r4k.c @ d5295253

History | View | Annotate | Download (7 kB)

1
#include "vl.h"
2

    
3
#define BIOS_FILENAME "mips_bios.bin"
4
//#define BIOS_FILENAME "system.bin"
5
#define KERNEL_LOAD_ADDR 0x80010000
6
#define INITRD_LOAD_ADDR 0x80800000
7

    
8
extern FILE *logfile;
9

    
10
static void pic_irq_request(void *opaque, int level)
11
{
12
    if (level) {
13
        cpu_single_env->CP0_Cause |= 0x00000400;
14
        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
15
    } else {
16
        cpu_single_env->CP0_Cause &= ~0x00000400;
17
        cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
18
    }
19
}
20

    
21
void cpu_mips_irqctrl_init (void)
22
{
23
}
24

    
25
uint32_t cpu_mips_get_random (CPUState *env)
26
{
27
    uint32_t now = qemu_get_clock(vm_clock);
28

    
29
    return now % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
30
}
31

    
32
/* MIPS R4K timer */
33
uint32_t cpu_mips_get_count (CPUState *env)
34
{
35
    return env->CP0_Count +
36
        (uint32_t)muldiv64(qemu_get_clock(vm_clock),
37
                           100 * 1000 * 1000, ticks_per_sec);
38
}
39

    
40
static void cpu_mips_update_count (CPUState *env, uint32_t count,
41
                                   uint32_t compare)
42
{
43
    uint64_t now, next;
44
    uint32_t tmp;
45
    
46
    tmp = count;
47
    if (count == compare)
48
        tmp++;
49
    now = qemu_get_clock(vm_clock);
50
    next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
51
    if (next == now)
52
        next++;
53
#if 1
54
    if (logfile) {
55
        fprintf(logfile, "%s: 0x%08llx %08x %08x => 0x%08llx\n",
56
                __func__, now, count, compare, next - now);
57
    }
58
#endif
59
    /* Store new count and compare registers */
60
    env->CP0_Compare = compare;
61
    env->CP0_Count =
62
        count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
63
    /* Adjust timer */
64
    qemu_mod_timer(env->timer, next);
65
}
66

    
67
void cpu_mips_store_count (CPUState *env, uint32_t value)
68
{
69
    cpu_mips_update_count(env, value, env->CP0_Compare);
70
}
71

    
72
void cpu_mips_store_compare (CPUState *env, uint32_t value)
73
{
74
    cpu_mips_update_count(env, cpu_mips_get_count(env), value);
75
    pic_set_irq(5, 0);
76
}
77

    
78
static void mips_timer_cb (void *opaque)
79
{
80
    CPUState *env;
81

    
82
    env = opaque;
83
#if 1
84
    if (logfile) {
85
        fprintf(logfile, "%s\n", __func__);
86
    }
87
#endif
88
    cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
89
    pic_set_irq(5, 1);
90
}
91

    
92
void cpu_mips_clock_init (CPUState *env)
93
{
94
    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
95
    env->CP0_Compare = 0;
96
    cpu_mips_update_count(env, 1, 0);
97
}
98

    
99
static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
100
{
101
    if (logfile)
102
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
103
    cpu_outb(NULL, addr & 0xffff, value);
104
}
105

    
106
static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
107
{
108
    uint32_t ret = cpu_inb(NULL, addr & 0xffff);
109
    if (logfile)
110
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
111
    return ret;
112
}
113

    
114
static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
115
{
116
    if (logfile)
117
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
118
#ifdef TARGET_WORDS_BIGENDIAN
119
    value = bswap16(value);
120
#endif
121
    cpu_outw(NULL, addr & 0xffff, value);
122
}
123

    
124
static uint32_t io_readw (void *opaque, target_phys_addr_t addr)
125
{
126
    uint32_t ret = cpu_inw(NULL, addr & 0xffff);
127
#ifdef TARGET_WORDS_BIGENDIAN
128
    ret = bswap16(ret);
129
#endif
130
    if (logfile)
131
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
132
    return ret;
133
}
134

    
135
static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
136
{
137
    if (logfile)
138
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
139
#ifdef TARGET_WORDS_BIGENDIAN
140
    value = bswap32(value);
141
#endif
142
    cpu_outl(NULL, addr & 0xffff, value);
143
}
144

    
145
static uint32_t io_readl (void *opaque, target_phys_addr_t addr)
146
{
147
    uint32_t ret = cpu_inl(NULL, addr & 0xffff);
148

    
149
#ifdef TARGET_WORDS_BIGENDIAN
150
    ret = bswap32(ret);
151
#endif
152
    if (logfile)
153
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
154
    return ret;
155
}
156

    
157
CPUWriteMemoryFunc *io_write[] = {
158
    &io_writeb,
159
    &io_writew,
160
    &io_writel,
161
};
162

    
163
CPUReadMemoryFunc *io_read[] = {
164
    &io_readb,
165
    &io_readw,
166
    &io_readl,
167
};
168

    
169
void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
170
                    DisplayState *ds, const char **fd_filename, int snapshot,
171
                    const char *kernel_filename, const char *kernel_cmdline,
172
                    const char *initrd_filename)
173
{
174
    char buf[1024];
175
    target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
176
    unsigned long bios_offset;
177
    int io_memory;
178
    int linux_boot;
179
    int ret;
180

    
181
    printf("%s: start\n", __func__);
182
    linux_boot = (kernel_filename != NULL);
183
    /* allocate RAM */
184
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
185
    bios_offset = ram_size + vga_ram_size;
186
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
187
    printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE);
188
    ret = load_image(buf, phys_ram_base + bios_offset);
189
    if (ret != BIOS_SIZE) {
190
        fprintf(stderr, "qemu: could not load MIPS bios '%s'\n", buf);
191
        exit(1);
192
    }
193
    cpu_register_physical_memory((uint32_t)(0x1fc00000),
194
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
195
#if 0
196
    memcpy(phys_ram_base + 0x10000, phys_ram_base + bios_offset, BIOS_SIZE);
197
    cpu_single_env->PC = 0x80010004;
198
#else
199
    cpu_single_env->PC = 0xBFC00004;
200
#endif
201
    if (linux_boot) {
202
        kernel_base = KERNEL_LOAD_ADDR;
203
        /* now we can load the kernel */
204
        kernel_size = load_image(kernel_filename,
205
                                phys_ram_base + (kernel_base - 0x80000000));
206
        if (kernel_size == (target_ulong) -1) {
207
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
208
                    kernel_filename);
209
            exit(1);
210
        }
211
        /* load initrd */
212
        if (initrd_filename) {
213
            initrd_base = INITRD_LOAD_ADDR;
214
            initrd_size = load_image(initrd_filename,
215
                                     phys_ram_base + initrd_base);
216
            if (initrd_size == (target_ulong) -1) {
217
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
218
                        initrd_filename);
219
                exit(1);
220
            }
221
        } else {
222
            initrd_base = 0;
223
            initrd_size = 0;
224
        }
225
        cpu_single_env->PC = KERNEL_LOAD_ADDR;
226
    } else {
227
        kernel_base = 0;
228
        kernel_size = 0;
229
        initrd_base = 0;
230
        initrd_size = 0;
231
    }
232

    
233
    /* Init internal devices */
234
    cpu_mips_clock_init(cpu_single_env);
235
    cpu_mips_irqctrl_init();
236

    
237
    /* Register 64 KB of ISA IO space at 0x14000000 */
238
    io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
239
    cpu_register_physical_memory(0x14000000, 0x00010000, io_memory);
240
    isa_mem_base = 0x10000000;
241

    
242
    isa_pic = pic_init(pic_irq_request, cpu_single_env);
243
    serial_init(0x3f8, 4, serial_hds[0]);
244
    vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size, 
245
                   vga_ram_size, 0, 0);
246

    
247
    isa_ne2000_init(0x300, 9, &nd_table[0]);
248
}
249

    
250
QEMUMachine mips_machine = {
251
    "mips",
252
    "mips r4k platform",
253
    mips_r4k_init,
254
};