1
2
/*
* QEMU Sun4u System Emulator
ths
authored
18 years ago
3
*
4
* Copyright ( c ) 2005 Fabrice Bellard
ths
authored
18 years ago
5
*
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the "Software" ), to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
24
25
26
27
28
29
30
31
32
# include "hw.h"
# include "pci.h"
# include "pc.h"
# include "nvram.h"
# include "fdc.h"
# include "net.h"
# include "qemu-timer.h"
# include "sysemu.h"
# include "boards.h"
33
# include "firmware_abi.h"
34
35
36
37
# define KERNEL_LOAD_ADDR 0x00404000
# define CMDLINE_ADDR 0x003ff000
# define INITRD_LOAD_ADDR 0x00300000
38
# define PROM_SIZE_MAX ( 4 * 1024 * 1024 )
39
40
# define PROM_ADDR 0x1fff0000000ULL
# define PROM_VADDR 0x000ffd00000ULL
41
# define APB_SPECIAL_BASE 0x1fe00000000ULL
42
43
44
# define APB_MEM_BASE 0x1ff00000000ULL
# define VGA_BASE ( APB_MEM_BASE + 0x400000ULL )
# define PROM_FILENAME "openbios-sparc64"
45
# define NVRAM_SIZE 0x2000
ths
authored
17 years ago
46
# define MAX_IDE_BUS 2
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
int DMA_get_channel_mode ( int nchan )
{
return 0 ;
}
int DMA_read_memory ( int nchan , void * buf , int pos , int size )
{
return 0 ;
}
int DMA_write_memory ( int nchan , void * buf , int pos , int size )
{
return 0 ;
}
void DMA_hold_DREQ ( int nchan ) {}
void DMA_release_DREQ ( int nchan ) {}
void DMA_schedule ( int nchan ) {}
void DMA_run ( void ) {}
void DMA_init ( int high_page_enable ) {}
void DMA_register_channel ( int nchan ,
DMA_transfer_handler transfer_handler ,
void * opaque )
{
}
71
72
73
74
75
76
77
78
79
80
static int nvram_boot_set ( void * opaque , const char * boot_device )
{
unsigned int i ;
uint8_t image [ sizeof ( ohwcfg_v3_t )];
ohwcfg_v3_t * header = ( ohwcfg_v3_t * ) & image ;
m48t59_t * nvram = ( m48t59_t * ) opaque ;
for ( i = 0 ; i < sizeof ( image ); i ++ )
image [ i ] = m48t59_read ( nvram , i ) & 0xff ;
81
strcpy (( char * ) header -> boot_devices , boot_device );
82
83
84
85
86
87
88
89
90
header -> nboot_devices = strlen ( boot_device ) & 0xff ;
header -> crc = cpu_to_be16 ( OHW_compute_crc ( header , 0x00 , 0xF8 ));
for ( i = 0 ; i < sizeof ( image ); i ++ )
m48t59_write ( nvram , i , image [ i ]);
return 0 ;
}
91
92
extern int nographic ;
93
static int sun4u_NVRAM_set_params ( m48t59_t * nvram , uint16_t NVRAM_size ,
94
const char * arch ,
95
96
ram_addr_t RAM_size ,
const char * boot_devices ,
97
98
99
100
101
uint32_t kernel_image , uint32_t kernel_size ,
const char * cmdline ,
uint32_t initrd_image , uint32_t initrd_size ,
uint32_t NVRAM_image ,
int width , int height , int depth )
102
{
103
104
unsigned int i ;
uint32_t start , end ;
105
106
107
108
109
110
111
112
uint8_t image [ 0x1ff0 ];
ohwcfg_v3_t * header = ( ohwcfg_v3_t * ) & image ;
struct sparc_arch_cfg * sparc_header ;
struct OpenBIOS_nvpart_v1 * part_header ;
memset ( image , '\0' , sizeof ( image ));
// Try to match PPC NVRAM
113
strcpy (( char * ) header -> struct_ident , "QEMU_BIOS" );
114
115
116
117
118
header -> struct_version = cpu_to_be32 ( 3 ); /* structure v3 */
header -> nvram_size = cpu_to_be16 ( NVRAM_size );
header -> nvram_arch_ptr = cpu_to_be16 ( sizeof ( ohwcfg_v3_t ));
header -> nvram_arch_size = cpu_to_be16 ( sizeof ( struct sparc_arch_cfg ));
119
strcpy (( char * ) header -> arch , arch );
120
121
122
header -> nb_cpus = smp_cpus & 0xff ;
header -> RAM0_base = 0 ;
header -> RAM0_size = cpu_to_be64 (( uint64_t ) RAM_size );
123
strcpy (( char * ) header -> boot_devices , boot_devices );
124
125
126
header -> nboot_devices = strlen ( boot_devices ) & 0xff ;
header -> kernel_image = cpu_to_be64 (( uint64_t ) kernel_image );
header -> kernel_size = cpu_to_be64 (( uint64_t ) kernel_size );
127
if ( cmdline ) {
128
pstrcpy_targphys ( CMDLINE_ADDR , TARGET_PAGE_SIZE , cmdline );
129
130
header -> cmdline = cpu_to_be64 (( uint64_t ) CMDLINE_ADDR );
header -> cmdline_size = cpu_to_be64 (( uint64_t ) strlen ( cmdline ));
131
}
132
133
134
135
136
137
138
139
140
header -> initrd_image = cpu_to_be64 (( uint64_t ) initrd_image );
header -> initrd_size = cpu_to_be64 (( uint64_t ) initrd_size );
header -> NVRAM_image = cpu_to_be64 (( uint64_t ) NVRAM_image );
header -> width = cpu_to_be16 ( width );
header -> height = cpu_to_be16 ( height );
header -> depth = cpu_to_be16 ( depth );
if ( nographic )
header -> graphic_flags = cpu_to_be16 ( OHW_GF_NOGRAPHICS );
141
142
143
144
145
146
147
148
header -> crc = cpu_to_be16 ( OHW_compute_crc ( header , 0x00 , 0xF8 ));
// Architecture specific header
start = sizeof ( ohwcfg_v3_t );
sparc_header = ( struct sparc_arch_cfg * ) & image [ start ];
sparc_header -> valid = 0 ;
start += sizeof ( struct sparc_arch_cfg );
149
150
151
// OpenBIOS nvram variables
// Variable partition
152
153
154
part_header = ( struct OpenBIOS_nvpart_v1 * ) & image [ start ];
part_header -> signature = OPENBIOS_PART_SYSTEM ;
strcpy ( part_header -> name , "system" );
155
156
end = start + sizeof ( struct OpenBIOS_nvpart_v1 );
157
for ( i = 0 ; i < nb_prom_envs ; i ++ )
158
159
160
161
end = OpenBIOS_set_var ( image , end , prom_envs [ i ]);
// End marker
image [ end ++ ] = '\0' ;
162
163
end = start + (( end - start + 15 ) & ~ 15 );
164
OpenBIOS_finish_partition ( part_header , end - start );
165
166
167
// free partition
start = end ;
168
169
170
part_header = ( struct OpenBIOS_nvpart_v1 * ) & image [ start ];
part_header -> signature = OPENBIOS_PART_FREE ;
strcpy ( part_header -> name , "free" );
171
172
end = 0x1fd0 ;
173
174
175
176
OpenBIOS_finish_partition ( part_header , end - start );
for ( i = 0 ; i < sizeof ( image ); i ++ )
m48t59_write ( nvram , i , image [ i ]);
177
178
179
qemu_register_boot_set ( nvram_boot_set , nvram );
180
return 0 ;
181
182
}
183
void pic_info ( void )
184
185
186
{
}
187
void irq_info ( void )
188
189
190
{
}
191
void qemu_system_powerdown ( void )
192
193
194
{
}
195
196
197
static void main_cpu_reset ( void * opaque )
{
CPUState * env = opaque ;
198
199
cpu_reset ( env );
200
201
202
203
204
205
206
207
ptimer_set_limit ( env -> tick , 0x7fffffffffffffffULL , 1 );
ptimer_run ( env -> tick , 0 );
ptimer_set_limit ( env -> stick , 0x7fffffffffffffffULL , 1 );
ptimer_run ( env -> stick , 0 );
ptimer_set_limit ( env -> hstick , 0x7fffffffffffffffULL , 1 );
ptimer_run ( env -> hstick , 0 );
}
208
static void tick_irq ( void * opaque )
209
210
211
212
213
214
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
}
215
static void stick_irq ( void * opaque )
216
217
218
219
220
221
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
}
222
static void hstick_irq ( void * opaque )
223
224
225
226
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
227
228
}
229
230
231
232
static void dummy_cpu_set_irq ( void * opaque , int irq , int level )
{
}
233
234
235
static const int ide_iobase [ 2 ] = { 0x1f0 , 0x170 };
static const int ide_iobase2 [ 2 ] = { 0x3f6 , 0x376 };
static const int ide_irq [ 2 ] = { 14 , 15 };
236
237
238
239
240
241
242
243
static const int serial_io [ MAX_SERIAL_PORTS ] = { 0x3f8 , 0x2f8 , 0x3e8 , 0x2e8 };
static const int serial_irq [ MAX_SERIAL_PORTS ] = { 4 , 3 , 4 , 3 };
static const int parallel_io [ MAX_PARALLEL_PORTS ] = { 0x378 , 0x278 , 0x3bc };
static const int parallel_irq [ MAX_PARALLEL_PORTS ] = { 7 , 7 , 7 };
static fdctrl_t * floppy_controller ;
244
245
/* Sun4u hardware initialisation */
246
static void sun4u_init ( ram_addr_t RAM_size , int vga_ram_size ,
247
248
249
const char * boot_devices , DisplayState * ds ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model )
250
{
251
CPUState * env ;
252
char buf [ 1024 ];
253
m48t59_t * nvram ;
254
255
int ret , linux_boot ;
unsigned int i ;
256
257
long prom_offset , initrd_size , kernel_size ;
PCIBus * pci_bus ;
258
QEMUBH * bh ;
259
qemu_irq * irq ;
260
int drive_index ;
ths
authored
17 years ago
261
262
BlockDriverState * hd [ MAX_IDE_BUS * MAX_IDE_DEVS ];
BlockDriverState * fd [ MAX_FD ];
263
264
265
linux_boot = ( kernel_filename != NULL );
266
267
268
/* init CPUs */
if ( cpu_model == NULL )
cpu_model = "TI UltraSparc II" ;
269
270
env = cpu_init ( cpu_model );
if ( ! env ) {
271
272
273
fprintf ( stderr , "Unable to find Sparc CPU definition \n " );
exit ( 1 );
}
274
275
276
277
278
279
280
281
282
283
284
bh = qemu_bh_new ( tick_irq , env );
env -> tick = ptimer_init ( bh );
ptimer_set_period ( env -> tick , 1ULL );
bh = qemu_bh_new ( stick_irq , env );
env -> stick = ptimer_init ( bh );
ptimer_set_period ( env -> stick , 1ULL );
bh = qemu_bh_new ( hstick_irq , env );
env -> hstick = ptimer_init ( bh );
ptimer_set_period ( env -> hstick , 1ULL );
285
register_savevm ( "cpu" , 0 , 4 , cpu_save , cpu_load , env );
286
qemu_register_reset ( main_cpu_reset , env );
287
main_cpu_reset ( env );
288
289
/* allocate RAM */
290
cpu_register_physical_memory ( 0 , RAM_size , 0 );
291
292
prom_offset = RAM_size + vga_ram_size ;
ths
authored
18 years ago
293
cpu_register_physical_memory ( PROM_ADDR ,
294
295
( PROM_SIZE_MAX + TARGET_PAGE_SIZE ) &
TARGET_PAGE_MASK ,
296
prom_offset | IO_MEM_ROM );
297
298
299
300
if ( bios_name == NULL )
bios_name = PROM_FILENAME ;
snprintf ( buf , sizeof ( buf ), "%s/%s" , bios_dir , bios_name );
301
ret = load_elf ( buf , PROM_ADDR - PROM_VADDR , NULL , NULL , NULL );
302
if ( ret < 0 ) {
303
304
305
fprintf ( stderr , "qemu: could not load prom '%s' \n " ,
buf );
exit ( 1 );
306
307
308
}
kernel_size = 0 ;
309
initrd_size = 0 ;
310
if ( linux_boot ) {
311
/* XXX: put correct offset */
ths
authored
18 years ago
312
kernel_size = load_elf ( kernel_filename , 0 , NULL , NULL , NULL );
313
if ( kernel_size < 0 )
314
315
kernel_size = load_aout ( kernel_filename , KERNEL_LOAD_ADDR ,
ram_size - KERNEL_LOAD_ADDR );
316
if ( kernel_size < 0 )
317
318
319
kernel_size = load_image_targphys ( kernel_filename ,
KERNEL_LOAD_ADDR ,
ram_size - KERNEL_LOAD_ADDR );
320
if ( kernel_size < 0 ) {
ths
authored
18 years ago
321
fprintf ( stderr , "qemu: could not load kernel '%s' \n " ,
322
kernel_filename );
323
exit ( 1 );
324
325
326
327
}
/* load initrd */
if ( initrd_filename ) {
328
329
330
initrd_size = load_image_targphys ( initrd_filename ,
INITRD_LOAD_ADDR ,
ram_size - INITRD_LOAD_ADDR );
331
if ( initrd_size < 0 ) {
ths
authored
18 years ago
332
fprintf ( stderr , "qemu: could not load initial ram disk '%s' \n " ,
333
334
335
336
337
initrd_filename );
exit ( 1 );
}
}
if ( initrd_size > 0 ) {
338
for ( i = 0 ; i < 64 * TARGET_PAGE_SIZE ; i += TARGET_PAGE_SIZE ) {
339
340
341
if ( ldl_phys ( KERNEL_LOAD_ADDR + i ) == 0x48647253 ) { // HdrS
stl_phys ( KERNEL_LOAD_ADDR + i + 16 , INITRD_LOAD_ADDR );
stl_phys ( KERNEL_LOAD_ADDR + i + 20 , initrd_size );
342
343
344
break ;
}
}
345
346
}
}
347
pci_bus = pci_apb_init ( APB_SPECIAL_BASE , APB_MEM_BASE , NULL );
348
isa_mem_base = VGA_BASE ;
349
350
pci_cirrus_vga_init ( pci_bus , ds , phys_ram_base + RAM_size , RAM_size ,
vga_ram_size );
351
352
353
for ( i = 0 ; i < MAX_SERIAL_PORTS ; i ++ ) {
if ( serial_hds [ i ]) {
354
355
serial_init ( serial_io [ i ], NULL /*serial_irq[i]*/ , 115200 ,
serial_hds [ i ]);
356
357
358
359
360
}
}
for ( i = 0 ; i < MAX_PARALLEL_PORTS ; i ++ ) {
if ( parallel_hds [ i ]) {
361
362
parallel_init ( parallel_io [ i ], NULL /*parallel_irq[i]*/ ,
parallel_hds [ i ]);
363
364
365
366
}
}
for ( i = 0 ; i < nb_nics ; i ++ ) {
367
368
if ( ! nd_table [ i ]. model )
nd_table [ i ]. model = "ne2k_pci" ;
369
pci_nic_init ( pci_bus , & nd_table [ i ], - 1 );
370
371
}
372
irq = qemu_allocate_irqs ( dummy_cpu_set_irq , NULL , 32 );
ths
authored
17 years ago
373
374
375
376
377
if ( drive_get_max_bus ( IF_IDE ) >= MAX_IDE_BUS ) {
fprintf ( stderr , "qemu: too many IDE bus \n " );
exit ( 1 );
}
for ( i = 0 ; i < MAX_IDE_BUS * MAX_IDE_DEVS ; i ++ ) {
378
379
380
381
drive_index = drive_get_index ( IF_IDE , i / MAX_IDE_DEVS ,
i % MAX_IDE_DEVS );
if ( drive_index != - 1 )
hd [ i ] = drives_table [ drive_index ]. bdrv ;
ths
authored
17 years ago
382
383
384
385
386
387
else
hd [ i ] = NULL ;
}
// XXX pci_cmd646_ide_init ( pci_bus , hd , 1 );
pci_piix3_ide_init ( pci_bus , hd , - 1 , irq );
388
389
/* FIXME: wire up interrupts. */
i8042_init ( NULL /*1*/ , NULL /*12*/ , 0x60 );
ths
authored
17 years ago
390
for ( i = 0 ; i < MAX_FD ; i ++ ) {
391
392
393
drive_index = drive_get_index ( IF_FLOPPY , 0 , i );
if ( drive_index != - 1 )
fd [ i ] = drives_table [ drive_index ]. bdrv ;
ths
authored
17 years ago
394
395
396
397
else
fd [ i ] = NULL ;
}
floppy_controller = fdctrl_init ( NULL /*6*/ , 2 , 0 , 0x3f0 , fd );
398
nvram = m48t59_init ( NULL /*8*/ , 0 , 0x0074 , NVRAM_SIZE , 59 );
399
sun4u_NVRAM_set_params ( nvram , NVRAM_SIZE , "Sun4u" , RAM_size , boot_devices ,
400
401
402
403
404
405
406
KERNEL_LOAD_ADDR , kernel_size ,
kernel_cmdline ,
INITRD_LOAD_ADDR , initrd_size ,
/* XXX: need an option to load a NVRAM image */
0 ,
graphic_width , graphic_height , graphic_depth );
407
408
409
410
411
412
}
QEMUMachine sun4u_machine = {
"sun4u" ,
"Sun4u platform" ,
sun4u_init ,
413
PROM_SIZE_MAX + VGA_RAM_SIZE ,
414
};