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
71
72
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 )
{
}
extern int nographic ;
73
74
static int sun4u_NVRAM_set_params ( m48t59_t * nvram , uint16_t NVRAM_size ,
const unsigned char * arch ,
75
76
ram_addr_t RAM_size ,
const char * boot_devices ,
77
78
79
80
81
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 )
82
{
83
84
unsigned int i ;
uint32_t start , end ;
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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
strcpy ( header -> struct_ident , "QEMU_BIOS" );
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 ));
strcpy ( header -> arch , arch );
header -> nb_cpus = smp_cpus & 0xff ;
header -> RAM0_base = 0 ;
header -> RAM0_size = cpu_to_be64 (( uint64_t ) RAM_size );
strcpy ( header -> boot_devices , boot_devices );
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 );
107
if ( cmdline ) {
108
pstrcpy_targphys ( CMDLINE_ADDR , TARGET_PAGE_SIZE , cmdline );
109
110
header -> cmdline = cpu_to_be64 (( uint64_t ) CMDLINE_ADDR );
header -> cmdline_size = cpu_to_be64 (( uint64_t ) strlen ( cmdline ));
111
}
112
113
114
115
116
117
118
119
120
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 );
121
122
123
124
125
126
127
128
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 );
129
130
131
// OpenBIOS nvram variables
// Variable partition
132
133
134
part_header = ( struct OpenBIOS_nvpart_v1 * ) & image [ start ];
part_header -> signature = OPENBIOS_PART_SYSTEM ;
strcpy ( part_header -> name , "system" );
135
136
end = start + sizeof ( struct OpenBIOS_nvpart_v1 );
137
for ( i = 0 ; i < nb_prom_envs ; i ++ )
138
139
140
141
end = OpenBIOS_set_var ( image , end , prom_envs [ i ]);
// End marker
image [ end ++ ] = '\0' ;
142
143
end = start + (( end - start + 15 ) & ~ 15 );
144
OpenBIOS_finish_partition ( part_header , end - start );
145
146
147
// free partition
start = end ;
148
149
150
part_header = ( struct OpenBIOS_nvpart_v1 * ) & image [ start ];
part_header -> signature = OPENBIOS_PART_FREE ;
strcpy ( part_header -> name , "free" );
151
152
end = 0x1fd0 ;
153
154
155
156
OpenBIOS_finish_partition ( part_header , end - start );
for ( i = 0 ; i < sizeof ( image ); i ++ )
m48t59_write ( nvram , i , image [ i ]);
157
158
return 0 ;
159
160
}
161
void pic_info ( void )
162
163
164
{
}
165
void irq_info ( void )
166
167
168
{
}
169
void qemu_system_powerdown ( void )
170
171
172
{
}
173
174
175
static void main_cpu_reset ( void * opaque )
{
CPUState * env = opaque ;
176
177
cpu_reset ( env );
178
179
180
181
182
183
184
185
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 );
}
186
static void tick_irq ( void * opaque )
187
188
189
190
191
192
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
}
193
static void stick_irq ( void * opaque )
194
195
196
197
198
199
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
}
200
static void hstick_irq ( void * opaque )
201
202
203
204
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
205
206
}
207
208
209
210
static void dummy_cpu_set_irq ( void * opaque , int irq , int level )
{
}
211
212
213
static const int ide_iobase [ 2 ] = { 0x1f0 , 0x170 };
static const int ide_iobase2 [ 2 ] = { 0x3f6 , 0x376 };
static const int ide_irq [ 2 ] = { 14 , 15 };
214
215
216
217
218
219
220
221
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 ;
222
223
/* Sun4u hardware initialisation */
224
static void sun4u_init ( ram_addr_t RAM_size , int vga_ram_size ,
225
226
227
const char * boot_devices , DisplayState * ds ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model )
228
{
229
CPUState * env ;
230
char buf [ 1024 ];
231
m48t59_t * nvram ;
232
233
int ret , linux_boot ;
unsigned int i ;
234
235
long prom_offset , initrd_size , kernel_size ;
PCIBus * pci_bus ;
236
QEMUBH * bh ;
237
qemu_irq * irq ;
238
int drive_index ;
ths
authored
17 years ago
239
240
BlockDriverState * hd [ MAX_IDE_BUS * MAX_IDE_DEVS ];
BlockDriverState * fd [ MAX_FD ];
241
242
243
linux_boot = ( kernel_filename != NULL );
244
245
246
/* init CPUs */
if ( cpu_model == NULL )
cpu_model = "TI UltraSparc II" ;
247
248
env = cpu_init ( cpu_model );
if ( ! env ) {
249
250
251
fprintf ( stderr , "Unable to find Sparc CPU definition \n " );
exit ( 1 );
}
252
253
254
255
256
257
258
259
260
261
262
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 );
263
264
register_savevm ( "cpu" , 0 , 3 , cpu_save , cpu_load , env );
qemu_register_reset ( main_cpu_reset , env );
265
main_cpu_reset ( env );
266
267
/* allocate RAM */
268
cpu_register_physical_memory ( 0 , RAM_size , 0 );
269
270
prom_offset = RAM_size + vga_ram_size ;
ths
authored
18 years ago
271
cpu_register_physical_memory ( PROM_ADDR ,
272
273
( PROM_SIZE_MAX + TARGET_PAGE_SIZE ) &
TARGET_PAGE_MASK ,
274
prom_offset | IO_MEM_ROM );
275
276
277
278
if ( bios_name == NULL )
bios_name = PROM_FILENAME ;
snprintf ( buf , sizeof ( buf ), "%s/%s" , bios_dir , bios_name );
279
ret = load_elf ( buf , PROM_ADDR - PROM_VADDR , NULL , NULL , NULL );
280
if ( ret < 0 ) {
281
282
283
fprintf ( stderr , "qemu: could not load prom '%s' \n " ,
buf );
exit ( 1 );
284
285
286
}
kernel_size = 0 ;
287
initrd_size = 0 ;
288
if ( linux_boot ) {
289
/* XXX: put correct offset */
ths
authored
18 years ago
290
kernel_size = load_elf ( kernel_filename , 0 , NULL , NULL , NULL );
291
if ( kernel_size < 0 )
292
293
kernel_size = load_aout ( kernel_filename , KERNEL_LOAD_ADDR ,
ram_size - KERNEL_LOAD_ADDR );
294
if ( kernel_size < 0 )
295
296
297
kernel_size = load_image_targphys ( kernel_filename ,
KERNEL_LOAD_ADDR ,
ram_size - KERNEL_LOAD_ADDR );
298
if ( kernel_size < 0 ) {
ths
authored
18 years ago
299
fprintf ( stderr , "qemu: could not load kernel '%s' \n " ,
300
kernel_filename );
301
exit ( 1 );
302
303
304
305
}
/* load initrd */
if ( initrd_filename ) {
306
307
308
initrd_size = load_image_targphys ( initrd_filename ,
INITRD_LOAD_ADDR ,
ram_size - INITRD_LOAD_ADDR );
309
if ( initrd_size < 0 ) {
ths
authored
18 years ago
310
fprintf ( stderr , "qemu: could not load initial ram disk '%s' \n " ,
311
312
313
314
315
initrd_filename );
exit ( 1 );
}
}
if ( initrd_size > 0 ) {
316
for ( i = 0 ; i < 64 * TARGET_PAGE_SIZE ; i += TARGET_PAGE_SIZE ) {
317
318
319
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 );
320
321
322
break ;
}
}
323
324
}
}
325
pci_bus = pci_apb_init ( APB_SPECIAL_BASE , APB_MEM_BASE , NULL );
326
isa_mem_base = VGA_BASE ;
327
328
pci_cirrus_vga_init ( pci_bus , ds , phys_ram_base + RAM_size , RAM_size ,
vga_ram_size );
329
330
331
for ( i = 0 ; i < MAX_SERIAL_PORTS ; i ++ ) {
if ( serial_hds [ i ]) {
332
333
serial_init ( serial_io [ i ], NULL /*serial_irq[i]*/ , 115200 ,
serial_hds [ i ]);
334
335
336
337
338
}
}
for ( i = 0 ; i < MAX_PARALLEL_PORTS ; i ++ ) {
if ( parallel_hds [ i ]) {
339
340
parallel_init ( parallel_io [ i ], NULL /*parallel_irq[i]*/ ,
parallel_hds [ i ]);
341
342
343
344
}
}
for ( i = 0 ; i < nb_nics ; i ++ ) {
345
346
if ( ! nd_table [ i ]. model )
nd_table [ i ]. model = "ne2k_pci" ;
347
pci_nic_init ( pci_bus , & nd_table [ i ], - 1 );
348
349
}
350
irq = qemu_allocate_irqs ( dummy_cpu_set_irq , NULL , 32 );
ths
authored
17 years ago
351
352
353
354
355
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 ++ ) {
356
357
358
359
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
360
361
362
363
364
365
else
hd [ i ] = NULL ;
}
// XXX pci_cmd646_ide_init ( pci_bus , hd , 1 );
pci_piix3_ide_init ( pci_bus , hd , - 1 , irq );
366
367
/* FIXME: wire up interrupts. */
i8042_init ( NULL /*1*/ , NULL /*12*/ , 0x60 );
ths
authored
17 years ago
368
for ( i = 0 ; i < MAX_FD ; i ++ ) {
369
370
371
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
372
373
374
375
else
fd [ i ] = NULL ;
}
floppy_controller = fdctrl_init ( NULL /*6*/ , 2 , 0 , 0x3f0 , fd );
376
nvram = m48t59_init ( NULL /*8*/ , 0 , 0x0074 , NVRAM_SIZE , 59 );
377
sun4u_NVRAM_set_params ( nvram , NVRAM_SIZE , "Sun4u" , RAM_size , boot_devices ,
378
379
380
381
382
383
384
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 );
385
386
387
388
389
390
}
QEMUMachine sun4u_machine = {
"sun4u" ,
"Sun4u platform" ,
sun4u_init ,
391
PROM_SIZE_MAX + VGA_RAM_SIZE ,
392
};