root / hw / alpha_dp264.c @ 80bb2ff7
History | View | Annotate | Download (5.2 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 controler
|
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 |
qemu_irq rtc_irq; |
54 |
long size, i;
|
55 |
const char *palcode_filename; |
56 |
uint64_t palcode_entry, palcode_low, palcode_high; |
57 |
uint64_t kernel_entry, kernel_low, kernel_high; |
58 |
|
59 |
/* Create up to 4 cpus. */
|
60 |
memset(cpus, 0, sizeof(cpus)); |
61 |
for (i = 0; i < smp_cpus; ++i) { |
62 |
cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
|
63 |
} |
64 |
|
65 |
cpus[0]->trap_arg0 = ram_size;
|
66 |
cpus[0]->trap_arg1 = 0; |
67 |
cpus[0]->trap_arg2 = smp_cpus;
|
68 |
|
69 |
/* Init the chipset. */
|
70 |
pci_bus = typhoon_init(ram_size, &rtc_irq, cpus, clipper_pci_map_irq); |
71 |
|
72 |
rtc_init(1980, rtc_irq);
|
73 |
pit_init(0x40, 0); |
74 |
isa_create_simple("i8042");
|
75 |
|
76 |
/* VGA setup. Don't bother loading the bios. */
|
77 |
alpha_pci_vga_setup(pci_bus); |
78 |
|
79 |
/* Serial code setup. */
|
80 |
for (i = 0; i < MAX_SERIAL_PORTS; ++i) { |
81 |
if (serial_hds[i]) {
|
82 |
serial_isa_init(i, serial_hds[i]); |
83 |
} |
84 |
} |
85 |
|
86 |
/* Network setup. e1000 is good enough, failing Tulip support. */
|
87 |
for (i = 0; i < nb_nics; i++) { |
88 |
pci_nic_init_nofail(&nd_table[i], "e1000", NULL); |
89 |
} |
90 |
|
91 |
/* IDE disk setup. */
|
92 |
{ |
93 |
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
94 |
ide_drive_get(hd, MAX_IDE_BUS); |
95 |
|
96 |
pci_cmd646_ide_init(pci_bus, hd, 0);
|
97 |
} |
98 |
|
99 |
/* Load PALcode. Given that this is not "real" cpu palcode,
|
100 |
but one explicitly written for the emulation, we might as
|
101 |
well load it directly from and ELF image. */
|
102 |
palcode_filename = (bios_name ? bios_name : "palcode-clipper");
|
103 |
palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename); |
104 |
if (palcode_filename == NULL) { |
105 |
hw_error("no palcode provided\n");
|
106 |
exit(1);
|
107 |
} |
108 |
size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, |
109 |
NULL, &palcode_entry, &palcode_low, &palcode_high,
|
110 |
0, EM_ALPHA, 0); |
111 |
if (size < 0) { |
112 |
hw_error("could not load palcode '%s'\n", palcode_filename);
|
113 |
exit(1);
|
114 |
} |
115 |
|
116 |
/* Start all cpus at the PALcode RESET entry point. */
|
117 |
for (i = 0; i < smp_cpus; ++i) { |
118 |
cpus[i]->pal_mode = 1;
|
119 |
cpus[i]->pc = palcode_entry; |
120 |
cpus[i]->palbr = palcode_entry; |
121 |
} |
122 |
|
123 |
/* Load a kernel. */
|
124 |
if (kernel_filename) {
|
125 |
uint64_t param_offset; |
126 |
|
127 |
size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, |
128 |
NULL, &kernel_entry, &kernel_low, &kernel_high,
|
129 |
0, EM_ALPHA, 0); |
130 |
if (size < 0) { |
131 |
hw_error("could not load kernel '%s'\n", kernel_filename);
|
132 |
exit(1);
|
133 |
} |
134 |
|
135 |
cpus[0]->trap_arg1 = kernel_entry;
|
136 |
|
137 |
param_offset = kernel_low - 0x6000;
|
138 |
|
139 |
if (kernel_cmdline) {
|
140 |
pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); |
141 |
} |
142 |
|
143 |
if (initrd_filename) {
|
144 |
long initrd_base, initrd_size;
|
145 |
|
146 |
initrd_size = get_image_size(initrd_filename); |
147 |
if (initrd_size < 0) { |
148 |
hw_error("could not load initial ram disk '%s'\n",
|
149 |
initrd_filename); |
150 |
exit(1);
|
151 |
} |
152 |
|
153 |
/* Put the initrd image as high in memory as possible. */
|
154 |
initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; |
155 |
load_image_targphys(initrd_filename, initrd_base, |
156 |
ram_size - initrd_base); |
157 |
|
158 |
stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000UL); |
159 |
stq_phys(param_offset + 0x108, initrd_size);
|
160 |
} |
161 |
} |
162 |
} |
163 |
|
164 |
static QEMUMachine clipper_machine = {
|
165 |
.name = "clipper",
|
166 |
.desc = "Alpha DP264/CLIPPER",
|
167 |
.init = clipper_init, |
168 |
.max_cpus = 4,
|
169 |
.is_default = 1,
|
170 |
}; |
171 |
|
172 |
static void clipper_machine_init(void) |
173 |
{ |
174 |
qemu_register_machine(&clipper_machine); |
175 |
} |
176 |
|
177 |
machine_init(clipper_machine_init); |