root / hw / alpha_dp264.c @ a1bc20df
History | View | Annotate | Download (5.3 kB)
1 |
/*
|
---|---|
2 |
* QEMU Alpha DP264/CLIPPER hardware system emulator.
|
3 |
*
|
4 |
* Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
|
5 |
* variants because CLIPPER doesn't have an SMC669 SuperIO controller
|
6 |
* that we need to emulate as well.
|
7 |
*/
|
8 |
|
9 |
#include "hw.h" |
10 |
#include "elf.h" |
11 |
#include "loader.h" |
12 |
#include "boards.h" |
13 |
#include "alpha_sys.h" |
14 |
#include "sysemu.h" |
15 |
#include "mc146818rtc.h" |
16 |
#include "ide.h" |
17 |
#include "i8254.h" |
18 |
#include "serial.h" |
19 |
|
20 |
#define MAX_IDE_BUS 2 |
21 |
|
22 |
static 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 |
/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
|
31 |
(0) The dev_irq_n lines into the cpu, which we totally ignore,
|
32 |
(1) The DRIR lines in the typhoon chipset,
|
33 |
(2) The "vector" aka mangled interrupt number reported by SRM PALcode,
|
34 |
(3) The interrupt number assigned by the kernel.
|
35 |
The following function is concerned with (1) only. */
|
36 |
|
37 |
static 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 |
|
46 |
static void clipper_init(QEMUMachineInitArgs *args) |
47 |
{ |
48 |
ram_addr_t ram_size = args->ram_size; |
49 |
const char *cpu_model = args->cpu_model; |
50 |
const char *kernel_filename = args->kernel_filename; |
51 |
const char *kernel_cmdline = args->kernel_cmdline; |
52 |
const char *initrd_filename = args->initrd_filename; |
53 |
CPUAlphaState *cpus[4];
|
54 |
PCIBus *pci_bus; |
55 |
ISABus *isa_bus; |
56 |
qemu_irq rtc_irq; |
57 |
long size, i;
|
58 |
const char *palcode_filename; |
59 |
uint64_t palcode_entry, palcode_low, palcode_high; |
60 |
uint64_t kernel_entry, kernel_low, kernel_high; |
61 |
|
62 |
/* Create up to 4 cpus. */
|
63 |
memset(cpus, 0, sizeof(cpus)); |
64 |
for (i = 0; i < smp_cpus; ++i) { |
65 |
cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
|
66 |
} |
67 |
|
68 |
cpus[0]->trap_arg0 = ram_size;
|
69 |
cpus[0]->trap_arg1 = 0; |
70 |
cpus[0]->trap_arg2 = smp_cpus;
|
71 |
|
72 |
/* Init the chipset. */
|
73 |
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, |
74 |
clipper_pci_map_irq); |
75 |
|
76 |
rtc_init(isa_bus, 1980, rtc_irq);
|
77 |
pit_init(isa_bus, 0x40, 0, NULL); |
78 |
isa_create_simple(isa_bus, "i8042");
|
79 |
|
80 |
/* VGA setup. Don't bother loading the bios. */
|
81 |
pci_vga_init(pci_bus); |
82 |
|
83 |
/* Serial code setup. */
|
84 |
for (i = 0; i < MAX_SERIAL_PORTS; ++i) { |
85 |
if (serial_hds[i]) {
|
86 |
serial_isa_init(isa_bus, i, serial_hds[i]); |
87 |
} |
88 |
} |
89 |
|
90 |
/* Network setup. e1000 is good enough, failing Tulip support. */
|
91 |
for (i = 0; i < nb_nics; i++) { |
92 |
pci_nic_init_nofail(&nd_table[i], "e1000", NULL); |
93 |
} |
94 |
|
95 |
/* IDE disk setup. */
|
96 |
{ |
97 |
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
98 |
ide_drive_get(hd, MAX_IDE_BUS); |
99 |
|
100 |
pci_cmd646_ide_init(pci_bus, hd, 0);
|
101 |
} |
102 |
|
103 |
/* Load PALcode. Given that this is not "real" cpu palcode,
|
104 |
but one explicitly written for the emulation, we might as
|
105 |
well load it directly from and ELF image. */
|
106 |
palcode_filename = (bios_name ? bios_name : "palcode-clipper");
|
107 |
palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename); |
108 |
if (palcode_filename == NULL) { |
109 |
hw_error("no palcode provided\n");
|
110 |
exit(1);
|
111 |
} |
112 |
size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, |
113 |
NULL, &palcode_entry, &palcode_low, &palcode_high,
|
114 |
0, EM_ALPHA, 0); |
115 |
if (size < 0) { |
116 |
hw_error("could not load palcode '%s'\n", palcode_filename);
|
117 |
exit(1);
|
118 |
} |
119 |
|
120 |
/* Start all cpus at the PALcode RESET entry point. */
|
121 |
for (i = 0; i < smp_cpus; ++i) { |
122 |
cpus[i]->pal_mode = 1;
|
123 |
cpus[i]->pc = palcode_entry; |
124 |
cpus[i]->palbr = palcode_entry; |
125 |
} |
126 |
|
127 |
/* Load a kernel. */
|
128 |
if (kernel_filename) {
|
129 |
uint64_t param_offset; |
130 |
|
131 |
size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, |
132 |
NULL, &kernel_entry, &kernel_low, &kernel_high,
|
133 |
0, EM_ALPHA, 0); |
134 |
if (size < 0) { |
135 |
hw_error("could not load kernel '%s'\n", kernel_filename);
|
136 |
exit(1);
|
137 |
} |
138 |
|
139 |
cpus[0]->trap_arg1 = kernel_entry;
|
140 |
|
141 |
param_offset = kernel_low - 0x6000;
|
142 |
|
143 |
if (kernel_cmdline) {
|
144 |
pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); |
145 |
} |
146 |
|
147 |
if (initrd_filename) {
|
148 |
long initrd_base, initrd_size;
|
149 |
|
150 |
initrd_size = get_image_size(initrd_filename); |
151 |
if (initrd_size < 0) { |
152 |
hw_error("could not load initial ram disk '%s'\n",
|
153 |
initrd_filename); |
154 |
exit(1);
|
155 |
} |
156 |
|
157 |
/* Put the initrd image as high in memory as possible. */
|
158 |
initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; |
159 |
load_image_targphys(initrd_filename, initrd_base, |
160 |
ram_size - initrd_base); |
161 |
|
162 |
stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL); |
163 |
stq_phys(param_offset + 0x108, initrd_size);
|
164 |
} |
165 |
} |
166 |
} |
167 |
|
168 |
static QEMUMachine clipper_machine = {
|
169 |
.name = "clipper",
|
170 |
.desc = "Alpha DP264/CLIPPER",
|
171 |
.init = clipper_init, |
172 |
.max_cpus = 4,
|
173 |
.is_default = 1,
|
174 |
}; |
175 |
|
176 |
static void clipper_machine_init(void) |
177 |
{ |
178 |
qemu_register_machine(&clipper_machine); |
179 |
} |
180 |
|
181 |
machine_init(clipper_machine_init); |