1
2
3
4
5
6
7
8
9#include "hw/hw.h"
10#include "elf.h"
11#include "hw/loader.h"
12#include "hw/boards.h"
13#include "alpha_sys.h"
14#include "sysemu/sysemu.h"
15#include "hw/timer/mc146818rtc.h"
16#include "hw/ide.h"
17#include "hw/timer/i8254.h"
18#include "hw/char/serial.h"
19
20#define MAX_IDE_BUS 2
21
22static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
23{
24 if (((addr >> 41) & 3) == 2) {
25 addr &= 0xffffffffffull;
26 }
27 return addr;
28}
29
30
31
32
33
34
35
36
37static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
38{
39 int slot = d->devfn >> 3;
40
41 assert(irq_num >= 0 && irq_num <= 3);
42
43 return (slot + 1) * 4 + irq_num;
44}
45
46static void clipper_init(MachineState *machine)
47{
48 ram_addr_t ram_size = machine->ram_size;
49 const char *cpu_model = machine->cpu_model;
50 const char *kernel_filename = machine->kernel_filename;
51 const char *kernel_cmdline = machine->kernel_cmdline;
52 const char *initrd_filename = machine->initrd_filename;
53 AlphaCPU *cpus[4];
54 PCIBus *pci_bus;
55 ISABus *isa_bus;
56 qemu_irq rtc_irq;
57 long size, i;
58 char *palcode_filename;
59 uint64_t palcode_entry, palcode_low, palcode_high;
60 uint64_t kernel_entry, kernel_low, kernel_high;
61
62
63 memset(cpus, 0, sizeof(cpus));
64 for (i = 0; i < smp_cpus; ++i) {
65 cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
66 }
67
68 cpus[0]->env.trap_arg0 = ram_size;
69 cpus[0]->env.trap_arg1 = 0;
70 cpus[0]->env.trap_arg2 = smp_cpus;
71
72
73 pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
74 clipper_pci_map_irq);
75
76
77 rtc_init(isa_bus, 1900, rtc_irq);
78
79 pit_init(isa_bus, 0x40, 0, NULL);
80 isa_create_simple(isa_bus, "i8042");
81
82
83 pci_vga_init(pci_bus);
84
85
86 serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
87
88
89 for (i = 0; i < nb_nics; i++) {
90 pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL);
91 }
92
93
94 {
95 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
96 ide_drive_get(hd, ARRAY_SIZE(hd));
97
98 pci_cmd646_ide_init(pci_bus, hd, 0);
99 }
100
101
102
103
104 palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
105 bios_name ? bios_name : "palcode-clipper");
106 if (palcode_filename == NULL) {
107 hw_error("no palcode provided\n");
108 exit(1);
109 }
110 size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
111 NULL, &palcode_entry, &palcode_low, &palcode_high,
112 0, EM_ALPHA, 0);
113 if (size < 0) {
114 hw_error("could not load palcode '%s'\n", palcode_filename);
115 exit(1);
116 }
117 g_free(palcode_filename);
118
119
120 for (i = 0; i < smp_cpus; ++i) {
121 cpus[i]->env.pal_mode = 1;
122 cpus[i]->env.pc = palcode_entry;
123 cpus[i]->env.palbr = palcode_entry;
124 }
125
126
127 if (kernel_filename) {
128 uint64_t param_offset;
129
130 size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
131 NULL, &kernel_entry, &kernel_low, &kernel_high,
132 0, EM_ALPHA, 0);
133 if (size < 0) {
134 hw_error("could not load kernel '%s'\n", kernel_filename);
135 exit(1);
136 }
137
138 cpus[0]->env.trap_arg1 = kernel_entry;
139
140 param_offset = kernel_low - 0x6000;
141
142 if (kernel_cmdline) {
143 pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
144 }
145
146 if (initrd_filename) {
147 long initrd_base, initrd_size;
148
149 initrd_size = get_image_size(initrd_filename);
150 if (initrd_size < 0) {
151 hw_error("could not load initial ram disk '%s'\n",
152 initrd_filename);
153 exit(1);
154 }
155
156
157 initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
158 load_image_targphys(initrd_filename, initrd_base,
159 ram_size - initrd_base);
160
161 address_space_stq(&address_space_memory, param_offset + 0x100,
162 initrd_base + 0xfffffc0000000000ULL,
163 MEMTXATTRS_UNSPECIFIED,
164 NULL);
165 address_space_stq(&address_space_memory, param_offset + 0x108,
166 initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
167 }
168 }
169}
170
171static QEMUMachine clipper_machine = {
172 .name = "clipper",
173 .desc = "Alpha DP264/CLIPPER",
174 .init = clipper_init,
175 .max_cpus = 4,
176 .is_default = 1,
177};
178
179static void clipper_machine_init(void)
180{
181 qemu_register_machine(&clipper_machine);
182}
183
184machine_init(clipper_machine_init);
185