|
|
1.1 root 1: /*
1.1.1.7 root 2: * QEMU Sun4u/Sun4v System Emulator
1.1.1.6 root 3: *
1.1 root 4: * Copyright (c) 2005 Fabrice Bellard
1.1.1.6 root 5: *
1.1 root 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: */
1.1.1.6 root 24: #include "hw.h"
25: #include "pci.h"
1.1.1.9 ! root 26: #include "apb_pci.h"
1.1.1.6 root 27: #include "pc.h"
28: #include "nvram.h"
29: #include "fdc.h"
30: #include "net.h"
31: #include "qemu-timer.h"
32: #include "sysemu.h"
33: #include "boards.h"
34: #include "firmware_abi.h"
1.1.1.7 root 35: #include "fw_cfg.h"
1.1.1.9 ! root 36: #include "sysbus.h"
! 37: #include "ide.h"
! 38: #include "loader.h"
! 39: #include "elf.h"
1.1.1.7 root 40:
41: //#define DEBUG_IRQ
42:
43: #ifdef DEBUG_IRQ
1.1.1.8 root 44: #define DPRINTF(fmt, ...) \
45: do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.7 root 46: #else
1.1.1.8 root 47: #define DPRINTF(fmt, ...)
1.1.1.7 root 48: #endif
1.1 root 49:
50: #define KERNEL_LOAD_ADDR 0x00404000
51: #define CMDLINE_ADDR 0x003ff000
52: #define INITRD_LOAD_ADDR 0x00300000
1.1.1.7 root 53: #define PROM_SIZE_MAX (4 * 1024 * 1024)
1.1.1.6 root 54: #define PROM_VADDR 0x000ffd00000ULL
1.1 root 55: #define APB_SPECIAL_BASE 0x1fe00000000ULL
1.1.1.6 root 56: #define APB_MEM_BASE 0x1ff00000000ULL
57: #define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
58: #define PROM_FILENAME "openbios-sparc64"
1.1 root 59: #define NVRAM_SIZE 0x2000
1.1.1.6 root 60: #define MAX_IDE_BUS 2
1.1.1.7 root 61: #define BIOS_CFG_IOPORT 0x510
1.1.1.9 ! root 62: #define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
! 63: #define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
! 64: #define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
1.1 root 65:
1.1.1.7 root 66: #define MAX_PILS 16
1.1 root 67:
1.1.1.7 root 68: #define TICK_INT_DIS 0x8000000000000000ULL
69: #define TICK_MAX 0x7fffffffffffffffULL
70:
71: struct hwdef {
72: const char * const default_cpu_model;
73: uint16_t machine_id;
74: uint64_t prom_addr;
75: uint64_t console_serial_base;
76: };
1.1 root 77:
78: int DMA_get_channel_mode (int nchan)
79: {
80: return 0;
81: }
82: int DMA_read_memory (int nchan, void *buf, int pos, int size)
83: {
84: return 0;
85: }
86: int DMA_write_memory (int nchan, void *buf, int pos, int size)
87: {
88: return 0;
89: }
90: void DMA_hold_DREQ (int nchan) {}
91: void DMA_release_DREQ (int nchan) {}
92: void DMA_schedule(int nchan) {}
93: void DMA_init (int high_page_enable) {}
94: void DMA_register_channel (int nchan,
95: DMA_transfer_handler transfer_handler,
96: void *opaque)
97: {
98: }
99:
1.1.1.8 root 100: static int fw_cfg_boot_set(void *opaque, const char *boot_device)
1.1.1.7 root 101: {
1.1.1.8 root 102: fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
1.1.1.7 root 103: return 0;
104: }
1.1 root 105:
1.1.1.6 root 106: static int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
1.1.1.7 root 107: const char *arch,
108: ram_addr_t RAM_size,
109: const char *boot_devices,
1.1.1.6 root 110: uint32_t kernel_image, uint32_t kernel_size,
111: const char *cmdline,
112: uint32_t initrd_image, uint32_t initrd_size,
113: uint32_t NVRAM_image,
1.1.1.7 root 114: int width, int height, int depth,
115: const uint8_t *macaddr)
1.1 root 116: {
1.1.1.6 root 117: unsigned int i;
118: uint32_t start, end;
119: uint8_t image[0x1ff0];
120: struct OpenBIOS_nvpart_v1 *part_header;
121:
122: memset(image, '\0', sizeof(image));
123:
1.1.1.8 root 124: start = 0;
1.1.1.6 root 125:
126: // OpenBIOS nvram variables
127: // Variable partition
128: part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
129: part_header->signature = OPENBIOS_PART_SYSTEM;
1.1.1.7 root 130: pstrcpy(part_header->name, sizeof(part_header->name), "system");
1.1.1.6 root 131:
132: end = start + sizeof(struct OpenBIOS_nvpart_v1);
133: for (i = 0; i < nb_prom_envs; i++)
134: end = OpenBIOS_set_var(image, end, prom_envs[i]);
135:
136: // End marker
137: image[end++] = '\0';
138:
139: end = start + ((end - start + 15) & ~15);
140: OpenBIOS_finish_partition(part_header, end - start);
141:
142: // free partition
143: start = end;
144: part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
145: part_header->signature = OPENBIOS_PART_FREE;
1.1.1.7 root 146: pstrcpy(part_header->name, sizeof(part_header->name), "free");
1.1 root 147:
1.1.1.6 root 148: end = 0x1fd0;
149: OpenBIOS_finish_partition(part_header, end - start);
1.1 root 150:
1.1.1.7 root 151: Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
152:
1.1.1.6 root 153: for (i = 0; i < sizeof(image); i++)
154: m48t59_write(nvram, i, image[i]);
1.1 root 155:
1.1.1.6 root 156: return 0;
1.1 root 157: }
1.1.1.9 ! root 158: static unsigned long sun4u_load_kernel(const char *kernel_filename,
! 159: const char *initrd_filename,
! 160: ram_addr_t RAM_size, long *initrd_size)
! 161: {
! 162: int linux_boot;
! 163: unsigned int i;
! 164: long kernel_size;
! 165:
! 166: linux_boot = (kernel_filename != NULL);
! 167:
! 168: kernel_size = 0;
! 169: if (linux_boot) {
! 170: int bswap_needed;
! 171:
! 172: #ifdef BSWAP_NEEDED
! 173: bswap_needed = 1;
! 174: #else
! 175: bswap_needed = 0;
! 176: #endif
! 177: kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL,
! 178: 1, ELF_MACHINE, 0);
! 179: if (kernel_size < 0)
! 180: kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
! 181: RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
! 182: TARGET_PAGE_SIZE);
! 183: if (kernel_size < 0)
! 184: kernel_size = load_image_targphys(kernel_filename,
! 185: KERNEL_LOAD_ADDR,
! 186: RAM_size - KERNEL_LOAD_ADDR);
! 187: if (kernel_size < 0) {
! 188: fprintf(stderr, "qemu: could not load kernel '%s'\n",
! 189: kernel_filename);
! 190: exit(1);
! 191: }
! 192:
! 193: /* load initrd */
! 194: *initrd_size = 0;
! 195: if (initrd_filename) {
! 196: *initrd_size = load_image_targphys(initrd_filename,
! 197: INITRD_LOAD_ADDR,
! 198: RAM_size - INITRD_LOAD_ADDR);
! 199: if (*initrd_size < 0) {
! 200: fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
! 201: initrd_filename);
! 202: exit(1);
! 203: }
! 204: }
! 205: if (*initrd_size > 0) {
! 206: for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
! 207: if (ldl_phys(KERNEL_LOAD_ADDR + i) == 0x48647253) { // HdrS
! 208: stl_phys(KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
! 209: stl_phys(KERNEL_LOAD_ADDR + i + 20, *initrd_size);
! 210: break;
! 211: }
! 212: }
! 213: }
! 214: }
! 215: return kernel_size;
! 216: }
1.1 root 217:
1.1.1.8 root 218: void pic_info(Monitor *mon)
1.1 root 219: {
220: }
221:
1.1.1.8 root 222: void irq_info(Monitor *mon)
1.1 root 223: {
224: }
225:
1.1.1.7 root 226: void cpu_check_irqs(CPUState *env)
227: {
228: uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) |
229: ((env->softint & SOFTINT_TIMER) << 14);
230:
231: if (pil && (env->interrupt_index == 0 ||
232: (env->interrupt_index & ~15) == TT_EXTINT)) {
233: unsigned int i;
234:
235: for (i = 15; i > 0; i--) {
236: if (pil & (1 << i)) {
237: int old_interrupt = env->interrupt_index;
238:
239: env->interrupt_index = TT_EXTINT | i;
240: if (old_interrupt != env->interrupt_index) {
241: DPRINTF("Set CPU IRQ %d\n", i);
242: cpu_interrupt(env, CPU_INTERRUPT_HARD);
243: }
244: break;
245: }
246: }
247: } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) {
248: DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15);
249: env->interrupt_index = 0;
250: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
251: }
252: }
253:
254: static void cpu_set_irq(void *opaque, int irq, int level)
255: {
256: CPUState *env = opaque;
257:
258: if (level) {
259: DPRINTF("Raise CPU IRQ %d\n", irq);
260: env->halted = 0;
261: env->pil_in |= 1 << irq;
262: cpu_check_irqs(env);
263: } else {
264: DPRINTF("Lower CPU IRQ %d\n", irq);
265: env->pil_in &= ~(1 << irq);
266: cpu_check_irqs(env);
267: }
268: }
269:
270: typedef struct ResetData {
271: CPUState *env;
1.1.1.9 ! root 272: uint64_t prom_addr;
1.1.1.7 root 273: } ResetData;
274:
1.1.1.6 root 275: static void main_cpu_reset(void *opaque)
1.1 root 276: {
1.1.1.7 root 277: ResetData *s = (ResetData *)opaque;
278: CPUState *env = s->env;
1.1.1.9 ! root 279: static unsigned int nr_resets;
1.1 root 280:
1.1.1.6 root 281: cpu_reset(env);
1.1.1.7 root 282: env->tick_cmpr = TICK_INT_DIS | 0;
283: ptimer_set_limit(env->tick, TICK_MAX, 1);
284: ptimer_run(env->tick, 1);
285: env->stick_cmpr = TICK_INT_DIS | 0;
286: ptimer_set_limit(env->stick, TICK_MAX, 1);
287: ptimer_run(env->stick, 1);
288: env->hstick_cmpr = TICK_INT_DIS | 0;
289: ptimer_set_limit(env->hstick, TICK_MAX, 1);
290: ptimer_run(env->hstick, 1);
291: env->gregs[1] = 0; // Memory start
292: env->gregs[2] = ram_size; // Memory size
293: env->gregs[3] = 0; // Machine description XXX
1.1.1.9 ! root 294: if (nr_resets++ == 0) {
! 295: /* Power on reset */
! 296: env->pc = s->prom_addr + 0x20ULL;
! 297: } else {
! 298: env->pc = s->prom_addr + 0x40ULL;
! 299: }
1.1.1.7 root 300: env->npc = env->pc + 4;
1.1 root 301: }
302:
1.1.1.7 root 303: static void tick_irq(void *opaque)
1.1 root 304: {
1.1.1.6 root 305: CPUState *env = opaque;
1.1 root 306:
1.1.1.7 root 307: if (!(env->tick_cmpr & TICK_INT_DIS)) {
308: env->softint |= SOFTINT_TIMER;
309: cpu_interrupt(env, CPU_INTERRUPT_TIMER);
310: }
1.1 root 311: }
312:
1.1.1.7 root 313: static void stick_irq(void *opaque)
1.1 root 314: {
1.1.1.6 root 315: CPUState *env = opaque;
1.1 root 316:
1.1.1.7 root 317: if (!(env->stick_cmpr & TICK_INT_DIS)) {
318: env->softint |= SOFTINT_STIMER;
319: cpu_interrupt(env, CPU_INTERRUPT_TIMER);
320: }
1.1 root 321: }
322:
1.1.1.7 root 323: static void hstick_irq(void *opaque)
1.1 root 324: {
1.1.1.6 root 325: CPUState *env = opaque;
1.1 root 326:
1.1.1.7 root 327: if (!(env->hstick_cmpr & TICK_INT_DIS)) {
328: cpu_interrupt(env, CPU_INTERRUPT_TIMER);
329: }
330: }
331:
332: void cpu_tick_set_count(void *opaque, uint64_t count)
333: {
334: ptimer_set_count(opaque, -count);
1.1 root 335: }
336:
1.1.1.7 root 337: uint64_t cpu_tick_get_count(void *opaque)
1.1.1.2 root 338: {
1.1.1.7 root 339: return -ptimer_get_count(opaque);
340: }
341:
342: void cpu_tick_set_limit(void *opaque, uint64_t limit)
343: {
344: ptimer_set_limit(opaque, -limit, 0);
1.1.1.2 root 345: }
346:
1.1.1.7 root 347: static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
1.1.1.9 ! root 348: pcibus_t addr, pcibus_t size, int type)
1.1.1.7 root 349: {
350: DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
351: switch (region_num) {
352: case 0:
353: isa_mmio_init(addr, 0x1000000);
354: break;
355: case 1:
356: isa_mmio_init(addr, 0x800000);
357: break;
358: }
359: }
360:
1.1.1.9 ! root 361: static void dummy_isa_irq_handler(void *opaque, int n, int level)
! 362: {
! 363: }
! 364:
1.1.1.7 root 365: /* EBUS (Eight bit bus) bridge */
366: static void
367: pci_ebus_init(PCIBus *bus, int devfn)
368: {
1.1.1.9 ! root 369: qemu_irq *isa_irq;
! 370:
1.1.1.8 root 371: pci_create_simple(bus, devfn, "ebus");
1.1.1.9 ! root 372: isa_irq = qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16);
! 373: isa_bus_irqs(isa_irq);
1.1.1.8 root 374: }
1.1.1.7 root 375:
1.1.1.9 ! root 376: static int
1.1.1.8 root 377: pci_ebus_init1(PCIDevice *s)
378: {
1.1.1.9 ! root 379: isa_bus_new(&s->qdev);
! 380:
1.1.1.7 root 381: pci_config_set_vendor_id(s->config, PCI_VENDOR_ID_SUN);
382: pci_config_set_device_id(s->config, PCI_DEVICE_ID_SUN_EBUS);
383: s->config[0x04] = 0x06; // command = bus master, pci mem
384: s->config[0x05] = 0x00;
385: s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
386: s->config[0x07] = 0x03; // status = medium devsel
387: s->config[0x08] = 0x01; // revision
388: s->config[0x09] = 0x00; // programming i/f
389: pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER);
390: s->config[0x0D] = 0x0a; // latency_timer
1.1.1.8 root 391: s->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
1.1.1.7 root 392:
1.1.1.9 ! root 393: pci_register_bar(s, 0, 0x1000000, PCI_BASE_ADDRESS_SPACE_MEMORY,
1.1.1.7 root 394: ebus_mmio_mapfunc);
1.1.1.9 ! root 395: pci_register_bar(s, 1, 0x800000, PCI_BASE_ADDRESS_SPACE_MEMORY,
1.1.1.7 root 396: ebus_mmio_mapfunc);
1.1.1.9 ! root 397: return 0;
1.1.1.7 root 398: }
399:
1.1.1.8 root 400: static PCIDeviceInfo ebus_info = {
401: .qdev.name = "ebus",
402: .qdev.size = sizeof(PCIDevice),
403: .init = pci_ebus_init1,
404: };
405:
406: static void pci_ebus_register(void)
407: {
408: pci_qdev_register(&ebus_info);
409: }
410:
411: device_init(pci_ebus_register);
412:
1.1.1.9 ! root 413: /* Boot PROM (OpenBIOS) */
! 414: static void prom_init(target_phys_addr_t addr, const char *bios_name)
1.1 root 415: {
1.1.1.9 ! root 416: DeviceState *dev;
! 417: SysBusDevice *s;
1.1.1.8 root 418: char *filename;
1.1.1.9 ! root 419: int ret;
! 420:
! 421: dev = qdev_create(NULL, "openprom");
! 422: qdev_init_nofail(dev);
! 423: s = sysbus_from_qdev(dev);
! 424:
! 425: sysbus_mmio_map(s, 0, addr);
! 426:
! 427: /* load boot prom */
! 428: if (bios_name == NULL) {
! 429: bios_name = PROM_FILENAME;
! 430: }
! 431: filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
! 432: if (filename) {
! 433: ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL,
! 434: 1, ELF_MACHINE, 0);
! 435: if (ret < 0 || ret > PROM_SIZE_MAX) {
! 436: ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
! 437: }
! 438: qemu_free(filename);
! 439: } else {
! 440: ret = -1;
! 441: }
! 442: if (ret < 0 || ret > PROM_SIZE_MAX) {
! 443: fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
! 444: exit(1);
! 445: }
! 446: }
! 447:
! 448: static int prom_init1(SysBusDevice *dev)
! 449: {
! 450: ram_addr_t prom_offset;
! 451:
! 452: prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
! 453: sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
! 454: return 0;
! 455: }
! 456:
! 457: static SysBusDeviceInfo prom_info = {
! 458: .init = prom_init1,
! 459: .qdev.name = "openprom",
! 460: .qdev.size = sizeof(SysBusDevice),
! 461: .qdev.props = (Property[]) {
! 462: {/* end of property list */}
! 463: }
! 464: };
! 465:
! 466: static void prom_register_devices(void)
! 467: {
! 468: sysbus_register_withprop(&prom_info);
! 469: }
! 470:
! 471: device_init(prom_register_devices);
! 472:
! 473:
! 474: typedef struct RamDevice
! 475: {
! 476: SysBusDevice busdev;
! 477: uint64_t size;
! 478: } RamDevice;
! 479:
! 480: /* System RAM */
! 481: static int ram_init1(SysBusDevice *dev)
! 482: {
! 483: ram_addr_t RAM_size, ram_offset;
! 484: RamDevice *d = FROM_SYSBUS(RamDevice, dev);
! 485:
! 486: RAM_size = d->size;
! 487:
! 488: ram_offset = qemu_ram_alloc(RAM_size);
! 489: sysbus_init_mmio(dev, RAM_size, ram_offset);
! 490: return 0;
! 491: }
! 492:
! 493: static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size)
! 494: {
! 495: DeviceState *dev;
! 496: SysBusDevice *s;
! 497: RamDevice *d;
! 498:
! 499: /* allocate RAM */
! 500: dev = qdev_create(NULL, "memory");
! 501: s = sysbus_from_qdev(dev);
! 502:
! 503: d = FROM_SYSBUS(RamDevice, s);
! 504: d->size = RAM_size;
! 505: qdev_init_nofail(dev);
! 506:
! 507: sysbus_mmio_map(s, 0, addr);
! 508: }
! 509:
! 510: static SysBusDeviceInfo ram_info = {
! 511: .init = ram_init1,
! 512: .qdev.name = "memory",
! 513: .qdev.size = sizeof(RamDevice),
! 514: .qdev.props = (Property[]) {
! 515: DEFINE_PROP_UINT64("size", RamDevice, size, 0),
! 516: DEFINE_PROP_END_OF_LIST(),
! 517: }
! 518: };
! 519:
! 520: static void ram_register_devices(void)
! 521: {
! 522: sysbus_register_withprop(&ram_info);
! 523: }
! 524:
! 525: device_init(ram_register_devices);
! 526:
! 527: static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
! 528: {
! 529: CPUState *env;
1.1.1.6 root 530: QEMUBH *bh;
1.1.1.7 root 531: ResetData *reset_info;
1.1 root 532:
1.1.1.7 root 533: if (!cpu_model)
534: cpu_model = hwdef->default_cpu_model;
1.1.1.6 root 535: env = cpu_init(cpu_model);
536: if (!env) {
537: fprintf(stderr, "Unable to find Sparc CPU definition\n");
538: exit(1);
539: }
540: bh = qemu_bh_new(tick_irq, env);
541: env->tick = ptimer_init(bh);
542: ptimer_set_period(env->tick, 1ULL);
543:
544: bh = qemu_bh_new(stick_irq, env);
545: env->stick = ptimer_init(bh);
546: ptimer_set_period(env->stick, 1ULL);
547:
548: bh = qemu_bh_new(hstick_irq, env);
549: env->hstick = ptimer_init(bh);
550: ptimer_set_period(env->hstick, 1ULL);
1.1.1.7 root 551:
552: reset_info = qemu_mallocz(sizeof(ResetData));
553: reset_info->env = env;
1.1.1.9 ! root 554: reset_info->prom_addr = hwdef->prom_addr;
1.1.1.7 root 555: qemu_register_reset(main_cpu_reset, reset_info);
1.1.1.2 root 556:
1.1.1.9 ! root 557: return env;
! 558: }
1.1 root 559:
1.1.1.9 ! root 560: static void sun4uv_init(ram_addr_t RAM_size,
! 561: const char *boot_devices,
! 562: const char *kernel_filename, const char *kernel_cmdline,
! 563: const char *initrd_filename, const char *cpu_model,
! 564: const struct hwdef *hwdef)
! 565: {
! 566: CPUState *env;
! 567: m48t59_t *nvram;
! 568: unsigned int i;
! 569: long initrd_size, kernel_size;
! 570: PCIBus *pci_bus, *pci_bus2, *pci_bus3;
! 571: qemu_irq *irq;
! 572: DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
! 573: DriveInfo *fd[MAX_FD];
! 574: void *fw_cfg;
1.1 root 575:
1.1.1.9 ! root 576: /* init CPUs */
! 577: env = cpu_devinit(cpu_model, hwdef);
1.1 root 578:
1.1.1.9 ! root 579: /* set up devices */
! 580: ram_init(0, RAM_size);
! 581:
! 582: prom_init(hwdef->prom_addr, bios_name);
1.1 root 583:
1.1.1.8 root 584:
585: irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
586: pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
1.1.1.7 root 587: &pci_bus3);
1.1 root 588: isa_mem_base = VGA_BASE;
1.1.1.8 root 589: pci_vga_init(pci_bus, 0, 0);
1.1.1.7 root 590:
591: // XXX Should be pci_bus3
592: pci_ebus_init(pci_bus, -1);
593:
594: i = 0;
595: if (hwdef->console_serial_base) {
596: serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200,
597: serial_hds[i], 1);
598: i++;
599: }
600: for(; i < MAX_SERIAL_PORTS; i++) {
1.1 root 601: if (serial_hds[i]) {
1.1.1.9 ! root 602: serial_isa_init(i, serial_hds[i]);
1.1 root 603: }
604: }
605:
606: for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
607: if (parallel_hds[i]) {
1.1.1.9 ! root 608: parallel_init(i, parallel_hds[i]);
1.1 root 609: }
610: }
611:
1.1.1.7 root 612: for(i = 0; i < nb_nics; i++)
1.1.1.9 ! root 613: pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
1.1 root 614:
1.1.1.6 root 615: if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
616: fprintf(stderr, "qemu: too many IDE bus\n");
617: exit(1);
618: }
619: for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
1.1.1.9 ! root 620: hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS,
! 621: i % MAX_IDE_DEVS);
1.1.1.6 root 622: }
623:
1.1.1.7 root 624: pci_cmd646_ide_init(pci_bus, hd, 1);
625:
1.1.1.9 ! root 626: isa_create_simple("i8042");
1.1.1.6 root 627: for(i = 0; i < MAX_FD; i++) {
1.1.1.9 ! root 628: fd[i] = drive_get(IF_FLOPPY, 0, i);
1.1.1.6 root 629: }
1.1.1.9 ! root 630: fdctrl_init_isa(fd);
! 631: nvram = m48t59_init_isa(0x0074, NVRAM_SIZE, 59);
! 632:
! 633: initrd_size = 0;
! 634: kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
! 635: ram_size, &initrd_size);
! 636:
1.1.1.7 root 637: sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
638: KERNEL_LOAD_ADDR, kernel_size,
639: kernel_cmdline,
640: INITRD_LOAD_ADDR, initrd_size,
641: /* XXX: need an option to load a NVRAM image */
642: 0,
643: graphic_width, graphic_height, graphic_depth,
644: (uint8_t *)&nd_table[0].macaddr);
645:
646: fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
647: fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
648: fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
649: fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
1.1.1.8 root 650: fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
651: fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
652: if (kernel_cmdline) {
653: fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
1.1.1.9 ! root 654: pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
1.1.1.8 root 655: } else {
656: fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
657: }
658: fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
659: fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
660: fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
1.1.1.9 ! root 661:
! 662: fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
! 663: fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
! 664: fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
! 665:
1.1.1.8 root 666: qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1.1.1.7 root 667: }
668:
669: enum {
670: sun4u_id = 0,
671: sun4v_id = 64,
672: niagara_id,
673: };
1.1 root 674:
1.1.1.7 root 675: static const struct hwdef hwdefs[] = {
676: /* Sun4u generic PC-like machine */
677: {
678: .default_cpu_model = "TI UltraSparc II",
679: .machine_id = sun4u_id,
680: .prom_addr = 0x1fff0000000ULL,
681: .console_serial_base = 0,
682: },
683: /* Sun4v generic PC-like machine */
684: {
685: .default_cpu_model = "Sun UltraSparc T1",
686: .machine_id = sun4v_id,
687: .prom_addr = 0x1fff0000000ULL,
688: .console_serial_base = 0,
689: },
690: /* Sun4v generic Niagara machine */
691: {
692: .default_cpu_model = "Sun UltraSparc T1",
693: .machine_id = niagara_id,
694: .prom_addr = 0xfff0000000ULL,
695: .console_serial_base = 0xfff0c2c000ULL,
696: },
697: };
698:
699: /* Sun4u hardware initialisation */
1.1.1.8 root 700: static void sun4u_init(ram_addr_t RAM_size,
1.1.1.7 root 701: const char *boot_devices,
702: const char *kernel_filename, const char *kernel_cmdline,
703: const char *initrd_filename, const char *cpu_model)
704: {
1.1.1.8 root 705: sun4uv_init(RAM_size, boot_devices, kernel_filename,
1.1.1.7 root 706: kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
707: }
708:
709: /* Sun4v hardware initialisation */
1.1.1.8 root 710: static void sun4v_init(ram_addr_t RAM_size,
1.1.1.7 root 711: const char *boot_devices,
712: const char *kernel_filename, const char *kernel_cmdline,
713: const char *initrd_filename, const char *cpu_model)
714: {
1.1.1.8 root 715: sun4uv_init(RAM_size, boot_devices, kernel_filename,
1.1.1.7 root 716: kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
717: }
718:
719: /* Niagara hardware initialisation */
1.1.1.8 root 720: static void niagara_init(ram_addr_t RAM_size,
1.1.1.7 root 721: const char *boot_devices,
722: const char *kernel_filename, const char *kernel_cmdline,
723: const char *initrd_filename, const char *cpu_model)
724: {
1.1.1.8 root 725: sun4uv_init(RAM_size, boot_devices, kernel_filename,
1.1.1.7 root 726: kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
1.1 root 727: }
728:
1.1.1.8 root 729: static QEMUMachine sun4u_machine = {
1.1.1.7 root 730: .name = "sun4u",
731: .desc = "Sun4u platform",
732: .init = sun4u_init,
733: .max_cpus = 1, // XXX for now
1.1.1.8 root 734: .is_default = 1,
1.1.1.7 root 735: };
736:
1.1.1.8 root 737: static QEMUMachine sun4v_machine = {
1.1.1.7 root 738: .name = "sun4v",
739: .desc = "Sun4v platform",
740: .init = sun4v_init,
741: .max_cpus = 1, // XXX for now
742: };
743:
1.1.1.8 root 744: static QEMUMachine niagara_machine = {
1.1.1.7 root 745: .name = "Niagara",
746: .desc = "Sun4v platform, Niagara",
747: .init = niagara_init,
748: .max_cpus = 1, // XXX for now
1.1 root 749: };
1.1.1.8 root 750:
751: static void sun4u_machine_init(void)
752: {
753: qemu_register_machine(&sun4u_machine);
754: qemu_register_machine(&sun4v_machine);
755: qemu_register_machine(&niagara_machine);
756: }
757:
758: machine_init(sun4u_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.