1
2
/*
* QEMU Sun4m System Emulator
ths
authored
18 years ago
3
*
4
* Copyright ( c ) 2003 - 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
24
* 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 .
*/
# include "vl.h"
25
// # define DEBUG_IRQ
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
* Sun4m architecture was used in the following machines :
*
* SPARCserver 6 xxMP / xx
* SPARCclassic ( SPARCclassic Server )( SPARCstation LC ) ( 4 / 15 ), SPARCclassic X ( 4 / 10 )
* SPARCstation LX / ZX ( 4 / 30 )
* SPARCstation Voyager
* SPARCstation 10 / xx , SPARCserver 10 / xx
* SPARCstation 5 , SPARCserver 5
* SPARCstation 20 / xx , SPARCserver 20
* SPARCstation 4
*
* See for example : http :// www . sunhelp . org / faq / sunref1 . html
*/
42
43
44
45
46
47
48
# ifdef DEBUG_IRQ
# define DPRINTF ( fmt , args ...) \
do { printf ( "CPUIRQ: " fmt , ## args ); } while ( 0 )
# else
# define DPRINTF ( fmt , args ...)
# endif
49
# define KERNEL_LOAD_ADDR 0x00004000
50
# define CMDLINE_ADDR 0x007ff000
51
# define INITRD_LOAD_ADDR 0x00800000
52
# define PROM_SIZE_MAX ( 512 * 1024 )
53
54
# define PROM_PADDR 0xff0000000ULL
# define PROM_VADDR 0xffd00000
55
# define PROM_FILENAME "openbios-sparc32"
56
57
# define MAX_CPUS 16
58
# define MAX_PILS 16
59
60
struct hwdef {
61
62
63
64
65
target_phys_addr_t iommu_base , slavio_base ;
target_phys_addr_t intctl_base , counter_base , nvram_base , ms_kb_base ;
target_phys_addr_t serial_base , fd_base ;
target_phys_addr_t dma_base , esp_base , le_base ;
target_phys_addr_t tcx_base , cs_base , power_base ;
66
67
68
long vram_size , nvram_size ;
// IRQ numbers are not PIL ones , but master interrupt controller register
// bit numbers
69
int intctl_g_intr , esp_irq , le_irq , clock_irq , clock1_irq ;
70
71
int ser_irq , ms_kb_irq , fd_irq , me_irq , cs_irq ;
int machine_id ; // For NVRAM
72
uint32_t intbit_to_level [ 32 ];
73
74
};
75
76
77
78
79
80
81
/* TSC handling */
uint64_t cpu_get_tsc ()
{
return qemu_get_clock ( vm_clock );
}
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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 )
{
}
105
static void nvram_set_word ( m48t59_t * nvram , uint32_t addr , uint16_t value )
106
{
107
108
m48t59_write ( nvram , addr ++ , ( value >> 8 ) & 0xff );
m48t59_write ( nvram , addr ++ , value & 0xff );
109
110
}
111
static void nvram_set_lword ( m48t59_t * nvram , uint32_t addr , uint32_t value )
112
{
113
114
115
116
m48t59_write ( nvram , addr ++ , value >> 24 );
m48t59_write ( nvram , addr ++ , ( value >> 16 ) & 0xff );
m48t59_write ( nvram , addr ++ , ( value >> 8 ) & 0xff );
m48t59_write ( nvram , addr ++ , value & 0xff );
117
118
}
119
static void nvram_set_string ( m48t59_t * nvram , uint32_t addr ,
120
121
122
123
124
const unsigned char * str , uint32_t max )
{
unsigned int i ;
for ( i = 0 ; i < max && str [ i ] != '\0' ; i ++ ) {
125
m48t59_write ( nvram , addr + i , str [ i ]);
126
}
127
m48t59_write ( nvram , addr + max - 1 , '\0' );
128
}
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
static uint32_t nvram_set_var ( m48t59_t * nvram , uint32_t addr ,
const unsigned char * str )
{
uint32_t len ;
len = strlen ( str ) + 1 ;
nvram_set_string ( nvram , addr , str , len );
return addr + len ;
}
static void nvram_finish_partition ( m48t59_t * nvram , uint32_t start ,
uint32_t end )
{
unsigned int i , sum ;
// Length divided by 16
m48t59_write ( nvram , start + 2 , (( end - start ) >> 12 ) & 0xff );
m48t59_write ( nvram , start + 3 , (( end - start ) >> 4 ) & 0xff );
// Checksum
sum = m48t59_read ( nvram , start );
for ( i = 0 ; i < 14 ; i ++ ) {
sum += m48t59_read ( nvram , start + 2 + i );
sum = ( sum + (( sum & 0xff00 ) >> 8 )) & 0xff ;
}
m48t59_write ( nvram , start + 1 , sum & 0xff );
}
158
159
extern int nographic ;
160
static void nvram_init ( m48t59_t * nvram , uint8_t * macaddr , const char * cmdline ,
161
162
163
int boot_device , uint32_t RAM_size ,
uint32_t kernel_size ,
int width , int height , int depth ,
164
int machine_id )
165
166
{
unsigned char tmp = 0 ;
167
168
unsigned int i , j ;
uint32_t start , end ;
169
170
171
172
173
// Try to match PPC NVRAM
nvram_set_string ( nvram , 0x00 , "QEMU_BIOS" , 16 );
nvram_set_lword ( nvram , 0x10 , 0x00000001 ); /* structure v1 */
// NVRAM_size , arch not applicable
174
175
m48t59_write ( nvram , 0x2D , smp_cpus & 0xff );
m48t59_write ( nvram , 0x2E , 0 );
176
m48t59_write ( nvram , 0x2F , nographic & 0xff );
177
nvram_set_lword ( nvram , 0x30 , RAM_size );
178
m48t59_write ( nvram , 0x34 , boot_device & 0xff );
179
180
nvram_set_lword ( nvram , 0x38 , KERNEL_LOAD_ADDR );
nvram_set_lword ( nvram , 0x3C , kernel_size );
181
if ( cmdline ) {
182
183
strcpy ( phys_ram_base + CMDLINE_ADDR , cmdline );
nvram_set_lword ( nvram , 0x40 , CMDLINE_ADDR );
184
nvram_set_lword ( nvram , 0x44 , strlen ( cmdline ));
185
}
186
187
188
189
// initrd_image , initrd_size passed differently
nvram_set_word ( nvram , 0x54 , width );
nvram_set_word ( nvram , 0x56 , height );
nvram_set_word ( nvram , 0x58 , depth );
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// OpenBIOS nvram variables
// Variable partition
start = 252 ;
m48t59_write ( nvram , start , 0x70 );
nvram_set_string ( nvram , start + 4 , "system" , 12 );
end = start + 16 ;
for ( i = 0 ; i < nb_prom_envs ; i ++ )
end = nvram_set_var ( nvram , end , prom_envs [ i ]);
m48t59_write ( nvram , end ++ , 0 );
end = start + (( end - start + 15 ) & ~ 15 );
nvram_finish_partition ( nvram , start , end );
// free partition
start = end ;
m48t59_write ( nvram , start , 0x7f );
nvram_set_string ( nvram , start + 4 , "free" , 12 );
end = 0x1fd0 ;
nvram_finish_partition ( nvram , start , end );
213
// Sun4m specific use
214
start = i = 0x1fd8 ;
215
m48t59_write ( nvram , i ++ , 0x01 );
216
m48t59_write ( nvram , i ++ , machine_id );
217
j = 0 ;
218
219
220
221
222
223
m48t59_write ( nvram , i ++ , macaddr [ j ++ ]);
m48t59_write ( nvram , i ++ , macaddr [ j ++ ]);
m48t59_write ( nvram , i ++ , macaddr [ j ++ ]);
m48t59_write ( nvram , i ++ , macaddr [ j ++ ]);
m48t59_write ( nvram , i ++ , macaddr [ j ++ ]);
m48t59_write ( nvram , i , macaddr [ j ]);
224
225
/* Calculate checksum */
226
227
for ( i = start ; i < start + 15 ; i ++ ) {
tmp ^= m48t59_read ( nvram , i );
228
}
229
m48t59_write ( nvram , start + 15 , tmp );
230
231
232
233
234
235
236
237
238
239
240
241
242
243
}
static void * slavio_intctl ;
void pic_info ()
{
slavio_pic_info ( slavio_intctl );
}
void irq_info ()
{
slavio_irq_info ( slavio_intctl );
}
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
void cpu_check_irqs ( CPUState * env )
{
if ( env -> pil_in && ( env -> interrupt_index == 0 ||
( env -> interrupt_index & ~ 15 ) == TT_EXTINT )) {
unsigned int i ;
for ( i = 15 ; i > 0 ; i -- ) {
if ( env -> pil_in & ( 1 << i )) {
int old_interrupt = env -> interrupt_index ;
env -> interrupt_index = TT_EXTINT | i ;
if ( old_interrupt != env -> interrupt_index )
cpu_interrupt ( env , CPU_INTERRUPT_HARD );
break ;
}
}
} else if ( ! env -> pil_in && ( env -> interrupt_index & ~ 15 ) == TT_EXTINT ) {
env -> interrupt_index = 0 ;
cpu_reset_interrupt ( env , CPU_INTERRUPT_HARD );
}
}
266
267
268
269
270
271
272
static void cpu_set_irq ( void * opaque , int irq , int level )
{
CPUState * env = opaque ;
if ( level ) {
DPRINTF ( "Raise CPU IRQ %d \n " , irq );
env -> halted = 0 ;
273
274
env -> pil_in |= 1 << irq ;
cpu_check_irqs ( env );
275
276
} else {
DPRINTF ( "Lower CPU IRQ %d \n " , irq );
277
278
env -> pil_in &= ~ ( 1 << irq );
cpu_check_irqs ( env );
279
280
281
282
283
284
285
}
}
static void dummy_cpu_set_irq ( void * opaque , int irq , int level )
{
}
286
287
288
289
290
291
292
static void * slavio_misc ;
void qemu_system_powerdown ( void )
{
slavio_set_power_fail ( slavio_misc , 1 );
}
293
294
295
static void main_cpu_reset ( void * opaque )
{
CPUState * env = opaque ;
296
297
298
299
300
301
302
303
304
cpu_reset ( env );
env -> halted = 0 ;
}
static void secondary_cpu_reset ( void * opaque )
{
CPUState * env = opaque ;
305
cpu_reset ( env );
306
env -> halted = 1 ;
307
308
}
309
310
static void * sun4m_hw_init ( const struct hwdef * hwdef , int RAM_size ,
DisplayState * ds , const char * cpu_model )
311
312
{
313
CPUState * env , * envs [ MAX_CPUS ];
314
unsigned int i ;
315
void * iommu , * espdma , * ledma , * main_esp , * nvram ;
316
const sparc_def_t * def ;
317
qemu_irq * cpu_irqs [ MAX_CPUS ], * slavio_irq , * slavio_cpu_irq ,
318
* espdma_irq , * ledma_irq ;
319
qemu_irq * esp_reset , * le_reset ;
320
321
/* init CPUs */
322
323
324
325
326
sparc_find_by_name ( cpu_model , & def );
if ( def == NULL ) {
fprintf ( stderr , "Unable to find Sparc CPU definition \n " );
exit ( 1 );
}
327
328
329
for ( i = 0 ; i < smp_cpus ; i ++ ) {
env = cpu_init ();
330
cpu_sparc_register ( env , def , i );
331
envs [ i ] = env ;
332
333
334
335
if ( i == 0 ) {
qemu_register_reset ( main_cpu_reset , env );
} else {
qemu_register_reset ( secondary_cpu_reset , env );
336
env -> halted = 1 ;
337
}
338
register_savevm ( "cpu" , i , 3 , cpu_save , cpu_load , env );
339
cpu_irqs [ i ] = qemu_allocate_irqs ( cpu_set_irq , envs [ i ], MAX_PILS );
340
}
341
342
343
344
for ( i = smp_cpus ; i < MAX_CPUS ; i ++ )
cpu_irqs [ i ] = qemu_allocate_irqs ( dummy_cpu_set_irq , NULL , MAX_PILS );
345
/* allocate RAM */
346
cpu_register_physical_memory ( 0 , RAM_size , 0 );
347
348
349
iommu = iommu_init ( hwdef -> iommu_base );
slavio_intctl = slavio_intctl_init ( hwdef -> intctl_base ,
350
hwdef -> intctl_base + 0x10000ULL ,
351
& hwdef -> intbit_to_level [ 0 ],
352
& slavio_irq , & slavio_cpu_irq ,
353
cpu_irqs ,
354
hwdef -> clock_irq );
355
356
espdma = sparc32_dma_init ( hwdef -> dma_base , slavio_irq [ hwdef -> esp_irq ],
357
358
iommu , & espdma_irq , & esp_reset );
359
ledma = sparc32_dma_init ( hwdef -> dma_base + 16ULL ,
360
361
slavio_irq [ hwdef -> le_irq ], iommu , & ledma_irq ,
& le_reset );
362
363
364
365
366
if ( graphic_depth != 8 && graphic_depth != 24 ) {
fprintf ( stderr , "qemu: Unsupported depth: %d \n " , graphic_depth );
exit ( 1 );
}
367
tcx_init ( ds , hwdef -> tcx_base , phys_ram_base + RAM_size , RAM_size ,
368
hwdef -> vram_size , graphic_width , graphic_height , graphic_depth );
369
370
371
if ( nd_table [ 0 ]. model == NULL
|| strcmp ( nd_table [ 0 ]. model , "lance" ) == 0 ) {
372
lance_init ( & nd_table [ 0 ], hwdef -> le_base , ledma , * ledma_irq , le_reset );
373
374
375
} else if ( strcmp ( nd_table [ 0 ]. model , "?" ) == 0 ) {
fprintf ( stderr , "qemu: Supported NICs: lance \n " );
exit ( 1 );
376
377
378
} else {
fprintf ( stderr , "qemu: Unsupported NIC: %s \n " , nd_table [ 0 ]. model );
exit ( 1 );
379
}
380
381
382
nvram = m48t59_init ( slavio_irq [ 0 ], hwdef -> nvram_base , 0 ,
hwdef -> nvram_size , 8 );
383
384
385
386
slavio_timer_init_all ( hwdef -> counter_base , slavio_irq [ hwdef -> clock1_irq ],
slavio_cpu_irq );
387
slavio_serial_ms_kbd_init ( hwdef -> ms_kb_base , slavio_irq [ hwdef -> ms_kb_irq ]);
388
389
// Slavio TTYA ( base + 4 , Linux ttyS0 ) is the first Qemu serial device
// Slavio TTYB ( base + 0 , Linux ttyS1 ) is the second Qemu serial device
390
391
392
slavio_serial_init ( hwdef -> serial_base , slavio_irq [ hwdef -> ser_irq ],
serial_hds [ 1 ], serial_hds [ 0 ]);
fdctrl_init ( slavio_irq [ hwdef -> fd_irq ], 0 , 1 , hwdef -> fd_base , fd_table );
393
394
395
main_esp = esp_init ( bs_table , hwdef -> esp_base , espdma , * espdma_irq ,
esp_reset );
ths
authored
18 years ago
396
397
398
399
400
401
402
for ( i = 0 ; i < MAX_DISKS ; i ++ ) {
if ( bs_table [ i ]) {
esp_scsi_attach ( main_esp , bs_table [ i ], i );
}
}
403
slavio_misc = slavio_misc_init ( hwdef -> slavio_base , hwdef -> power_base ,
404
slavio_irq [ hwdef -> me_irq ]);
405
if ( hwdef -> cs_base != ( target_phys_addr_t ) - 1 )
406
cs_init ( hwdef -> cs_base , hwdef -> cs_irq , slavio_intctl );
407
408
return nvram ;
409
410
}
411
static void sun4m_load_kernel ( long vram_size , int RAM_size , int boot_device ,
412
413
414
const char * kernel_filename ,
const char * kernel_cmdline ,
const char * initrd_filename ,
415
416
int machine_id ,
void * nvram )
417
418
419
420
421
422
423
{
int ret , linux_boot ;
char buf [ 1024 ];
unsigned int i ;
long prom_offset , initrd_size , kernel_size ;
linux_boot = ( kernel_filename != NULL );
424
425
prom_offset = RAM_size + vram_size ;
426
cpu_register_physical_memory ( PROM_PADDR ,
ths
authored
18 years ago
427
( PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1 ) & TARGET_PAGE_MASK ,
428
prom_offset | IO_MEM_ROM );
429
430
431
432
if ( bios_name == NULL )
bios_name = PROM_FILENAME ;
snprintf ( buf , sizeof ( buf ), "%s/%s" , bios_dir , bios_name );
433
ret = load_elf ( buf , PROM_PADDR - PROM_VADDR , NULL , NULL , NULL );
434
435
436
437
438
439
if ( ret < 0 || ret > PROM_SIZE_MAX )
ret = load_image ( buf , phys_ram_base + prom_offset );
if ( ret < 0 || ret > PROM_SIZE_MAX ) {
fprintf ( stderr , "qemu: could not load prom '%s' \n " ,
buf );
exit ( 1 );
440
441
}
442
kernel_size = 0 ;
443
if ( linux_boot ) {
444
445
kernel_size = load_elf ( kernel_filename , - 0xf0000000ULL , NULL , NULL ,
NULL );
446
if ( kernel_size < 0 )
447
448
449
kernel_size = load_aout ( kernel_filename , phys_ram_base + KERNEL_LOAD_ADDR );
if ( kernel_size < 0 )
kernel_size = load_image ( kernel_filename , phys_ram_base + KERNEL_LOAD_ADDR );
450
if ( kernel_size < 0 ) {
ths
authored
18 years ago
451
fprintf ( stderr , "qemu: could not load kernel '%s' \n " ,
452
kernel_filename );
453
exit ( 1 );
454
}
455
456
457
458
459
460
/* load initrd */
initrd_size = 0 ;
if ( initrd_filename ) {
initrd_size = load_image ( initrd_filename , phys_ram_base + INITRD_LOAD_ADDR );
if ( initrd_size < 0 ) {
ths
authored
18 years ago
461
fprintf ( stderr , "qemu: could not load initial ram disk '%s' \n " ,
462
463
464
465
466
initrd_filename );
exit ( 1 );
}
}
if ( initrd_size > 0 ) {
467
468
469
470
471
472
473
474
for ( i = 0 ; i < 64 * TARGET_PAGE_SIZE ; i += TARGET_PAGE_SIZE ) {
if ( ldl_raw ( phys_ram_base + KERNEL_LOAD_ADDR + i )
== 0x48647253 ) { // HdrS
stl_raw ( phys_ram_base + KERNEL_LOAD_ADDR + i + 16 , INITRD_LOAD_ADDR );
stl_raw ( phys_ram_base + KERNEL_LOAD_ADDR + i + 20 , initrd_size );
break ;
}
}
475
}
476
}
477
nvram_init ( nvram , ( uint8_t * ) & nd_table [ 0 ]. macaddr , kernel_cmdline ,
478
boot_device , RAM_size , kernel_size , graphic_width ,
479
480
481
482
483
484
485
486
487
graphic_height , graphic_depth , machine_id );
}
static const struct hwdef hwdefs [] = {
/* SS-5 */
{
. iommu_base = 0x10000000 ,
. tcx_base = 0x50000000 ,
. cs_base = 0x6c000000 ,
488
. slavio_base = 0x70000000 ,
489
490
491
492
493
494
495
496
497
. ms_kb_base = 0x71000000 ,
. serial_base = 0x71100000 ,
. nvram_base = 0x71200000 ,
. fd_base = 0x71400000 ,
. counter_base = 0x71d00000 ,
. intctl_base = 0x71e00000 ,
. dma_base = 0x78400000 ,
. esp_base = 0x78800000 ,
. le_base = 0x78c00000 ,
498
. power_base = 0x7a000000 ,
499
500
501
502
503
504
505
506
507
508
509
510
. vram_size = 0x00100000 ,
. nvram_size = 0x2000 ,
. esp_irq = 18 ,
. le_irq = 16 ,
. clock_irq = 7 ,
. clock1_irq = 19 ,
. ms_kb_irq = 14 ,
. ser_irq = 15 ,
. fd_irq = 22 ,
. me_irq = 30 ,
. cs_irq = 5 ,
. machine_id = 0x80 ,
511
. intbit_to_level = {
512
513
2 , 3 , 5 , 7 , 9 , 11 , 0 , 14 , 3 , 5 , 7 , 9 , 11 , 13 , 12 , 12 ,
6 , 0 , 4 , 10 , 8 , 0 , 11 , 0 , 0 , 0 , 0 , 0 , 15 , 0 , 15 , 0 ,
514
515
516
517
},
},
/* SS-10 */
{
518
519
. iommu_base = 0xfe0000000ULL ,
. tcx_base = 0xe20000000ULL ,
520
. cs_base = - 1 ,
521
522
523
524
525
526
527
528
529
530
531
. slavio_base = 0xff0000000ULL ,
. ms_kb_base = 0xff1000000ULL ,
. serial_base = 0xff1100000ULL ,
. nvram_base = 0xff1200000ULL ,
. fd_base = 0xff1700000ULL ,
. counter_base = 0xff1300000ULL ,
. intctl_base = 0xff1400000ULL ,
. dma_base = 0xef0400000ULL ,
. esp_base = 0xef0800000ULL ,
. le_base = 0xef0c00000ULL ,
. power_base = 0xefa000000ULL ,
532
533
534
535
536
537
538
539
540
541
. vram_size = 0x00100000 ,
. nvram_size = 0x2000 ,
. esp_irq = 18 ,
. le_irq = 16 ,
. clock_irq = 7 ,
. clock1_irq = 19 ,
. ms_kb_irq = 14 ,
. ser_irq = 15 ,
. fd_irq = 22 ,
. me_irq = 30 ,
542
543
. cs_irq = - 1 ,
. machine_id = 0x72 ,
544
. intbit_to_level = {
545
546
2 , 3 , 5 , 7 , 9 , 11 , 0 , 14 , 3 , 5 , 7 , 9 , 11 , 13 , 12 , 12 ,
6 , 0 , 4 , 10 , 8 , 0 , 11 , 0 , 0 , 0 , 0 , 0 , 15 , 0 , 15 , 0 ,
547
},
548
549
550
},
};
551
static void sun4m_common_init ( int RAM_size , int boot_device , DisplayState * ds ,
552
553
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model ,
554
unsigned int machine , int max_ram )
555
{
556
557
558
void * nvram ;
if (( unsigned int ) RAM_size > ( unsigned int ) max_ram ) {
559
fprintf ( stderr , "qemu: Too much memory for this machine: %d, maximum %d \n " ,
560
( unsigned int ) RAM_size / ( 1024 * 1024 ),
561
( unsigned int ) max_ram / ( 1024 * 1024 ));
562
563
exit ( 1 );
}
564
nvram = sun4m_hw_init ( & hwdefs [ machine ], RAM_size , ds , cpu_model );
565
566
sun4m_load_kernel ( hwdefs [ machine ]. vram_size , RAM_size , boot_device ,
567
kernel_filename , kernel_cmdline , initrd_filename ,
568
hwdefs [ machine ]. machine_id , nvram );
569
570
571
}
/* SPARCstation 5 hardware initialisation */
572
static void ss5_init ( int RAM_size , int vga_ram_size , int boot_device ,
573
574
575
576
577
578
DisplayState * ds , const char ** fd_filename , int snapshot ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model )
{
if ( cpu_model == NULL )
cpu_model = "Fujitsu MB86904" ;
579
sun4m_common_init ( RAM_size , boot_device , ds , kernel_filename ,
580
kernel_cmdline , initrd_filename , cpu_model ,
581
0 , 0x10000000 );
582
}
583
584
/* SPARCstation 10 hardware initialisation */
585
static void ss10_init ( int RAM_size , int vga_ram_size , int boot_device ,
586
587
588
589
590
591
DisplayState * ds , const char ** fd_filename , int snapshot ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model )
{
if ( cpu_model == NULL )
cpu_model = "TI SuperSparc II" ;
592
sun4m_common_init ( RAM_size , boot_device , ds , kernel_filename ,
593
kernel_cmdline , initrd_filename , cpu_model ,
594
1 , 0xffffffff ); // XXX actually first 62 GB ok
595
596
}
597
598
599
600
QEMUMachine ss5_machine = {
"SS-5" ,
"Sun4m platform, SPARCstation 5" ,
ss5_init ,
601
};
602
603
604
605
606
607
QEMUMachine ss10_machine = {
"SS-10" ,
"Sun4m platform, SPARCstation 10" ,
ss10_init ,
};