full system SPARC emulation (Blue Swirl)
[qemu] / hw / sun4m.c
1 /*
2  * QEMU Sun4m System Emulator
3  * 
4  * Copyright (c) 2003-2004 Fabrice Bellard
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 #include "vl.h"
25 #include "m48t08.h"
26
27 #define KERNEL_LOAD_ADDR     0x00004000
28 #define MMU_CONTEXT_TBL      0x00003000
29 #define MMU_L1PTP            (MMU_CONTEXT_TBL + 0x0400)
30 #define MMU_L2PTP            (MMU_CONTEXT_TBL + 0x0800)
31 #define ROMVEC_DATA          (MMU_CONTEXT_TBL + 0x1800)
32 #define PROM_ADDR            0xffd04000
33 #define PROM_FILENAME        "proll.bin"
34 #define PHYS_JJ_EEPROM  0x71200000      /* [2000] MK48T08 */
35 #define PHYS_JJ_IDPROM_OFF      0x1FD8
36 #define PHYS_JJ_EEPROM_SIZE     0x2000
37
38 /* TSC handling */
39
40 uint64_t cpu_get_tsc()
41 {
42     return qemu_get_clock(vm_clock);
43 }
44
45 void DMA_run() {}
46 void SB16_run() {}
47 void vga_invalidate_display() {}
48 void vga_screen_dump(const char *filename) {}
49 int serial_can_receive(SerialState *s) { return 0; }
50 void serial_receive_byte(SerialState *s, int ch) {}
51 void serial_receive_break(SerialState *s) {}
52
53 static m48t08_t *nvram;
54
55 /* Sun4m hardware initialisation */
56 void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
57              DisplayState *ds, const char **fd_filename, int snapshot,
58              const char *kernel_filename, const char *kernel_cmdline,
59              const char *initrd_filename)
60 {
61     char buf[1024];
62     int ret, linux_boot, bios_size;
63     unsigned long bios_offset;
64
65     linux_boot = (kernel_filename != NULL);
66
67     /* allocate RAM */
68     cpu_register_physical_memory(0, ram_size, 0);
69     bios_offset = ram_size;
70
71     iommu_init();
72     sched_init();
73     tcx_init(ds);
74     lance_init(&nd_table[0], 6);
75     nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
76
77     magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
78
79 #if 0
80     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
81     bios_size = get_image_size(buf);
82     ret = load_image(buf, phys_ram_base + bios_offset);
83     if (ret != bios_size) {
84         fprintf(stderr, "qemu: could not load prom '%s'\n", buf);
85         exit(1);
86     }
87     cpu_register_physical_memory(PROM_ADDR, 
88                                  bios_size, bios_offset | IO_MEM_ROM);
89 #endif
90
91     /* We load Proll as the kernel and start it. It will issue a magic
92        IO to load the real kernel */
93     if (linux_boot) {
94         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
95         ret = load_kernel(buf, 
96                           phys_ram_base + KERNEL_LOAD_ADDR);
97         if (ret < 0) {
98             fprintf(stderr, "qemu: could not load kernel '%s'\n", 
99                     buf);
100             exit(1);
101         }
102     }
103     /* Setup a MMU entry for entire address space */
104     stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
105     stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
106 #if 0
107     stl_raw(phys_ram_base + MMU_L1PTP + (0x50 << 2), (MMU_L2PTP >> 4) | 1); // frame buffer at 50..
108 #endif
109     stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
110     /* 3 = U:RWX S:RWX */
111     stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
112 #if 0
113     stl_raw(phys_ram_base + MMU_L2PTP + 0x84, (PHYS_JJ_TCX_FB >> 4) \
114             | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
115     stl_raw(phys_ram_base + MMU_L2PTP + 0x88, (PHYS_JJ_TCX_FB >> 4) \
116             | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
117     stl_raw(phys_ram_base + MMU_L2PTP + 0x140, (PHYS_JJ_TCX_FB >> 4) \
118             | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
119     // "Empirical constant"
120     stl_raw(phys_ram_base + ROMVEC_DATA, 0x10010407);
121
122     // Version: V3 prom
123     stl_raw(phys_ram_base + ROMVEC_DATA + 4, 3);
124
125     stl_raw(phys_ram_base + ROMVEC_DATA + 0x1c, ROMVEC_DATA+0x400);
126     stl_raw(phys_ram_base + ROMVEC_DATA + 0x400, ROMVEC_DATA+0x404);
127     stl_raw(phys_ram_base + ROMVEC_DATA + 0x404, 0x81c3e008); // retl
128     stl_raw(phys_ram_base + ROMVEC_DATA + 0x408, 0x01000000); // nop
129 #endif
130 }