Fix initialisation of serial/parallel ports, spotted by Stefan Weil.
[qemu] / hw / mips_malta.c
1 /*
2  * QEMU Malta board support
3  *
4  * Copyright (c) 2006 Aurelien Jarno
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 "vl.h"
26
27 #ifdef TARGET_WORDS_BIGENDIAN
28 #define BIOS_FILENAME "mips_bios.bin"
29 #else
30 #define BIOS_FILENAME "mipsel_bios.bin"
31 #endif
32
33 #ifdef MIPS_HAS_MIPS64
34 #define INITRD_LOAD_ADDR        (int64_t)0x80800000
35 #else
36 #define INITRD_LOAD_ADDR        (int32_t)0x80800000
37 #endif
38
39 #define ENVP_ADDR               (int32_t)0x80002000
40 #define VIRT_TO_PHYS_ADDEND     (-((int64_t)(int32_t)0x80000000))
41
42 #define ENVP_NB_ENTRIES         16
43 #define ENVP_ENTRY_SIZE         256
44
45
46 extern FILE *logfile;
47
48 typedef struct {
49     uint32_t leds;
50     uint32_t brk;
51     uint32_t gpout;
52     uint32_t i2coe;
53     uint32_t i2cout;
54     uint32_t i2csel;
55     CharDriverState *display;
56     char display_text[9];
57 } MaltaFPGAState;
58
59 static PITState *pit;
60
61 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
62 static void pic_irq_request(void *opaque, int level)
63 {
64     cpu_mips_irq_request(opaque, 2, level);
65 }
66
67 /* Malta FPGA */
68 static void malta_fpga_update_display(void *opaque)
69 {
70     char leds_text[9];
71     int i;
72     MaltaFPGAState *s = opaque;
73
74     for (i = 7 ; i >= 0 ; i--) {
75         if (s->leds & (1 << i))
76             leds_text[i] = '#';
77         else
78             leds_text[i] = ' ';
79     }
80     leds_text[8] = '\0';
81
82     qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
83     qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
84 }
85
86 static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
87 {
88     MaltaFPGAState *s = opaque;
89     uint32_t val = 0;
90     uint32_t saddr;
91
92     saddr = (addr & 0xfffff);
93
94     switch (saddr) {
95
96     /* SWITCH Register */
97     case 0x00200:
98         val = 0x00000000;               /* All switches closed */
99         break;
100
101     /* STATUS Register */
102     case 0x00208:
103 #ifdef TARGET_WORDS_BIGENDIAN
104         val = 0x00000012;
105 #else
106         val = 0x00000010;
107 #endif
108         break;
109
110     /* JMPRS Register */
111     case 0x00210:
112         val = 0x00;
113         break;
114
115     /* LEDBAR Register */
116     case 0x00408:
117         val = s->leds;
118         break;
119
120     /* BRKRES Register */
121     case 0x00508:
122         val = s->brk;
123         break;
124
125     /* GPOUT Register */
126     case 0x00a00:
127         val = s->gpout;
128         break;
129
130     /* XXX: implement a real I2C controller */
131
132     /* GPINP Register */
133     case 0x00a08:
134         /* IN = OUT until a real I2C control is implemented */
135         if (s->i2csel)
136             val = s->i2cout;
137         else
138             val = 0x00;
139         break;
140
141     /* I2CINP Register */
142     case 0x00b00:
143         val = 0x00000003;
144         break;
145
146     /* I2COE Register */
147     case 0x00b08:
148         val = s->i2coe;
149         break;
150
151     /* I2COUT Register */
152     case 0x00b10:
153         val = s->i2cout;
154         break;
155
156     /* I2CSEL Register */
157     case 0x00b18:
158         val = s->i2cout;
159         break;
160
161     default:
162 #if 0
163         printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
164                 addr);
165 #endif
166         break;
167     }
168     return val;
169 }
170
171 static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
172                               uint32_t val)
173 {
174     MaltaFPGAState *s = opaque;
175     uint32_t saddr;
176
177     saddr = (addr & 0xfffff);
178
179     switch (saddr) {
180
181     /* SWITCH Register */
182     case 0x00200:
183         break;
184
185     /* JMPRS Register */
186     case 0x00210:
187         break;
188
189     /* LEDBAR Register */
190     /* XXX: implement a 8-LED array */
191     case 0x00408:
192         s->leds = val & 0xff;
193         break;
194
195     /* ASCIIWORD Register */
196     case 0x00410:
197         snprintf(s->display_text, 9, "%08X", val);
198         malta_fpga_update_display(s);
199         break;
200
201     /* ASCIIPOS0 to ASCIIPOS7 Registers */
202     case 0x00418:
203     case 0x00420:
204     case 0x00428:
205     case 0x00430:
206     case 0x00438:
207     case 0x00440:
208     case 0x00448:
209     case 0x00450:
210         s->display_text[(saddr - 0x00418) >> 3] = (char) val;
211         malta_fpga_update_display(s);
212         break;
213
214     /* SOFTRES Register */
215     case 0x00500:
216         if (val == 0x42)
217             qemu_system_reset_request ();
218         break;
219
220     /* BRKRES Register */
221     case 0x00508:
222         s->brk = val & 0xff;
223         break;
224
225     /* GPOUT Register */
226     case 0x00a00:
227         s->gpout = val & 0xff;
228         break;
229
230     /* I2COE Register */
231     case 0x00b08:
232         s->i2coe = val & 0x03;
233         break;
234
235     /* I2COUT Register */
236     case 0x00b10:
237         s->i2cout = val & 0x03;
238         break;
239
240     /* I2CSEL Register */
241     case 0x00b18:
242         s->i2cout = val & 0x01;
243         break;
244
245     default:
246 #if 0
247         printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
248                 addr);
249 #endif
250         break;
251     }
252 }
253
254 static CPUReadMemoryFunc *malta_fpga_read[] = {
255    malta_fpga_readl,
256    malta_fpga_readl,
257    malta_fpga_readl
258 };
259
260 static CPUWriteMemoryFunc *malta_fpga_write[] = {
261    malta_fpga_writel,
262    malta_fpga_writel,
263    malta_fpga_writel
264 };
265
266 void malta_fpga_reset(void *opaque)
267 {
268     MaltaFPGAState *s = opaque;
269
270     s->leds   = 0x00;
271     s->brk    = 0x0a;
272     s->gpout  = 0x00;
273     s->i2coe  = 0x0;
274     s->i2cout = 0x3;
275     s->i2csel = 0x1;
276
277     s->display_text[8] = '\0';
278     snprintf(s->display_text, 9, "        ");
279     malta_fpga_update_display(s);
280 }
281
282 MaltaFPGAState *malta_fpga_init(target_phys_addr_t base)
283 {
284     MaltaFPGAState *s;
285     int malta;
286
287     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
288
289     malta = cpu_register_io_memory(0, malta_fpga_read,
290                                    malta_fpga_write, s);
291     cpu_register_physical_memory(base, 0x100000, malta);
292
293     s->display = qemu_chr_open("vc");
294     qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
295     qemu_chr_printf(s->display, "+--------+\r\n");
296     qemu_chr_printf(s->display, "+        +\r\n");
297     qemu_chr_printf(s->display, "+--------+\r\n");
298     qemu_chr_printf(s->display, "\n");
299     qemu_chr_printf(s->display, "Malta ASCII\r\n");
300     qemu_chr_printf(s->display, "+--------+\r\n");
301     qemu_chr_printf(s->display, "+        +\r\n");
302     qemu_chr_printf(s->display, "+--------+\r\n");
303
304     malta_fpga_reset(s);
305     qemu_register_reset(malta_fpga_reset, s);
306
307     return s;
308 }
309
310 /* Audio support */
311 #ifdef HAS_AUDIO
312 static void audio_init (PCIBus *pci_bus)
313 {
314     struct soundhw *c;
315     int audio_enabled = 0;
316
317     for (c = soundhw; !audio_enabled && c->name; ++c) {
318         audio_enabled = c->enabled;
319     }
320
321     if (audio_enabled) {
322         AudioState *s;
323
324         s = AUD_init ();
325         if (s) {
326             for (c = soundhw; c->name; ++c) {
327                 if (c->enabled) {
328                     if (c->isa) {
329                         fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
330                         exit(1);
331                     }
332                     else {
333                         if (pci_bus) {
334                             c->init.init_pci (pci_bus, s);
335                         }
336                     }
337                 }
338             }
339         }
340     }
341 }
342 #endif
343
344 /* Network support */
345 static void network_init (PCIBus *pci_bus)
346 {
347     int i;
348     NICInfo *nd;
349
350     for(i = 0; i < nb_nics; i++) {
351         nd = &nd_table[i];
352         if (!nd->model) {
353             nd->model = "pcnet";
354         }
355         if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
356             /* The malta board has a PCNet card using PCI SLOT 11 */
357             pci_nic_init(pci_bus, nd, 88);
358         } else {
359             pci_nic_init(pci_bus, nd, -1);
360         }
361     }
362 }
363
364 /* ROM and pseudo bootloader
365
366    The following code implements a very very simple bootloader. It first
367    loads the registers a0 to a3 to the values expected by the OS, and
368    then jump at the kernel address.
369
370    The bootloader should pass the locations of the kernel arguments and
371    environment variables tables. Those tables contain the 32-bit address
372    of NULL terminated strings. The environment variables table should be
373    terminated by a NULL address.
374
375    For a simpler implementation, the number of kernel arguments is fixed
376    to two (the name of the kernel and the command line), and the two
377    tables are actually the same one.
378
379    The registers a0 to a3 should contain the following values:
380      a0 - number of kernel arguments
381      a1 - 32-bit address of the kernel arguments table
382      a2 - 32-bit address of the environment variables table
383      a3 - RAM size in bytes
384 */
385
386 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
387 {
388     uint32_t *p;
389
390     /* Small bootloader */
391     p = (uint32_t *) (phys_ram_base + bios_offset);
392     stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
393     stl_raw(p++, 0x00000000);                                      /* nop */
394
395     /* Second part of the bootloader */
396     p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
397     stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
398     stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
399     stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
400     stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
401     stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
402     stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
403     stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
404     stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
405     stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
406     stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
407     stl_raw(p++, 0x03e00008);                                      /* jr ra */
408     stl_raw(p++, 0x00000000);                                      /* nop */
409 }
410
411 static void prom_set(int index, const char *string, ...)
412 {
413     va_list ap;
414     int32_t *p;
415     int32_t table_addr;
416     char *s;
417
418     if (index >= ENVP_NB_ENTRIES)
419         return;
420
421     p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
422     p += index;
423
424     if (string == NULL) {
425         stl_raw(p, 0);
426         return;
427     }
428
429     table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
430     s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
431
432     stl_raw(p, table_addr);
433
434     va_start(ap, string);
435     vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
436     va_end(ap);
437 }
438
439 /* Kernel */
440 static int64_t load_kernel (CPUState *env)
441 {
442     int64_t kernel_addr = 0;
443     int index = 0;
444     long initrd_size;
445
446     if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
447         fprintf(stderr, "qemu: could not load kernel '%s'\n",
448                 env->kernel_filename);
449       exit(1);
450     }
451
452     /* load initrd */
453     initrd_size = 0;
454     if (env->initrd_filename) {
455         initrd_size = load_image(env->initrd_filename,
456                                  phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
457         if (initrd_size == (target_ulong) -1) {
458             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
459                     env->initrd_filename);
460             exit(1);
461         }
462     }
463
464     /* Store command line.  */
465     prom_set(index++, env->kernel_filename);
466     if (initrd_size > 0)
467         prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
468     else
469         prom_set(index++, env->kernel_cmdline);
470
471     /* Setup minimum environment variables */
472     prom_set(index++, "memsize");
473     prom_set(index++, "%i", env->ram_size);
474     prom_set(index++, "modetty0");
475     prom_set(index++, "38400n8r");
476     prom_set(index++, NULL);
477
478     return kernel_addr;
479 }
480
481 static void main_cpu_reset(void *opaque)
482 {
483     CPUState *env = opaque;
484     cpu_reset(env);
485
486     /* The bootload does not need to be rewritten as it is located in a
487        read only location. The kernel location and the arguments table
488        location does not change. */
489     if (env->kernel_filename)
490         load_kernel (env);
491 }
492
493 static
494 void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
495                       DisplayState *ds, const char **fd_filename, int snapshot,
496                       const char *kernel_filename, const char *kernel_cmdline,
497                       const char *initrd_filename)
498 {
499     char buf[1024];
500     unsigned long bios_offset;
501     int64_t kernel_addr;
502     PCIBus *pci_bus;
503     CPUState *env;
504     RTCState *rtc_state;
505     /* fdctrl_t *floppy_controller; */
506     MaltaFPGAState *malta_fpga;
507     int ret;
508
509     env = cpu_init();
510     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
511     qemu_register_reset(main_cpu_reset, env);
512
513     /* allocate RAM */
514     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
515
516     /* Map the bios at two physical locations, as on the real board */
517     bios_offset = ram_size + vga_ram_size;
518     cpu_register_physical_memory(0x1e000000LL,
519                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
520     cpu_register_physical_memory(0x1fc00000LL,
521                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
522
523     /* Load a BIOS image except if a kernel image has been specified. In
524        the later case, just write a small bootloader to the flash
525        location. */
526     if (kernel_filename) {
527         env->ram_size = ram_size;
528         env->kernel_filename = kernel_filename;
529         env->kernel_cmdline = kernel_cmdline;
530         env->initrd_filename = initrd_filename;
531         kernel_addr = load_kernel(env);
532         write_bootloader(env, bios_offset, kernel_addr);
533     } else {
534         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
535         ret = load_image(buf, phys_ram_base + bios_offset);
536         if (ret < 0 || ret > BIOS_SIZE) {
537             fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
538                     buf);
539             exit(1);
540         }
541     }
542
543     /* Board ID = 0x420 (Malta Board with CoreLV)
544        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
545        map to the board ID. */
546     stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
547
548     /* Init internal devices */
549     cpu_mips_clock_init(env);
550     cpu_mips_irqctrl_init();
551
552     /* FPGA */
553     malta_fpga = malta_fpga_init(0x1f000000LL);
554
555     /* Interrupt controller */
556     isa_pic = pic_init(pic_irq_request, env);
557
558     /* Northbridge */
559     pci_bus = pci_gt64120_init(isa_pic);
560
561     /* Southbridge */
562     piix4_init(pci_bus, 80);
563     pci_piix3_ide_init(pci_bus, bs_table, 81);
564     usb_uhci_init(pci_bus, 82);
565     piix4_pm_init(pci_bus, 83);
566     pit = pit_init(0x40, 0);
567     DMA_init(0);
568
569     /* Super I/O */
570     kbd_init();
571     rtc_state = rtc_init(0x70, 8);
572     if (serial_hds[0])
573         serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
574     if (serial_hds[1])
575         serial_init(&pic_set_irq_new, isa_pic, 0x2f8, 4, serial_hds[1]);
576     if (parallel_hds[0])
577         parallel_init(0x378, 7, parallel_hds[0]);
578     /* XXX: The floppy controller does not work correctly, something is
579        probably wrong.
580     floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
581
582     /* Sound card */
583 #ifdef HAS_AUDIO
584     audio_init(pci_bus);
585 #endif
586
587     /* Network card */
588     network_init(pci_bus);
589 }
590
591 QEMUMachine mips_malta_machine = {
592     "malta",
593     "MIPS Malta Core LV",
594     mips_malta_init,
595 };