Revision 83469015 hw/sun4u.c
b/hw/sun4u.c | ||
---|---|---|
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 | 24 |
#include "vl.h" |
25 |
#include "m48t08.h"
|
|
25 |
#include "m48t59.h"
|
|
26 | 26 |
|
27 |
#define KERNEL_LOAD_ADDR 0x00004000 |
|
28 |
#define CMDLINE_ADDR 0x007ff000 |
|
29 |
#define INITRD_LOAD_ADDR 0x00800000 |
|
30 |
#define PROM_ADDR 0xffd00000 |
|
27 |
#define KERNEL_LOAD_ADDR 0x00404000 |
|
28 |
#define CMDLINE_ADDR 0x003ff000 |
|
29 |
#define INITRD_LOAD_ADDR 0x00300000 |
|
30 |
#define PROM_ADDR 0x1fff0000000ULL |
|
31 |
#define APB_SPECIAL_BASE 0x1fe00000000ULL |
|
32 |
#define APB_MEM_BASE 0x1ff00000000ULL |
|
33 |
#define VGA_BASE (APB_MEM_BASE + 0x400000ULL) |
|
31 | 34 |
#define PROM_FILENAMEB "proll-sparc64.bin" |
32 | 35 |
#define PROM_FILENAMEE "proll-sparc64.elf" |
33 |
#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */ |
|
34 |
#define PHYS_JJ_IDPROM_OFF 0x1FD8 |
|
35 |
#define PHYS_JJ_EEPROM_SIZE 0x2000 |
|
36 |
// IRQs are not PIL ones, but master interrupt controller register |
|
37 |
// bits |
|
38 |
#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */ |
|
39 |
#define PHYS_JJ_MS_KBD_IRQ 14 |
|
40 |
#define PHYS_JJ_SER 0x71100000 /* Serial */ |
|
41 |
#define PHYS_JJ_SER_IRQ 15 |
|
36 |
#define NVRAM_SIZE 0x2000 |
|
42 | 37 |
|
43 | 38 |
/* TSC handling */ |
44 | 39 |
|
... | ... | |
70 | 65 |
{ |
71 | 66 |
} |
72 | 67 |
|
73 |
static void nvram_set_word (m48t08_t *nvram, uint32_t addr, uint16_t value) |
|
68 |
/* NVRAM helpers */ |
|
69 |
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value) |
|
74 | 70 |
{ |
75 |
m48t08_write(nvram, addr++, (value >> 8) & 0xff);
|
|
76 |
m48t08_write(nvram, addr++, value & 0xff);
|
|
71 |
m48t59_set_addr(nvram, addr);
|
|
72 |
m48t59_write(nvram, value);
|
|
77 | 73 |
} |
78 | 74 |
|
79 |
static void nvram_set_lword (m48t08_t *nvram, uint32_t addr, uint32_t value)
|
|
75 |
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
|
|
80 | 76 |
{ |
81 |
m48t08_write(nvram, addr++, value >> 24); |
|
82 |
m48t08_write(nvram, addr++, (value >> 16) & 0xff); |
|
83 |
m48t08_write(nvram, addr++, (value >> 8) & 0xff); |
|
84 |
m48t08_write(nvram, addr++, value & 0xff); |
|
77 |
m48t59_set_addr(nvram, addr); |
|
78 |
return m48t59_read(nvram); |
|
85 | 79 |
} |
86 | 80 |
|
87 |
static void nvram_set_string (m48t08_t *nvram, uint32_t addr, |
|
81 |
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value) |
|
82 |
{ |
|
83 |
m48t59_set_addr(nvram, addr); |
|
84 |
m48t59_write(nvram, value >> 8); |
|
85 |
m48t59_set_addr(nvram, addr + 1); |
|
86 |
m48t59_write(nvram, value & 0xFF); |
|
87 |
} |
|
88 |
|
|
89 |
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr) |
|
90 |
{ |
|
91 |
uint16_t tmp; |
|
92 |
|
|
93 |
m48t59_set_addr(nvram, addr); |
|
94 |
tmp = m48t59_read(nvram) << 8; |
|
95 |
m48t59_set_addr(nvram, addr + 1); |
|
96 |
tmp |= m48t59_read(nvram); |
|
97 |
|
|
98 |
return tmp; |
|
99 |
} |
|
100 |
|
|
101 |
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value) |
|
102 |
{ |
|
103 |
m48t59_set_addr(nvram, addr); |
|
104 |
m48t59_write(nvram, value >> 24); |
|
105 |
m48t59_set_addr(nvram, addr + 1); |
|
106 |
m48t59_write(nvram, (value >> 16) & 0xFF); |
|
107 |
m48t59_set_addr(nvram, addr + 2); |
|
108 |
m48t59_write(nvram, (value >> 8) & 0xFF); |
|
109 |
m48t59_set_addr(nvram, addr + 3); |
|
110 |
m48t59_write(nvram, value & 0xFF); |
|
111 |
} |
|
112 |
|
|
113 |
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr) |
|
114 |
{ |
|
115 |
uint32_t tmp; |
|
116 |
|
|
117 |
m48t59_set_addr(nvram, addr); |
|
118 |
tmp = m48t59_read(nvram) << 24; |
|
119 |
m48t59_set_addr(nvram, addr + 1); |
|
120 |
tmp |= m48t59_read(nvram) << 16; |
|
121 |
m48t59_set_addr(nvram, addr + 2); |
|
122 |
tmp |= m48t59_read(nvram) << 8; |
|
123 |
m48t59_set_addr(nvram, addr + 3); |
|
124 |
tmp |= m48t59_read(nvram); |
|
125 |
|
|
126 |
return tmp; |
|
127 |
} |
|
128 |
|
|
129 |
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr, |
|
88 | 130 |
const unsigned char *str, uint32_t max) |
89 | 131 |
{ |
90 |
unsigned int i;
|
|
132 |
int i; |
|
91 | 133 |
|
92 | 134 |
for (i = 0; i < max && str[i] != '\0'; i++) { |
93 |
m48t08_write(nvram, addr + i, str[i]); |
|
135 |
m48t59_set_addr(nvram, addr + i); |
|
136 |
m48t59_write(nvram, str[i]); |
|
94 | 137 |
} |
95 |
m48t08_write(nvram, addr + max - 1, '\0'); |
|
138 |
m48t59_set_addr(nvram, addr + max - 1); |
|
139 |
m48t59_write(nvram, '\0'); |
|
96 | 140 |
} |
97 | 141 |
|
98 |
static m48t08_t *nvram; |
|
142 |
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max) |
|
143 |
{ |
|
144 |
int i; |
|
145 |
|
|
146 |
memset(dst, 0, max); |
|
147 |
for (i = 0; i < max; i++) { |
|
148 |
dst[i] = NVRAM_get_byte(nvram, addr + i); |
|
149 |
if (dst[i] == '\0') |
|
150 |
break; |
|
151 |
} |
|
152 |
|
|
153 |
return i; |
|
154 |
} |
|
155 |
|
|
156 |
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value) |
|
157 |
{ |
|
158 |
uint16_t tmp; |
|
159 |
uint16_t pd, pd1, pd2; |
|
160 |
|
|
161 |
tmp = prev >> 8; |
|
162 |
pd = prev ^ value; |
|
163 |
pd1 = pd & 0x000F; |
|
164 |
pd2 = ((pd >> 4) & 0x000F) ^ pd1; |
|
165 |
tmp ^= (pd1 << 3) | (pd1 << 8); |
|
166 |
tmp ^= pd2 | (pd2 << 7) | (pd2 << 12); |
|
167 |
|
|
168 |
return tmp; |
|
169 |
} |
|
170 |
|
|
171 |
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count) |
|
172 |
{ |
|
173 |
uint32_t i; |
|
174 |
uint16_t crc = 0xFFFF; |
|
175 |
int odd; |
|
176 |
|
|
177 |
odd = count & 1; |
|
178 |
count &= ~1; |
|
179 |
for (i = 0; i != count; i++) { |
|
180 |
crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i)); |
|
181 |
} |
|
182 |
if (odd) { |
|
183 |
crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8); |
|
184 |
} |
|
185 |
|
|
186 |
return crc; |
|
187 |
} |
|
99 | 188 |
|
100 | 189 |
extern int nographic; |
101 | 190 |
|
102 |
static void nvram_init(m48t08_t *nvram, uint8_t *macaddr, const char *cmdline, |
|
103 |
int boot_device, uint32_t RAM_size, |
|
104 |
uint32_t kernel_size, |
|
105 |
int width, int height, int depth) |
|
106 |
{ |
|
107 |
unsigned char tmp = 0; |
|
108 |
int i, j; |
|
109 |
|
|
110 |
// Try to match PPC NVRAM |
|
111 |
nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16); |
|
112 |
nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */ |
|
113 |
// NVRAM_size, arch not applicable |
|
114 |
m48t08_write(nvram, 0x2F, nographic & 0xff); |
|
115 |
nvram_set_lword(nvram, 0x30, RAM_size); |
|
116 |
m48t08_write(nvram, 0x34, boot_device & 0xff); |
|
117 |
nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR); |
|
118 |
nvram_set_lword(nvram, 0x3C, kernel_size); |
|
191 |
int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, |
|
192 |
const unsigned char *arch, |
|
193 |
uint32_t RAM_size, int boot_device, |
|
194 |
uint32_t kernel_image, uint32_t kernel_size, |
|
195 |
const char *cmdline, |
|
196 |
uint32_t initrd_image, uint32_t initrd_size, |
|
197 |
uint32_t NVRAM_image, |
|
198 |
int width, int height, int depth) |
|
199 |
{ |
|
200 |
uint16_t crc; |
|
201 |
|
|
202 |
/* Set parameters for Open Hack'Ware BIOS */ |
|
203 |
NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16); |
|
204 |
NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */ |
|
205 |
NVRAM_set_word(nvram, 0x14, NVRAM_size); |
|
206 |
NVRAM_set_string(nvram, 0x20, arch, 16); |
|
207 |
NVRAM_set_byte(nvram, 0x2f, nographic & 0xff); |
|
208 |
NVRAM_set_lword(nvram, 0x30, RAM_size); |
|
209 |
NVRAM_set_byte(nvram, 0x34, boot_device); |
|
210 |
NVRAM_set_lword(nvram, 0x38, kernel_image); |
|
211 |
NVRAM_set_lword(nvram, 0x3C, kernel_size); |
|
119 | 212 |
if (cmdline) { |
120 |
strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); |
|
121 |
nvram_set_lword(nvram, 0x40, CMDLINE_ADDR); |
|
122 |
nvram_set_lword(nvram, 0x44, strlen(cmdline)); |
|
213 |
/* XXX: put the cmdline in NVRAM too ? */ |
|
214 |
strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); |
|
215 |
NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR); |
|
216 |
NVRAM_set_lword(nvram, 0x44, strlen(cmdline)); |
|
217 |
} else { |
|
218 |
NVRAM_set_lword(nvram, 0x40, 0); |
|
219 |
NVRAM_set_lword(nvram, 0x44, 0); |
|
123 | 220 |
} |
124 |
// initrd_image, initrd_size passed differently |
|
125 |
nvram_set_word(nvram, 0x54, width); |
|
126 |
nvram_set_word(nvram, 0x56, height); |
|
127 |
nvram_set_word(nvram, 0x58, depth); |
|
128 |
|
|
129 |
// Sun4m specific use |
|
130 |
i = 0x1fd8; |
|
131 |
m48t08_write(nvram, i++, 0x01); |
|
132 |
m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */ |
|
133 |
j = 0; |
|
134 |
m48t08_write(nvram, i++, macaddr[j++]); |
|
135 |
m48t08_write(nvram, i++, macaddr[j++]); |
|
136 |
m48t08_write(nvram, i++, macaddr[j++]); |
|
137 |
m48t08_write(nvram, i++, macaddr[j++]); |
|
138 |
m48t08_write(nvram, i++, macaddr[j++]); |
|
139 |
m48t08_write(nvram, i, macaddr[j]); |
|
140 |
|
|
141 |
/* Calculate checksum */ |
|
142 |
for (i = 0x1fd8; i < 0x1fe7; i++) { |
|
143 |
tmp ^= m48t08_read(nvram, i); |
|
144 |
} |
|
145 |
m48t08_write(nvram, 0x1fe7, tmp); |
|
221 |
NVRAM_set_lword(nvram, 0x48, initrd_image); |
|
222 |
NVRAM_set_lword(nvram, 0x4C, initrd_size); |
|
223 |
NVRAM_set_lword(nvram, 0x50, NVRAM_image); |
|
224 |
|
|
225 |
NVRAM_set_word(nvram, 0x54, width); |
|
226 |
NVRAM_set_word(nvram, 0x56, height); |
|
227 |
NVRAM_set_word(nvram, 0x58, depth); |
|
228 |
crc = NVRAM_compute_crc(nvram, 0x00, 0xF8); |
|
229 |
NVRAM_set_word(nvram, 0xFC, crc); |
|
230 |
|
|
231 |
return 0; |
|
146 | 232 |
} |
147 | 233 |
|
148 | 234 |
void pic_info() |
... | ... | |
157 | 243 |
{ |
158 | 244 |
} |
159 | 245 |
|
160 |
void vga_update_display()
|
|
246 |
void pic_set_irq_new(void *opaque, int irq, int level)
|
|
161 | 247 |
{ |
162 | 248 |
} |
163 | 249 |
|
164 |
void vga_invalidate_display()
|
|
250 |
void qemu_system_powerdown(void)
|
|
165 | 251 |
{ |
166 | 252 |
} |
167 | 253 |
|
168 |
void vga_screen_dump(const char *filename)
|
|
169 |
{
|
|
170 |
}
|
|
254 |
static const int ide_iobase[2] = { 0x1f0, 0x170 };
|
|
255 |
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
|
|
256 |
static const int ide_irq[2] = { 14, 15 };
|
|
171 | 257 |
|
172 |
void qemu_system_powerdown(void) |
|
173 |
{ |
|
174 |
} |
|
258 |
static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; |
|
259 |
static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; |
|
260 |
|
|
261 |
static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; |
|
262 |
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; |
|
263 |
|
|
264 |
static fdctrl_t *floppy_controller; |
|
175 | 265 |
|
176 | 266 |
/* Sun4u hardware initialisation */ |
177 | 267 |
static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, |
... | ... | |
180 | 270 |
const char *initrd_filename) |
181 | 271 |
{ |
182 | 272 |
char buf[1024]; |
273 |
m48t59_t *nvram; |
|
183 | 274 |
int ret, linux_boot; |
184 | 275 |
unsigned int i; |
185 |
long vram_size = 0x100000, prom_offset, initrd_size, kernel_size; |
|
276 |
long prom_offset, initrd_size, kernel_size; |
|
277 |
PCIBus *pci_bus; |
|
186 | 278 |
|
187 | 279 |
linux_boot = (kernel_filename != NULL); |
188 | 280 |
|
189 | 281 |
/* allocate RAM */ |
190 | 282 |
cpu_register_physical_memory(0, ram_size, 0); |
191 | 283 |
|
192 |
nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE); |
|
193 |
// Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device |
|
194 |
// Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device |
|
195 |
slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]); |
|
196 |
|
|
197 |
prom_offset = ram_size + vram_size; |
|
284 |
prom_offset = ram_size + vga_ram_size; |
|
198 | 285 |
|
199 | 286 |
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE); |
200 | 287 |
ret = load_elf(buf, phys_ram_base + prom_offset); |
... | ... | |
211 | 298 |
prom_offset | IO_MEM_ROM); |
212 | 299 |
|
213 | 300 |
kernel_size = 0; |
301 |
initrd_size = 0; |
|
214 | 302 |
if (linux_boot) { |
215 | 303 |
kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); |
216 | 304 |
if (kernel_size < 0) |
... | ... | |
224 | 312 |
} |
225 | 313 |
|
226 | 314 |
/* load initrd */ |
227 |
initrd_size = 0; |
|
228 | 315 |
if (initrd_filename) { |
229 | 316 |
initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); |
230 | 317 |
if (initrd_size < 0) { |
... | ... | |
244 | 331 |
} |
245 | 332 |
} |
246 | 333 |
} |
247 |
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth); |
|
334 |
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE); |
|
335 |
isa_mem_base = VGA_BASE; |
|
336 |
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, |
|
337 |
vga_ram_size, 0, 0); |
|
338 |
cpu_register_physical_memory(VGA_BASE, vga_ram_size, ram_size); |
|
339 |
//pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size); |
|
340 |
|
|
341 |
for(i = 0; i < MAX_SERIAL_PORTS; i++) { |
|
342 |
if (serial_hds[i]) { |
|
343 |
serial_init(serial_io[i], serial_irq[i], serial_hds[i]); |
|
344 |
} |
|
345 |
} |
|
346 |
|
|
347 |
for(i = 0; i < MAX_PARALLEL_PORTS; i++) { |
|
348 |
if (parallel_hds[i]) { |
|
349 |
parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]); |
|
350 |
} |
|
351 |
} |
|
352 |
|
|
353 |
for(i = 0; i < nb_nics; i++) { |
|
354 |
pci_ne2000_init(pci_bus, &nd_table[i]); |
|
355 |
} |
|
356 |
|
|
357 |
pci_cmd646_ide_init(pci_bus, bs_table, 1); |
|
358 |
kbd_init(); |
|
359 |
floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); |
|
360 |
nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE); |
|
361 |
sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device, |
|
362 |
KERNEL_LOAD_ADDR, kernel_size, |
|
363 |
kernel_cmdline, |
|
364 |
INITRD_LOAD_ADDR, initrd_size, |
|
365 |
/* XXX: need an option to load a NVRAM image */ |
|
366 |
0, |
|
367 |
graphic_width, graphic_height, graphic_depth); |
|
368 |
|
|
248 | 369 |
} |
249 | 370 |
|
250 | 371 |
QEMUMachine sun4u_machine = { |
Also available in: Unified diff