root / hw / alpha_dp264.c @ b1277b03
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 |
|
19 |
#define MAX_IDE_BUS 2 |
20 |
|
21 |
static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) |
22 |
{ |
23 |
if (((addr >> 41) & 3) == 2) { |
24 |
addr &= 0xffffffffffull;
|
25 |
} |
26 |
return addr;
|
27 |
} |
28 |
|
29 |
/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
|
30 |
(0) The dev_irq_n lines into the cpu, which we totally ignore,
|
31 |
(1) The DRIR lines in the typhoon chipset,
|
32 |
(2) The "vector" aka mangled interrupt number reported by SRM PALcode,
|
33 |
(3) The interrupt number assigned by the kernel.
|
34 |
The following function is concerned with (1) only. */
|
35 |
|
36 |
static int clipper_pci_map_irq(PCIDevice *d, int irq_num) |
37 |
{ |
38 |
int slot = d->devfn >> 3; |
39 |
|
40 |
assert(irq_num >= 0 && irq_num <= 3); |
41 |
|
42 |
return (slot + 1) * 4 + irq_num; |
43 |
} |
44 |
|
45 |
static void clipper_init(ram_addr_t ram_size, |
46 |
const char *boot_device, |
47 |
const char *kernel_filename, |
48 |
const char *kernel_cmdline, |
49 |
const char *initrd_filename, |
50 |
const char *cpu_model) |
51 |
{ |
52 |
CPUState *cpus[4];
|
53 |
PCIBus *pci_bus; |
54 |
ISABus *isa_bus; |
55 |
qemu_irq rtc_irq; |
56 |
long size, i;
|
57 |
const char *palcode_filename; |
58 |
uint64_t palcode_entry, palcode_low, palcode_high; |
59 |
uint64_t kernel_entry, kernel_low, kernel_high; |
60 |
|
61 |
/* Create up to 4 cpus. */
|
62 |
memset(cpus, 0, sizeof(cpus)); |
63 |
for (i = 0; i < smp_cpus; ++i) { |
64 |
cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
|
65 |
} |
66 |
|
67 |
cpus[0]->trap_arg0 = ram_size;
|
68 |
cpus[0]->trap_arg1 = 0; |
69 |
cpus[0]->trap_arg2 = smp_cpus;
|
70 |
|
71 |
/* Init the chipset. */
|
72 |
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, |
73 |
clipper_pci_map_irq); |
74 |
|
75 |
rtc_init(isa_bus, 1980, rtc_irq);
|
76 |
pit_init(isa_bus, 0x40, 0); |
77 |
isa_create_simple(isa_bus, "i8042");
|
78 |
|
79 |
/* VGA setup. Don't bother loading the bios. */
|
80 |
alpha_pci_vga_setup(pci_bus); |
81 |
|
82 |
/* Serial code setup. */
|
83 |
for (i = 0; i < MAX_SERIAL_PORTS; ++i) { |
84 |
if (serial_hds[i]) {
|
85 |
serial_isa_init(isa_bus, i, serial_hds[i]); |
86 |
} |
87 |
} |
88 |
|
89 |
/* Network setup. e1000 is good enough, failing Tulip support. */
|
90 |
for (i = 0; i < nb_nics; i++) { |
91 |
pci_nic_init_nofail(&nd_table[i], "e1000", NULL); |
92 |
} |
93 |
|
94 |
/* IDE disk setup. */
|
95 |
{ |
96 |
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
97 |
ide_drive_get(hd, MAX_IDE_BUS); |
98 |
|
99 |
pci_cmd646_ide_init(pci_bus, hd, 0);
|
100 |
} |
101 |
|
102 |
/* Load PALcode. Given that this is not "real" cpu palcode,
|
103 |
but one explicitly written for the emulation, we might as
|
104 |
well load it directly from and ELF image. */
|
105 |
palcode_filename = (bios_name ? bios_name : "palcode-clipper");
|
106 |
palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename); |
107 |
if (palcode_filename == NULL) { |
108 |
hw_error("no palcode provided\n");
|
109 |
exit(1);
|
110 |
} |
111 |
size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, |
112 |
NULL, &palcode_entry, &palcode_low, &palcode_high,
|
113 |
0, EM_ALPHA, 0); |
114 |
if (size < 0) { |
115 |
hw_error("could not load palcode '%s'\n", palcode_filename);
|
116 |
exit(1);
|
117 |
} |
118 |
|
119 |
/* Start all cpus at the PALcode RESET entry point. */
|
120 |
for (i = 0; i < smp_cpus; ++i) { |
121 |
cpus[i]->pal_mode = 1;
|
122 |
cpus[i]->pc = palcode_entry; |
123 |
cpus[i]->palbr = palcode_entry; |
124 |
} |
125 |
|
126 |
/* Load a kernel. */
|
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]->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 |
/* Put the initrd image as high in memory as possible. */
|
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 |
stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL); |
162 |
stq_phys(param_offset + 0x108, initrd_size);
|
163 |
} |
164 |
} |
165 |
} |
166 |
|
167 |
static QEMUMachine clipper_machine = {
|
168 |
.name = "clipper",
|
169 |
.desc = "Alpha DP264/CLIPPER",
|
170 |
.init = clipper_init, |
171 |
.max_cpus = 4,
|
172 |
.is_default = 1,
|
173 |
}; |
174 |
|
175 |
static void clipper_machine_init(void) |
176 |
{ |
177 |
qemu_register_machine(&clipper_machine); |
178 |
} |
179 |
|
180 |
machine_init(clipper_machine_init); |