]> Git Repo - qemu.git/blame - hw/sun4m.c
Fix unportable bitfields use which broke pcnet for big endian hosts.
[qemu.git] / hw / sun4m.c
CommitLineData
420557e8
FB
1/*
2 * QEMU Sun4m System Emulator
3 *
b81b3b10 4 * Copyright (c) 2003-2005 Fabrice Bellard
420557e8
FB
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"
420557e8
FB
25
26#define KERNEL_LOAD_ADDR 0x00004000
b6f479d3 27#define CMDLINE_ADDR 0x007ff000
713c45fa 28#define INITRD_LOAD_ADDR 0x00800000
b3783731 29#define PROM_SIZE_MAX (256 * 1024)
e80cfcfc 30#define PROM_ADDR 0xffd00000
0986ac3b 31#define PROM_FILENAME "openbios-sparc32"
e80cfcfc 32#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */
420557e8
FB
33#define PHYS_JJ_IDPROM_OFF 0x1FD8
34#define PHYS_JJ_EEPROM_SIZE 0x2000
e80cfcfc
FB
35// IRQs are not PIL ones, but master interrupt controller register
36// bits
37#define PHYS_JJ_IOMMU 0x10000000 /* I/O MMU */
6f7e9aec 38#define PHYS_JJ_TCX_FB 0x50000000 /* TCX frame buffer */
3475187d 39#define PHYS_JJ_SLAVIO 0x70000000 /* Slavio base */
67e999be 40#define PHYS_JJ_DMA 0x78400000 /* DMA controller */
6f7e9aec
FB
41#define PHYS_JJ_ESP 0x78800000 /* ESP SCSI */
42#define PHYS_JJ_ESP_IRQ 18
e80cfcfc
FB
43#define PHYS_JJ_LE 0x78C00000 /* Lance ethernet */
44#define PHYS_JJ_LE_IRQ 16
45#define PHYS_JJ_CLOCK 0x71D00000 /* Per-CPU timer/counter, L14 */
46#define PHYS_JJ_CLOCK_IRQ 7
47#define PHYS_JJ_CLOCK1 0x71D10000 /* System timer/counter, L10 */
48#define PHYS_JJ_CLOCK1_IRQ 19
49#define PHYS_JJ_INTR0 0x71E00000 /* Per-CPU interrupt control registers */
8d5f07fa 50#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
e80cfcfc
FB
51#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */
52#define PHYS_JJ_MS_KBD_IRQ 14
53#define PHYS_JJ_SER 0x71100000 /* Serial */
54#define PHYS_JJ_SER_IRQ 15
e80cfcfc
FB
55#define PHYS_JJ_FDC 0x71400000 /* Floppy */
56#define PHYS_JJ_FLOPPY_IRQ 22
3475187d 57#define PHYS_JJ_ME_IRQ 30 /* Module error, power fail */
b8174937
FB
58#define PHYS_JJ_CS 0x6c000000 /* Crystal CS4231 */
59#define PHYS_JJ_CS_IRQ 5
60
ba3c64fb 61#define MAX_CPUS 16
420557e8
FB
62
63/* TSC handling */
64
65uint64_t cpu_get_tsc()
66{
67 return qemu_get_clock(vm_clock);
68}
69
6f7e9aec
FB
70int DMA_get_channel_mode (int nchan)
71{
72 return 0;
73}
74int DMA_read_memory (int nchan, void *buf, int pos, int size)
75{
76 return 0;
77}
78int DMA_write_memory (int nchan, void *buf, int pos, int size)
79{
80 return 0;
81}
82void DMA_hold_DREQ (int nchan) {}
83void DMA_release_DREQ (int nchan) {}
84void DMA_schedule(int nchan) {}
85void DMA_run (void) {}
86void DMA_init (int high_page_enable) {}
87void DMA_register_channel (int nchan,
88 DMA_transfer_handler transfer_handler,
89 void *opaque)
90{
91}
92
819385c5 93static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
6f7e9aec 94{
819385c5
FB
95 m48t59_write(nvram, addr++, (value >> 8) & 0xff);
96 m48t59_write(nvram, addr++, value & 0xff);
6f7e9aec
FB
97}
98
819385c5 99static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
6f7e9aec 100{
819385c5
FB
101 m48t59_write(nvram, addr++, value >> 24);
102 m48t59_write(nvram, addr++, (value >> 16) & 0xff);
103 m48t59_write(nvram, addr++, (value >> 8) & 0xff);
104 m48t59_write(nvram, addr++, value & 0xff);
6f7e9aec
FB
105}
106
819385c5 107static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
6f7e9aec
FB
108 const unsigned char *str, uint32_t max)
109{
110 unsigned int i;
111
112 for (i = 0; i < max && str[i] != '\0'; i++) {
819385c5 113 m48t59_write(nvram, addr + i, str[i]);
6f7e9aec 114 }
819385c5 115 m48t59_write(nvram, addr + max - 1, '\0');
6f7e9aec 116}
420557e8 117
819385c5 118static m48t59_t *nvram;
420557e8 119
6f7e9aec
FB
120extern int nographic;
121
819385c5 122static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
6f7e9aec
FB
123 int boot_device, uint32_t RAM_size,
124 uint32_t kernel_size,
125 int width, int height, int depth)
e80cfcfc
FB
126{
127 unsigned char tmp = 0;
128 int i, j;
129
6f7e9aec
FB
130 // Try to match PPC NVRAM
131 nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
132 nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
133 // NVRAM_size, arch not applicable
ba3c64fb
FB
134 m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
135 m48t59_write(nvram, 0x2E, 0);
819385c5 136 m48t59_write(nvram, 0x2F, nographic & 0xff);
6f7e9aec 137 nvram_set_lword(nvram, 0x30, RAM_size);
819385c5 138 m48t59_write(nvram, 0x34, boot_device & 0xff);
6f7e9aec
FB
139 nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
140 nvram_set_lword(nvram, 0x3C, kernel_size);
b6f479d3 141 if (cmdline) {
b6f479d3 142 strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
6f7e9aec
FB
143 nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
144 nvram_set_lword(nvram, 0x44, strlen(cmdline));
b6f479d3 145 }
6f7e9aec
FB
146 // initrd_image, initrd_size passed differently
147 nvram_set_word(nvram, 0x54, width);
148 nvram_set_word(nvram, 0x56, height);
149 nvram_set_word(nvram, 0x58, depth);
b6f479d3 150
6f7e9aec 151 // Sun4m specific use
e80cfcfc 152 i = 0x1fd8;
819385c5
FB
153 m48t59_write(nvram, i++, 0x01);
154 m48t59_write(nvram, i++, 0x80); /* Sun4m OBP */
e80cfcfc 155 j = 0;
819385c5
FB
156 m48t59_write(nvram, i++, macaddr[j++]);
157 m48t59_write(nvram, i++, macaddr[j++]);
158 m48t59_write(nvram, i++, macaddr[j++]);
159 m48t59_write(nvram, i++, macaddr[j++]);
160 m48t59_write(nvram, i++, macaddr[j++]);
161 m48t59_write(nvram, i, macaddr[j]);
e80cfcfc
FB
162
163 /* Calculate checksum */
164 for (i = 0x1fd8; i < 0x1fe7; i++) {
819385c5 165 tmp ^= m48t59_read(nvram, i);
e80cfcfc 166 }
819385c5 167 m48t59_write(nvram, 0x1fe7, tmp);
e80cfcfc
FB
168}
169
170static void *slavio_intctl;
171
172void pic_info()
173{
174 slavio_pic_info(slavio_intctl);
175}
176
177void irq_info()
178{
179 slavio_irq_info(slavio_intctl);
180}
181
182void pic_set_irq(int irq, int level)
183{
184 slavio_pic_set_irq(slavio_intctl, irq, level);
185}
186
502a5395
PB
187void pic_set_irq_new(void *opaque, int irq, int level)
188{
189 pic_set_irq(irq, level);
190}
191
ba3c64fb
FB
192void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
193{
194 slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
195}
196
3475187d
FB
197static void *slavio_misc;
198
199void qemu_system_powerdown(void)
200{
201 slavio_set_power_fail(slavio_misc, 1);
202}
203
c68ea704
FB
204static void main_cpu_reset(void *opaque)
205{
206 CPUState *env = opaque;
207 cpu_reset(env);
208}
209
420557e8 210/* Sun4m hardware initialisation */
c0e564d5
FB
211static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
212 DisplayState *ds, const char **fd_filename, int snapshot,
213 const char *kernel_filename, const char *kernel_cmdline,
94fc95cd 214 const char *initrd_filename, const char *cpu_model)
420557e8 215{
ba3c64fb 216 CPUState *env, *envs[MAX_CPUS];
420557e8 217 char buf[1024];
8d5f07fa 218 int ret, linux_boot;
713c45fa 219 unsigned int i;
6f7e9aec 220 long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
67e999be 221 void *iommu, *dma, *main_esp, *main_lance = NULL;
420557e8
FB
222
223 linux_boot = (kernel_filename != NULL);
224
ba3c64fb
FB
225 /* init CPUs */
226 for(i = 0; i < smp_cpus; i++) {
227 env = cpu_init();
228 envs[i] = env;
229 if (i != 0)
230 env->halted = 1;
231 register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
232 qemu_register_reset(main_cpu_reset, env);
233 }
420557e8
FB
234 /* allocate RAM */
235 cpu_register_physical_memory(0, ram_size, 0);
420557e8 236
e80cfcfc
FB
237 iommu = iommu_init(PHYS_JJ_IOMMU);
238 slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
ba3c64fb
FB
239 for(i = 0; i < smp_cpus; i++) {
240 slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
241 }
67e999be 242 dma = sparc32_dma_init(PHYS_JJ_DMA, PHYS_JJ_ESP_IRQ, PHYS_JJ_LE_IRQ, iommu, slavio_intctl);
ba3c64fb 243
95219897 244 tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
a41b2ff2
PB
245 if (nd_table[0].vlan) {
246 if (nd_table[0].model == NULL
247 || strcmp(nd_table[0].model, "lance") == 0) {
67e999be 248 main_lance = lance_init(&nd_table[0], PHYS_JJ_LE, dma);
a41b2ff2
PB
249 } else {
250 fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
251 exit (1);
252 }
253 }
819385c5 254 nvram = m48t59_init(0, PHYS_JJ_EEPROM, 0, PHYS_JJ_EEPROM_SIZE, 8);
ba3c64fb
FB
255 for (i = 0; i < MAX_CPUS; i++) {
256 slavio_timer_init(PHYS_JJ_CLOCK + i * TARGET_PAGE_SIZE, PHYS_JJ_CLOCK_IRQ, 0, i);
257 }
258 slavio_timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ, 2, (unsigned int)-1);
e80cfcfc 259 slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
b81b3b10
FB
260 // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
261 // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
262 slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
e80cfcfc 263 fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
67e999be 264 main_esp = esp_init(bs_table, PHYS_JJ_ESP, dma);
f1587550
TS
265
266 for (i = 0; i < MAX_DISKS; i++) {
267 if (bs_table[i]) {
268 esp_scsi_attach(main_esp, bs_table[i], i);
269 }
270 }
271
3475187d 272 slavio_misc = slavio_misc_init(PHYS_JJ_SLAVIO, PHYS_JJ_ME_IRQ);
b8174937 273 cs_init(PHYS_JJ_CS, PHYS_JJ_CS_IRQ, slavio_intctl);
67e999be 274 sparc32_dma_set_reset_data(dma, main_esp, main_lance);
420557e8 275
e80cfcfc 276 prom_offset = ram_size + vram_size;
b3783731
FB
277 cpu_register_physical_memory(PROM_ADDR,
278 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
279 prom_offset | IO_MEM_ROM);
e80cfcfc 280
0986ac3b 281 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
9ee3c029 282 ret = load_elf(buf, 0, NULL);
e80cfcfc
FB
283 if (ret < 0) {
284 fprintf(stderr, "qemu: could not load prom '%s'\n",
285 buf);
286 exit(1);
287 }
e80cfcfc 288
6f7e9aec 289 kernel_size = 0;
e80cfcfc 290 if (linux_boot) {
9ee3c029 291 kernel_size = load_elf(kernel_filename, -0xf0000000, NULL);
6f7e9aec
FB
292 if (kernel_size < 0)
293 kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
294 if (kernel_size < 0)
295 kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
296 if (kernel_size < 0) {
420557e8 297 fprintf(stderr, "qemu: could not load kernel '%s'\n",
e80cfcfc
FB
298 kernel_filename);
299 exit(1);
420557e8 300 }
713c45fa
FB
301
302 /* load initrd */
303 initrd_size = 0;
304 if (initrd_filename) {
305 initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
306 if (initrd_size < 0) {
307 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
308 initrd_filename);
309 exit(1);
310 }
311 }
312 if (initrd_size > 0) {
313 for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
314 if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
315 == 0x48647253) { // HdrS
316 stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
317 stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
318 break;
319 }
320 }
321 }
420557e8 322 }
6f7e9aec 323 nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth);
420557e8 324}
c0e564d5
FB
325
326QEMUMachine sun4m_machine = {
327 "sun4m",
328 "Sun4m platform",
329 sun4m_init,
330};
This page took 0.112439 seconds and 4 git commands to generate.