fix missing type declarations (Joachim Henke)
[qemu] / hw / sun4u.c
1 /*
2  * QEMU Sun4u System Emulator
3  * 
4  * Copyright (c) 2005 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 "m48t59.h"
26
27 #define KERNEL_LOAD_ADDR     0x00404000
28 #define CMDLINE_ADDR         0x003ff000
29 #define INITRD_LOAD_ADDR     0x00300000
30 #define PROM_SIZE_MAX        (256 * 1024)
31 #define PROM_ADDR            0x1fff0000000ULL
32 #define APB_SPECIAL_BASE     0x1fe00000000ULL
33 #define APB_MEM_BASE         0x1ff00000000ULL
34 #define VGA_BASE             (APB_MEM_BASE + 0x400000ULL)
35 #define PROM_FILENAMEB       "proll-sparc64.bin"
36 #define PROM_FILENAMEE       "proll-sparc64.elf"
37 #define NVRAM_SIZE           0x2000
38
39 /* TSC handling */
40
41 uint64_t cpu_get_tsc()
42 {
43     return qemu_get_clock(vm_clock);
44 }
45
46 int DMA_get_channel_mode (int nchan)
47 {
48     return 0;
49 }
50 int DMA_read_memory (int nchan, void *buf, int pos, int size)
51 {
52     return 0;
53 }
54 int DMA_write_memory (int nchan, void *buf, int pos, int size)
55 {
56     return 0;
57 }
58 void DMA_hold_DREQ (int nchan) {}
59 void DMA_release_DREQ (int nchan) {}
60 void DMA_schedule(int nchan) {}
61 void DMA_run (void) {}
62 void DMA_init (int high_page_enable) {}
63 void DMA_register_channel (int nchan,
64                            DMA_transfer_handler transfer_handler,
65                            void *opaque)
66 {
67 }
68
69 /* NVRAM helpers */
70 void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
71 {
72     m48t59_write(nvram, addr, value);
73 }
74
75 uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
76 {
77     return m48t59_read(nvram, addr);
78 }
79
80 void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
81 {
82     m48t59_write(nvram, addr, value >> 8);
83     m48t59_write(nvram, addr + 1, value & 0xFF);
84 }
85
86 uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
87 {
88     uint16_t tmp;
89
90     tmp = m48t59_read(nvram, addr) << 8;
91     tmp |= m48t59_read(nvram, addr + 1);
92
93     return tmp;
94 }
95
96 void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
97 {
98     m48t59_write(nvram, addr, value >> 24);
99     m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
100     m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
101     m48t59_write(nvram, addr + 3, value & 0xFF);
102 }
103
104 uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
105 {
106     uint32_t tmp;
107
108     tmp = m48t59_read(nvram, addr) << 24;
109     tmp |= m48t59_read(nvram, addr + 1) << 16;
110     tmp |= m48t59_read(nvram, addr + 2) << 8;
111     tmp |= m48t59_read(nvram, addr + 3);
112
113     return tmp;
114 }
115
116 void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
117                        const unsigned char *str, uint32_t max)
118 {
119     int i;
120
121     for (i = 0; i < max && str[i] != '\0'; i++) {
122         m48t59_write(nvram, addr + i, str[i]);
123     }
124     m48t59_write(nvram, addr + max - 1, '\0');
125 }
126
127 int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
128 {
129     int i;
130
131     memset(dst, 0, max);
132     for (i = 0; i < max; i++) {
133         dst[i] = NVRAM_get_byte(nvram, addr + i);
134         if (dst[i] == '\0')
135             break;
136     }
137
138     return i;
139 }
140
141 static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
142 {
143     uint16_t tmp;
144     uint16_t pd, pd1, pd2;
145
146     tmp = prev >> 8;
147     pd = prev ^ value;
148     pd1 = pd & 0x000F;
149     pd2 = ((pd >> 4) & 0x000F) ^ pd1;
150     tmp ^= (pd1 << 3) | (pd1 << 8);
151     tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
152
153     return tmp;
154 }
155
156 uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
157 {
158     uint32_t i;
159     uint16_t crc = 0xFFFF;
160     int odd;
161
162     odd = count & 1;
163     count &= ~1;
164     for (i = 0; i != count; i++) {
165         crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
166     }
167     if (odd) {
168         crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
169     }
170
171     return crc;
172 }
173
174 extern int nographic;
175
176 int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
177                           const unsigned char *arch,
178                           uint32_t RAM_size, int boot_device,
179                           uint32_t kernel_image, uint32_t kernel_size,
180                           const char *cmdline,
181                           uint32_t initrd_image, uint32_t initrd_size,
182                           uint32_t NVRAM_image,
183                           int width, int height, int depth)
184 {
185     uint16_t crc;
186
187     /* Set parameters for Open Hack'Ware BIOS */
188     NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
189     NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
190     NVRAM_set_word(nvram,   0x14, NVRAM_size);
191     NVRAM_set_string(nvram, 0x20, arch, 16);
192     NVRAM_set_byte(nvram,   0x2f, nographic & 0xff);
193     NVRAM_set_lword(nvram,  0x30, RAM_size);
194     NVRAM_set_byte(nvram,   0x34, boot_device);
195     NVRAM_set_lword(nvram,  0x38, kernel_image);
196     NVRAM_set_lword(nvram,  0x3C, kernel_size);
197     if (cmdline) {
198         /* XXX: put the cmdline in NVRAM too ? */
199         strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
200         NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
201         NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
202     } else {
203         NVRAM_set_lword(nvram,  0x40, 0);
204         NVRAM_set_lword(nvram,  0x44, 0);
205     }
206     NVRAM_set_lword(nvram,  0x48, initrd_image);
207     NVRAM_set_lword(nvram,  0x4C, initrd_size);
208     NVRAM_set_lword(nvram,  0x50, NVRAM_image);
209
210     NVRAM_set_word(nvram,   0x54, width);
211     NVRAM_set_word(nvram,   0x56, height);
212     NVRAM_set_word(nvram,   0x58, depth);
213     crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
214     NVRAM_set_word(nvram,  0xFC, crc);
215
216     return 0;
217 }
218
219 void pic_info()
220 {
221 }
222
223 void irq_info()
224 {
225 }
226
227 void pic_set_irq(int irq, int level)
228 {
229 }
230
231 void pic_set_irq_new(void *opaque, int irq, int level)
232 {
233 }
234
235 void qemu_system_powerdown(void)
236 {
237 }
238
239 static void main_cpu_reset(void *opaque)
240 {
241     CPUState *env = opaque;
242     cpu_reset(env);
243 }
244
245 static const int ide_iobase[2] = { 0x1f0, 0x170 };
246 static const int ide_iobase2[2] = { 0x3f6, 0x376 };
247 static const int ide_irq[2] = { 14, 15 };
248
249 static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
250 static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
251
252 static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
253 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
254
255 static fdctrl_t *floppy_controller;
256
257 /* Sun4u hardware initialisation */
258 static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
259              DisplayState *ds, const char **fd_filename, int snapshot,
260              const char *kernel_filename, const char *kernel_cmdline,
261              const char *initrd_filename)
262 {
263     CPUState *env;
264     char buf[1024];
265     m48t59_t *nvram;
266     int ret, linux_boot;
267     unsigned int i;
268     long prom_offset, initrd_size, kernel_size;
269     PCIBus *pci_bus;
270
271     linux_boot = (kernel_filename != NULL);
272
273     env = cpu_init();
274     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
275     qemu_register_reset(main_cpu_reset, env);
276
277     /* allocate RAM */
278     cpu_register_physical_memory(0, ram_size, 0);
279
280     prom_offset = ram_size + vga_ram_size;
281     cpu_register_physical_memory(PROM_ADDR, 
282                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK, 
283                                  prom_offset | IO_MEM_ROM);
284
285     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
286     ret = load_elf(buf, 0, NULL);
287     if (ret < 0) {
288         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
289         ret = load_image(buf, phys_ram_base + prom_offset);
290     }
291     if (ret < 0) {
292         fprintf(stderr, "qemu: could not load prom '%s'\n", 
293                 buf);
294         exit(1);
295     }
296
297     kernel_size = 0;
298     initrd_size = 0;
299     if (linux_boot) {
300         /* XXX: put correct offset */
301         kernel_size = load_elf(kernel_filename, 0, NULL);
302         if (kernel_size < 0)
303             kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
304         if (kernel_size < 0)
305             kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
306         if (kernel_size < 0) {
307             fprintf(stderr, "qemu: could not load kernel '%s'\n", 
308                     kernel_filename);
309             exit(1);
310         }
311
312         /* load initrd */
313         if (initrd_filename) {
314             initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
315             if (initrd_size < 0) {
316                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
317                         initrd_filename);
318                 exit(1);
319             }
320         }
321         if (initrd_size > 0) {
322             for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
323                 if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
324                     == 0x48647253) { // HdrS
325                     stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
326                     stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
327                     break;
328                 }
329             }
330         }
331     }
332     pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
333     isa_mem_base = VGA_BASE;
334     vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
335                    vga_ram_size, 0, 0);
336     cpu_register_physical_memory(VGA_BASE, vga_ram_size, ram_size);
337     //pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size);
338
339     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
340         if (serial_hds[i]) {
341             serial_init(&pic_set_irq_new, NULL,
342                         serial_io[i], serial_irq[i], serial_hds[i]);
343         }
344     }
345
346     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
347         if (parallel_hds[i]) {
348             parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
349         }
350     }
351
352     for(i = 0; i < nb_nics; i++) {
353         if (!nd_table[i].model)
354             nd_table[i].model = "ne2k_pci";
355         pci_nic_init(pci_bus, &nd_table[i]);
356     }
357
358     pci_cmd646_ide_init(pci_bus, bs_table, 1);
359     kbd_init();
360     floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
361     nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
362     sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device,
363                          KERNEL_LOAD_ADDR, kernel_size,
364                          kernel_cmdline,
365                          INITRD_LOAD_ADDR, initrd_size,
366                          /* XXX: need an option to load a NVRAM image */
367                          0,
368                          graphic_width, graphic_height, graphic_depth);
369
370 }
371
372 QEMUMachine sun4u_machine = {
373     "sun4u",
374     "Sun4u platform",
375     sun4u_init,
376 };