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