|
1 /* |
|
2 * QEMU MIPS Jazz support |
|
3 * |
|
4 * Copyright (c) 2007-2008 Hervé Poussineau |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 */ |
|
24 |
|
25 #include "hw.h" |
|
26 #include "mips.h" |
|
27 #include "pc.h" |
|
28 #include "isa.h" |
|
29 #include "fdc.h" |
|
30 #include "sysemu.h" |
|
31 #include "audio/audio.h" |
|
32 #include "boards.h" |
|
33 #include "net.h" |
|
34 #include "scsi.h" |
|
35 |
|
36 #ifdef TARGET_WORDS_BIGENDIAN |
|
37 #define BIOS_FILENAME "mips_bios.bin" |
|
38 #else |
|
39 #define BIOS_FILENAME "mipsel_bios.bin" |
|
40 #endif |
|
41 |
|
42 enum jazz_model_e |
|
43 { |
|
44 JAZZ_MAGNUM, |
|
45 JAZZ_PICA61, |
|
46 }; |
|
47 |
|
48 static void main_cpu_reset(void *opaque) |
|
49 { |
|
50 CPUState *env = opaque; |
|
51 cpu_reset(env); |
|
52 } |
|
53 |
|
54 static uint32_t rtc_readb(void *opaque, target_phys_addr_t addr) |
|
55 { |
|
56 CPUState *env = opaque; |
|
57 return cpu_inw(env, 0x71); |
|
58 } |
|
59 |
|
60 static void rtc_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
61 { |
|
62 CPUState *env = opaque; |
|
63 cpu_outw(env, 0x71, val & 0xff); |
|
64 } |
|
65 |
|
66 static CPUReadMemoryFunc *rtc_read[3] = { |
|
67 rtc_readb, |
|
68 rtc_readb, |
|
69 rtc_readb, |
|
70 }; |
|
71 |
|
72 static CPUWriteMemoryFunc *rtc_write[3] = { |
|
73 rtc_writeb, |
|
74 rtc_writeb, |
|
75 rtc_writeb, |
|
76 }; |
|
77 |
|
78 #ifdef HAS_AUDIO |
|
79 static void audio_init(qemu_irq *pic) |
|
80 { |
|
81 struct soundhw *c; |
|
82 int audio_enabled = 0; |
|
83 |
|
84 for (c = soundhw; !audio_enabled && c->name; ++c) { |
|
85 audio_enabled = c->enabled; |
|
86 } |
|
87 |
|
88 if (audio_enabled) { |
|
89 AudioState *s; |
|
90 |
|
91 s = AUD_init(); |
|
92 if (s) { |
|
93 for (c = soundhw; c->name; ++c) { |
|
94 if (c->enabled) { |
|
95 if (c->isa) { |
|
96 c->init.init_isa(s, pic); |
|
97 } |
|
98 } |
|
99 } |
|
100 } |
|
101 } |
|
102 } |
|
103 #endif |
|
104 |
|
105 static void espdma_memory_read(void *opaque, uint8_t *buf, int len) |
|
106 { |
|
107 printf("espdma_memory_read(buf %p, len %d) not implemented\n", buf, len); |
|
108 } |
|
109 |
|
110 static void espdma_memory_write(void *opaque, uint8_t *buf, int len) |
|
111 { |
|
112 printf("espdma_memory_write(buf %p, len %d) not implemented\n", buf, len); |
|
113 } |
|
114 |
|
115 #define MAGNUM_BIOS_SIZE_MAX 0x7e000 |
|
116 #define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX) |
|
117 |
|
118 static |
|
119 void mips_jazz_init (ram_addr_t ram_size, int vga_ram_size, |
|
120 DisplayState *ds, const char *cpu_model, |
|
121 enum jazz_model_e jazz_model) |
|
122 { |
|
123 char buf[1024]; |
|
124 unsigned long bios_offset; |
|
125 int bios_size, n; |
|
126 CPUState *env; |
|
127 qemu_irq *rc4030, *i8259; |
|
128 void *scsi_hba; |
|
129 int hd; |
|
130 int s_rtc; |
|
131 PITState *pit; |
|
132 BlockDriverState *fds[MAX_FD]; |
|
133 qemu_irq esp_reset; |
|
134 |
|
135 /* init CPUs */ |
|
136 if (cpu_model == NULL) { |
|
137 #ifdef TARGET_MIPS64 |
|
138 cpu_model = "R4000"; |
|
139 #else |
|
140 /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */ |
|
141 cpu_model = "24Kf"; |
|
142 #endif |
|
143 } |
|
144 env = cpu_init(cpu_model); |
|
145 if (!env) { |
|
146 fprintf(stderr, "Unable to find CPU definition\n"); |
|
147 exit(1); |
|
148 } |
|
149 qemu_register_reset(main_cpu_reset, env); |
|
150 |
|
151 /* allocate RAM */ |
|
152 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); |
|
153 |
|
154 /* load the BIOS image. */ |
|
155 bios_offset = ram_size + vga_ram_size; |
|
156 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); |
|
157 bios_size = load_image(buf, phys_ram_base + bios_offset); |
|
158 if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) { |
|
159 fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", |
|
160 buf); |
|
161 exit(1); |
|
162 } |
|
163 |
|
164 cpu_register_physical_memory(0x1fc00000LL, |
|
165 MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM); |
|
166 cpu_register_physical_memory(0xfff00000LL, |
|
167 MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM); |
|
168 |
|
169 /* Init CPU internal devices */ |
|
170 cpu_mips_irq_init_cpu(env); |
|
171 cpu_mips_clock_init(env); |
|
172 |
|
173 /* Chipset */ |
|
174 rc4030 = rc4030_init(env->irq[6], env->irq[3]); |
|
175 |
|
176 /* ISA devices */ |
|
177 i8259 = i8259_init(env->irq[4]); |
|
178 pit = pit_init(0x40, i8259[0]); |
|
179 pcspk_init(pit); |
|
180 |
|
181 /* ISA IO space at 0x90000000 */ |
|
182 isa_mmio_init(0x90000000, 0x01000000); |
|
183 isa_mem_base = 0x11000000; |
|
184 |
|
185 /* Video card */ |
|
186 switch (jazz_model) { |
|
187 case JAZZ_MAGNUM: |
|
188 g364fb_mm_init(ds, vga_ram_size, 0, 0x40000000, 0x60000000); |
|
189 break; |
|
190 case JAZZ_PICA61: |
|
191 isa_vga_mm_init(ds, phys_ram_base + ram_size, ram_size, vga_ram_size, |
|
192 0x40000000, 0x60000000, 0); |
|
193 break; |
|
194 default: |
|
195 break; |
|
196 } |
|
197 |
|
198 /* Network controller */ |
|
199 /* FIXME: missing NS SONIC DP83932 */ |
|
200 |
|
201 /* SCSI adapter */ |
|
202 scsi_hba = esp_init(0x80002000, 0, |
|
203 espdma_memory_read, espdma_memory_write, NULL, |
|
204 rc4030[5], &esp_reset); |
|
205 for (n = 0; n < ESP_MAX_DEVS; n++) { |
|
206 hd = drive_get_index(IF_SCSI, 0, n); |
|
207 if (hd != -1) { |
|
208 esp_scsi_attach(scsi_hba, drives_table[hd].bdrv, n); |
|
209 } |
|
210 } |
|
211 |
|
212 /* Floppy */ |
|
213 if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) { |
|
214 fprintf(stderr, "qemu: too many floppy drives\n"); |
|
215 exit(1); |
|
216 } |
|
217 for (n = 0; n < MAX_FD; n++) { |
|
218 int fd = drive_get_index(IF_FLOPPY, 0, n); |
|
219 if (fd != -1) |
|
220 fds[n] = drives_table[fd].bdrv; |
|
221 else |
|
222 fds[n] = NULL; |
|
223 } |
|
224 fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds); |
|
225 |
|
226 /* Real time clock */ |
|
227 rtc_init(0x70, i8259[8]); |
|
228 s_rtc = cpu_register_io_memory(0, rtc_read, rtc_write, env); |
|
229 cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc); |
|
230 |
|
231 /* Keyboard (i8042) */ |
|
232 i8042_mm_init(rc4030[6], rc4030[7], 0x80005000, 0x1000, 0x1); |
|
233 |
|
234 /* Serial ports */ |
|
235 if (serial_hds[0]) |
|
236 serial_mm_init(0x80006000, 0, rc4030[8], 8000000/16, serial_hds[0], 1); |
|
237 if (serial_hds[1]) |
|
238 serial_mm_init(0x80007000, 0, rc4030[9], 8000000/16, serial_hds[1], 1); |
|
239 |
|
240 /* Parallel port */ |
|
241 if (parallel_hds[0]) |
|
242 parallel_mm_init(0x80008000, 0, rc4030[0], parallel_hds[0]); |
|
243 |
|
244 /* Sound card */ |
|
245 /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */ |
|
246 #ifdef HAS_AUDIO |
|
247 audio_init(i8259); |
|
248 #endif |
|
249 |
|
250 /* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */ |
|
251 ds1225y_init(0x80009000, "nvram"); |
|
252 |
|
253 /* LED indicator */ |
|
254 jazz_led_init(ds, 0x8000f000); |
|
255 } |
|
256 |
|
257 static |
|
258 void mips_magnum_init (ram_addr_t ram_size, int vga_ram_size, |
|
259 const char *boot_device, DisplayState *ds, |
|
260 const char *kernel_filename, const char *kernel_cmdline, |
|
261 const char *initrd_filename, const char *cpu_model) |
|
262 { |
|
263 mips_jazz_init(ram_size, vga_ram_size, ds, cpu_model, JAZZ_MAGNUM); |
|
264 } |
|
265 |
|
266 static |
|
267 void mips_pica61_init (ram_addr_t ram_size, int vga_ram_size, |
|
268 const char *boot_device, DisplayState *ds, |
|
269 const char *kernel_filename, const char *kernel_cmdline, |
|
270 const char *initrd_filename, const char *cpu_model) |
|
271 { |
|
272 mips_jazz_init(ram_size, vga_ram_size, ds, cpu_model, JAZZ_PICA61); |
|
273 } |
|
274 |
|
275 QEMUMachine mips_magnum_machine = { |
|
276 .name = "magnum", |
|
277 .desc = "MIPS Magnum", |
|
278 .init = mips_magnum_init, |
|
279 .ram_require = MAGNUM_BIOS_SIZE + VGA_RAM_SIZE, |
|
280 .nodisk_ok = 1, |
|
281 }; |
|
282 |
|
283 QEMUMachine mips_pica61_machine = { |
|
284 .name = "pica61", |
|
285 .desc = "Acer Pica 61", |
|
286 .init = mips_pica61_init, |
|
287 .ram_require = MAGNUM_BIOS_SIZE + VGA_RAM_SIZE, |
|
288 .nodisk_ok = 1, |
|
289 }; |