Statistics
| Branch: | Revision:

root / target-ppc / hw.c @ 9a64fbe4

History | View | Annotate | Download (24.8 kB)

1
/*
2
 * Hardware simulation for PPC target.
3
 * For now, this is only a 'minimal' collection of hacks needed to boot Linux.
4
 */
5

    
6
#include <stdlib.h>
7
#include <stdio.h>
8
#include <stdarg.h>
9
#include <string.h>
10
#include <ctype.h>
11
#include <unistd.h>
12
#include <fcntl.h>
13
#include <inttypes.h>
14
#include <unistd.h>
15
#include <time.h>
16

    
17
#include "cpu.h"
18
#include "vl.h"
19

    
20
//#define HARD_DEBUG_PPC_IO
21
#define DEBUG_PPC_IO
22

    
23
extern int loglevel;
24
extern FILE *logfile;
25

    
26
#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
27
#define DEBUG_PPC_IO
28
#endif
29

    
30
#if defined (HARD_DEBUG_PPC_IO)
31
#define PPC_IO_DPRINTF(fmt, args...)                     \
32
do {                                                     \
33
    if (loglevel > 0) {                                  \
34
        fprintf(logfile, "%s: " fmt, __func__ , ##args); \
35
    } else {                                             \
36
        printf("%s : " fmt, __func__ , ##args);          \
37
    }                                                    \
38
} while (0)
39
#elif defined (DEBUG_PPC_IO)
40
#define PPC_IO_DPRINTF(fmt, args...)                     \
41
do {                                                     \
42
    if (loglevel > 0) {                                  \
43
        fprintf(logfile, "%s: " fmt, __func__ , ##args); \
44
    }                                                    \
45
} while (0)
46
#else
47
#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
48
#endif
49

    
50
#if defined (USE_OPEN_FIRMWARE)
51
#include "of.h"
52
#else
53
#define NVRAM_SIZE 0x2000
54
#endif
55

    
56
/* IO ports emulation */
57
#define PPC_IO_BASE 0x80000000
58

    
59
static void PPC_io_writeb (uint32_t addr, uint32_t value)
60
{
61
    /* Don't polute serial port output */
62
    if ((addr < 0x800003F0 || addr > 0x80000400) &&
63
        (addr < 0x80000074 || addr > 0x80000077) &&
64
        (addr < 0x80000020 || addr > 0x80000021) &&
65
        (addr < 0x800000a0 || addr > 0x800000a1) &&
66
        (addr < 0x800001f0 || addr > 0x800001f7) &&
67
        (addr < 0x80000170 || addr > 0x80000177)) {
68
        PPC_IO_DPRINTF("0x%08x => 0x%02x\n", addr - PPC_IO_BASE, value);
69
    }
70
    cpu_outb(NULL, addr - PPC_IO_BASE, value);
71
}
72

    
73
static uint32_t PPC_io_readb (uint32_t addr)
74
{
75
    uint32_t ret = cpu_inb(NULL, addr - PPC_IO_BASE);
76

    
77
    if ((addr < 0x800003F0 || addr > 0x80000400) &&
78
        (addr < 0x80000074 || addr > 0x80000077) &&
79
        (addr < 0x80000020 || addr > 0x80000021) &&
80
        (addr < 0x800000a0 || addr > 0x800000a1) &&
81
        (addr < 0x800001f0 || addr > 0x800001f7) &&
82
        (addr < 0x80000170 || addr > 0x80000177) &&
83
        (addr < 0x8000060 || addr > 0x8000064)) {
84
//        PPC_IO_DPRINTF("0x%08x <= 0x%02x\n", addr - PPC_IO_BASE, ret);
85
    }
86

    
87
    return ret;
88
}
89

    
90
static void PPC_io_writew (uint32_t addr, uint32_t value)
91
{
92
    if ((addr < 0x800001f0 || addr > 0x800001f7) &&
93
        (addr < 0x80000170 || addr > 0x80000177)) {
94
        PPC_IO_DPRINTF("0x%08x => 0x%04x\n", addr - PPC_IO_BASE, value);
95
    }
96
    cpu_outw(NULL, addr - PPC_IO_BASE, value);
97
}
98

    
99
static uint32_t PPC_io_readw (uint32_t addr)
100
{
101
    uint32_t ret = cpu_inw(NULL, addr - PPC_IO_BASE);
102

    
103
    if ((addr < 0x800001f0 || addr > 0x800001f7) &&
104
        (addr < 0x80000170 || addr > 0x80000177)) {
105
        PPC_IO_DPRINTF("0x%08x <= 0x%04x\n", addr - PPC_IO_BASE, ret);
106
    }
107

    
108
    return ret;
109
}
110

    
111
static void PPC_io_writel (uint32_t addr, uint32_t value)
112
{
113
    PPC_IO_DPRINTF("0x%08x => 0x%08x\n", addr - PPC_IO_BASE, value);
114
    cpu_outl(NULL, addr - PPC_IO_BASE, value);
115
}
116

    
117
static uint32_t PPC_io_readl (uint32_t addr)
118
{
119
    uint32_t ret = cpu_inl(NULL, addr - PPC_IO_BASE);
120

    
121
    PPC_IO_DPRINTF("0x%08x <= 0x%08x\n", addr - PPC_IO_BASE, ret);
122

    
123
    return ret;
124
}
125

    
126
static CPUWriteMemoryFunc *PPC_io_write[] = {
127
    &PPC_io_writeb,
128
    &PPC_io_writew,
129
    &PPC_io_writel,
130
};
131

    
132
static CPUReadMemoryFunc *PPC_io_read[] = {
133
    &PPC_io_readb,
134
    &PPC_io_readw,
135
    &PPC_io_readl,
136
};
137

    
138
uint32_t pic_intack_read(CPUState *env);
139

    
140
/* Read-only register (?) */
141
static void _PPC_ioB_write (uint32_t addr, uint32_t value)
142
{
143
    PPC_IO_DPRINTF("0x%08x => 0x%08x\n", addr, value);
144
}
145

    
146
static uint32_t _PPC_ioB_read (uint32_t addr)
147
{
148
    uint32_t retval = 0;
149

    
150
    if (addr == 0xBFFFFFF0)
151
        retval = pic_intack_read(NULL);
152
    PPC_IO_DPRINTF("0x%08x <= 0x%08x\n", addr, retval);
153

    
154
    return retval;
155
}
156

    
157
static CPUWriteMemoryFunc *PPC_ioB_write[] = {
158
    &_PPC_ioB_write,
159
    &_PPC_ioB_write,
160
    &_PPC_ioB_write,
161
};
162

    
163
static CPUReadMemoryFunc *PPC_ioB_read[] = {
164
    &_PPC_ioB_read,
165
    &_PPC_ioB_read,
166
    &_PPC_ioB_read,
167
};
168

    
169
#if 0
170
static CPUWriteMemoryFunc *PPC_io3_write[] = {
171
    &PPC_io3_writeb,
172
    &PPC_io3_writew,
173
    &PPC_io3_writel,
174
};
175

176
static CPUReadMemoryFunc *PPC_io3_read[] = {
177
    &PPC_io3_readb,
178
    &PPC_io3_readw,
179
    &PPC_io3_readl,
180
};
181
#endif
182

    
183
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
184
static uint8_t PREP_fake_io[2];
185
static uint8_t NVRAM_lock;
186

    
187
static void PREP_io_write (CPUState *env, uint32_t addr, uint32_t val)
188
{
189
    PREP_fake_io[addr - 0x0398] = val;
190
}
191

    
192
static uint32_t PREP_io_read (CPUState *env, uint32_t addr)
193
{
194
    return PREP_fake_io[addr - 0x0398];
195
}
196

    
197
static uint8_t syscontrol;
198

    
199
static void PREP_io_800_writeb (CPUState *env, uint32_t addr, uint32_t val)
200
{
201
    switch (addr) {
202
    case 0x0092:
203
        /* Special port 92 */
204
        /* Check soft reset asked */
205
        if (val & 0x80) {
206
            printf("Soft reset asked... Stop emulation\n");
207
            abort();
208
        }
209
        /* Check LE mode */
210
        if (val & 0x40) {
211
            printf("Little Endian mode isn't supported (yet ?)\n");
212
            abort();
213
        }
214
        break;
215
    case 0x0808:
216
        /* Hardfile light register: don't care */
217
        break;
218
    case 0x0810:
219
        /* Password protect 1 register */
220
        NVRAM_lock ^= 0x01;
221
        break;
222
    case 0x0812:
223
        /* Password protect 2 register */
224
        NVRAM_lock ^= 0x02;
225
        break;
226
    case 0x0814:
227
        /* L2 invalidate register: don't care */
228
        break;
229
    case 0x081C:
230
        /* system control register */
231
        syscontrol = val;
232
        break;
233
    case 0x0850:
234
        /* I/O map type register */
235
        if (val & 0x80) {
236
            printf("No support for non-continuous I/O map mode\n");
237
            abort();
238
        }
239
        break;
240
    default:
241
        break;
242
    }
243
}
244

    
245
static uint32_t PREP_io_800_readb (CPUState *env, uint32_t addr)
246
{
247
    uint32_t retval = 0xFF;
248

    
249
    switch (addr) {
250
    case 0x0092:
251
        /* Special port 92 */
252
        retval = 0x40;
253
        break;
254
    case 0x080C:
255
        /* Equipment present register:
256
         *  no L2 cache
257
         *  no upgrade processor
258
         *  no cards in PCI slots
259
         *  SCSI fuse is bad
260
         */
261
        retval = 0xFC;
262
        break;
263
    case 0x0818:
264
        /* Keylock */
265
        retval = 0x00;
266
        break;
267
    case 0x081C:
268
        /* system control register
269
         * 7 - 6 / 1 - 0: L2 cache enable
270
         */
271
        retval = syscontrol;
272
        break;
273
    case 0x0823:
274
        /* */
275
        retval = 0x03; /* no L2 cache */
276
        break;
277
    case 0x0850:
278
        /* I/O map type register */
279
        retval = 0x00;
280
        break;
281
    default:
282
        break;
283
    }
284

    
285
    return retval;
286
}
287

    
288
/* M48T59 NVRAM/RTC emulation */
289
static uint8_t NVRAM[NVRAM_SIZE];
290

    
291
/* RTC */
292
static time_t time_offset;
293

    
294
time_t get_time (void)
295
{
296
    return time(NULL) + time_offset;
297
}
298

    
299
void set_time_offset (time_t new_time)
300
{
301
    time_t now = time(NULL);
302

    
303
    time_offset = new_time - now;
304
}
305

    
306
static void NVRAM_init (void)
307
{
308
    /* NVRAM header */
309
    /* 0x00: NVRAM size in kB */
310
    NVRAM[0x00] = (NVRAM_SIZE >> 12) & 0xFF;
311
    NVRAM[0x01] = (NVRAM_SIZE >> 10) & 0xFF;
312
    /* 0x02: NVRAM version */
313
    NVRAM[0x02] = 0x01;
314
    /* 0x03: NVRAM revision */
315
    NVRAM[0x03] = 0x00;
316
    /* 0x04: checksum 0 => OS area   */
317
    /* 0x06: checksum of config area */
318
    /* 0x08: last OS */
319
    NVRAM[0x08] = 0x00; /* Unknown */
320
    /* 0x09: endian */
321
    NVRAM[0x09] = 'B';
322
    /* 0x0B: PM mode */
323
    NVRAM[0x0B] = 0x00;
324
    /* Restart block description record */
325
    /* 0x0C: restart block version */
326
    NVRAM[0x0C] = 0x00;
327
    NVRAM[0x0D] = 0x01;
328
    /* 0x0E: restart block revision */
329
    NVRAM[0x0E] = 0x00;
330
    NVRAM[0x0F] = 0x00;
331
    /* 0x1C: checksum of restart block */
332
    /* 0x20: restart address */
333
    NVRAM[0x20] = 0x00;
334
    NVRAM[0x21] = 0x00;
335
    NVRAM[0x22] = 0x00;
336
    NVRAM[0x23] = 0x00;
337
    /* 0x24: save area address */
338
    NVRAM[0x24] = 0x00;
339
    NVRAM[0x25] = 0x00;
340
    NVRAM[0x26] = 0x00;
341
    NVRAM[0x27] = 0x00;
342
    /* 0x28: save area length */
343
    NVRAM[0x28] = 0x00;
344
    NVRAM[0x29] = 0x00;
345
    NVRAM[0x2A] = 0x00;
346
    NVRAM[0x2B] = 0x00;
347
    /* Security section */
348
    /* Set all to zero */
349
    /* 0xC4: pointer to global environment area */
350
    NVRAM[0xC4] = 0x00;
351
    NVRAM[0xC5] = 0x00;
352
    NVRAM[0xC6] = 0x01;
353
    NVRAM[0xC7] = 0x00;
354
    /* 0xC8: size of global environment area */
355
    NVRAM[0xC8] = 0x00;
356
    NVRAM[0xC9] = 0x00;
357
    NVRAM[0xCA] = 0x07;
358
    NVRAM[0xCB] = 0x00;
359
    /* 0xD4: pointer to configuration area */
360
    NVRAM[0xD4] = 0x00;
361
    NVRAM[0xD5] = 0x00;
362
    NVRAM[0xD6] = 0x08;
363
    NVRAM[0xD7] = 0x00;
364
    /* 0xD8: size of configuration area */
365
    NVRAM[0xD8] = 0x00;
366
    NVRAM[0xD9] = 0x00;
367
    NVRAM[0xDA] = 0x08;
368
    NVRAM[0xDB] = 0x00;
369
    /* 0xE8: pointer to OS specific area */
370
    NVRAM[0xE8] = 0x00;
371
    NVRAM[0xE9] = 0x00;
372
    NVRAM[0xEA] = 0x10;
373
    NVRAM[0xEB] = 0x00;
374
    /* 0xD8: size of OS specific area */
375
    NVRAM[0xEC] = 0x00;
376
    NVRAM[0xED] = 0x00;
377
    NVRAM[0xEE] = 0x0F;
378
    NVRAM[0xEF] = 0xF0;
379
    /* CRC */
380
    /* RTC init */
381
    NVRAM[0x1FFC] = 0x50;
382
}
383

    
384
static uint16_t NVRAM_addr;
385

    
386
/* Direct access to NVRAM */
387
void NVRAM_write (CPUState *env, uint32_t addr, uint32_t val)
388
{
389
    switch (addr) {
390
    case 0x1FF0:
391
        /* flags register */
392
        break;
393
    case 0x1FF1:
394
        /* unused */
395
        break;
396
    case 0x1FF2:
397
        /* alarm seconds */
398
        break;
399
    case 0x1FF3:
400
        /* alarm minutes */
401
        break;
402
    case 0x1FF4:
403
        /* alarm hours */
404
        break;
405
    case 0x1FF5:
406
        /* alarm date */
407
        break;
408
    case 0x1FF6:
409
        /* interrupts */
410
        break;
411
    case 0x1FF7:
412
        /* watchdog */
413
        break;
414
    case 0x1FF8:
415
        /* control */
416
        break;
417
    case 0x1FF9:
418
        /* seconds (BCD) */
419
        break;
420
    case 0x1FFA:
421
        /* minutes (BCD) */
422
        break;
423
    case 0x1FFB:
424
        /* hours (BCD) */
425
        break;
426
    case 0x1FFC:
427
        /* day of the week / century */
428
        NVRAM[0x1FFC] = val & 0x50;
429
        break;
430
    case 0x1FFD:
431
        /* date */
432
        break;
433
    case 0x1FFE:
434
        /* month */
435
        break;
436
    case 0x1FFF:
437
        /* year */
438
        break;
439
    default:
440
        if (addr < NVRAM_SIZE)
441
            NVRAM[addr] = val & 0xFF;
442
        break;
443
    }
444
}
445

    
446
uint32_t NVRAM_read (CPUState *env, uint32_t addr)
447
{
448
    struct tm tm;
449
    time_t t;
450
    uint32_t retval = 0xFF;
451

    
452
    switch (addr) {
453
    case 0x1FF0:
454
        /* flags register */
455
        break;
456
    case 0x1FF1:
457
        /* unused */
458
        break;
459
    case 0x1FF2:
460
        /* alarm seconds */
461
        break;
462
    case 0x1FF3:
463
        /* alarm minutes */
464
        break;
465
    case 0x1FF4:
466
        /* alarm hours */
467
        break;
468
    case 0x1FF5:
469
        /* alarm date */
470
        break;
471
    case 0x1FF6:
472
        /* interrupts */
473
        break;
474
    case 0x1FF7:
475
        /* watchdog */
476
        break;
477
    case 0x1FF8:
478
        /* control */
479
        break;
480
    case 0x1FF9:
481
        /* seconds (BCD) */
482
        t = get_time();
483
        localtime_r(&t, &tm);
484
        retval = ((tm.tm_sec / 10) << 4) | (tm.tm_sec % 10);
485
//            printf("return seconds=%d\n", tm.tm_sec);
486
        break;
487
    case 0x1FFA:
488
        /* minutes (BCD) */
489
        t = get_time();
490
        localtime_r(&t, &tm);
491
        retval = ((tm.tm_min / 10) << 4) | (tm.tm_min % 10);
492
        break;
493
    case 0x1FFB:
494
        /* hours (BCD) */
495
        t = get_time();
496
        localtime_r(&t, &tm);
497
        retval = ((tm.tm_hour / 10) << 4) | (tm.tm_hour % 10);
498
        break;
499
    case 0x1FFC:
500
        /* day of the week / century */
501
        t = get_time();
502
        localtime_r(&t, &tm);
503
        retval = (NVRAM[0x1FFC] & 0x50) | tm.tm_wday;
504
        break;
505
    case 0x1FFD:
506
        /* date */
507
        t = get_time();
508
        localtime_r(&t, &tm);
509
        retval = ((tm.tm_mday / 10) << 4) | (tm.tm_mday % 10);
510
        break;
511
    case 0x1FFE:
512
        /* month */
513
        t = get_time();
514
        localtime_r(&t, &tm);
515
        retval = ((tm.tm_mon / 10) << 4) | (tm.tm_mon % 10);
516
        break;
517
    case 0x1FFF:
518
        /* year */
519
        t = get_time();
520
        localtime_r(&t, &tm);
521
        retval = ((tm.tm_year / 10) << 4) | (tm.tm_year % 10);
522
        break;
523
    default:
524
        if (NVRAM_addr < NVRAM_SIZE)
525
            retval = NVRAM[NVRAM_addr];
526
        break;
527
    }
528

    
529
    return retval;
530
}
531

    
532
/* IO access to NVRAM */
533
static void NVRAM_writeb (CPUState *env, uint32_t addr, uint32_t val)
534
{
535
    switch (addr) {
536
    case 0x74:
537
        NVRAM_addr &= ~0x00FF;
538
        NVRAM_addr |= val;
539
        break;
540
    case 0x75:
541
        NVRAM_addr &= ~0xFF00;
542
        NVRAM_addr |= val << 8;
543
        break;
544
    case 0x77:
545
        NVRAM_write(env, NVRAM_addr, val);
546
        NVRAM_addr = 0x0000;
547
        break;
548
    default:
549
        break;
550
    }
551
}
552

    
553
static uint32_t NVRAM_readb (CPUState *env, uint32_t addr)
554
{
555
    if (addr == 0x77)
556
        return NVRAM_read(env, NVRAM_addr);
557

    
558
    return 0xFF;
559
}
560

    
561
int load_initrd (const char *filename, uint8_t *addr)
562
{
563
    int fd, size;
564

    
565
    printf("Load initrd\n");
566
    fd = open(filename, O_RDONLY);
567
    if (fd < 0)
568
        return -1;
569
    size = read(fd, addr, 16 * 1024 * 1024);
570
    if (size < 0)
571
        goto fail;
572
    close(fd);
573
    printf("Load initrd: %d\n", size);
574
    return size;
575
 fail:
576
    close(fd);
577
    printf("Load initrd failed\n");
578
    return -1;
579
}
580

    
581
/* Quick hack for PPC memory infos... */
582
static void put_long (void *addr, uint32_t l)
583
{
584
    char *pos = addr;
585
    pos[0] = (l >> 24) & 0xFF;
586
    pos[1] = (l >> 16) & 0xFF;
587
    pos[2] = (l >> 8) & 0xFF;
588
    pos[3] = l & 0xFF;
589
}
590

    
591
/* bootloader infos are in the form:
592
 * uint32_t TAG
593
 * uint32_t TAG_size (from TAG to next TAG).
594
 * datas
595
 * ....
596
 */
597
#if !defined (USE_OPEN_FIRMWARE)
598
static void *set_bootinfo_tag (void *addr, uint32_t tag, uint32_t size,
599
                               void *data)
600
{
601
    char *pos = addr;
602

    
603
    put_long(pos, tag);
604
    pos += 4;
605
    put_long(pos, size + 8);
606
    pos += 4;
607
    memcpy(pos, data, size);
608
    pos += size;
609

    
610
    return pos;
611
}
612
#endif
613

    
614
typedef struct boot_dev_t {
615
    const unsigned char *name;
616
    int major;
617
    int minor;
618
} boot_dev_t;
619

    
620
static boot_dev_t boot_devs[] = 
621
{
622
    { "/dev/fd0", 2, 0, },
623
    { "/dev/fd1", 2, 1, },
624
    { "/dev/hda1", 3, 1, },
625
//    { "/dev/ide/host0/bus0/target0/lun0/part1", 3, 1, },
626
    { "/dev/hdc", 22, 0, },
627
    { "/dev/ram0 init=/linuxrc", 1, 0, },
628
};
629

    
630
/* BATU:
631
 * BEPI  : bloc virtual address
632
 * BL    : area size bits (128 kB is 0, 256 1, 512 3, ...
633
 * Vs/Vp
634
 * BATL:
635
 * BPRN  : bloc real address align on 4MB boundary
636
 * WIMG  : cache access mode : not used
637
 * PP    : protection bits
638
 */
639
static void setup_BAT (CPUPPCState *env, int BAT,
640
                       uint32_t virtual, uint32_t physical,
641
                       uint32_t size, int Vs, int Vp, int PP)
642
{
643
    uint32_t sz_bits, tmp_sz, align, tmp;
644
    
645
    sz_bits = 0;
646
    align = 131072;
647
    for (tmp_sz = size / 131072; tmp_sz != 1; tmp_sz = tmp_sz >> 1) {
648
        sz_bits = (sz_bits << 1) + 1;
649
        align = align << 1;
650
    }
651
    tmp = virtual & ~(align - 1);  /* Align virtual area start */
652
    tmp |= sz_bits << 2;           /* Fix BAT size             */
653
    tmp |= Vs << 1;                /* Supervisor access        */
654
    tmp |= Vp;                     /* User access              */
655
    env->DBAT[0][BAT] = tmp;
656
    env->IBAT[0][BAT] = tmp;
657
    tmp = physical & ~(align - 1); /* Align physical area start */
658
    tmp |= 0;                      /* Don't care about WIMG     */
659
    tmp |= PP;                     /* Protection                */
660
    env->DBAT[1][BAT] = tmp;
661
    env->IBAT[1][BAT] = tmp;
662
    printf("Set BATU0 to 0x%08x BATL0 to 0x%08x\n",
663
           env->DBAT[0][BAT], env->DBAT[1][BAT]);
664
}
665

    
666
static void VGA_printf (uint8_t *s)
667
{
668
    uint16_t *arg_ptr;
669
    unsigned int format_width, i;
670
    int in_format;
671
    uint16_t arg, digit, nibble;
672
    uint8_t c;
673

    
674
    arg_ptr = (uint16_t *)(&s);
675
    in_format = 0;
676
    format_width = 0;
677
    while ((c = *s) != '\0') {
678
        if (c == '%') {
679
            in_format = 1;
680
            format_width = 0;
681
        } else if (in_format) {
682
            if ((c >= '0') && (c <= '9')) {
683
                format_width = (format_width * 10) + (c - '0');
684
            } else if (c == 'x') {
685
                arg_ptr++; // increment to next arg
686
                arg = *arg_ptr;
687
                if (format_width == 0)
688
                    format_width = 4;
689
                digit = format_width - 1;
690
                for (i = 0; i < format_width; i++) {
691
                    nibble = (arg >> (4 * digit)) & 0x000f;
692
                    if (nibble <= 9)
693
                        PPC_io_writeb(PPC_IO_BASE + 0x500, nibble + '0');
694
                    else
695
                        PPC_io_writeb(PPC_IO_BASE + 0x500, nibble + 'A');
696
                    digit--;
697
                }
698
                in_format = 0;
699
            }
700
            //else if (c == 'd') {
701
            //  in_format = 0;
702
            //  }
703
        } else {
704
            PPC_io_writeb(PPC_IO_BASE + 0x500, c);
705
        }
706
        s++;
707
    }
708
}
709

    
710
static void VGA_init (void)
711
{
712
    /* Basic VGA init, inspired by plex86 VGAbios */
713
    printf("Init VGA...\n");
714
    /* switch to color mode and enable CPU access 480 lines */
715
    PPC_io_writeb(PPC_IO_BASE + 0x3C2, 0xC3);
716
    /* more than 64k 3C4/04 */
717
    PPC_io_writeb(PPC_IO_BASE + 0x3C4, 0x04);
718
    PPC_io_writeb(PPC_IO_BASE + 0x3C5, 0x02);
719
    VGA_printf("PPC VGA BIOS...\n");
720
}
721

    
722
void PPC_init_hw (CPUPPCState *env, uint32_t mem_size,
723
                  uint32_t kernel_addr, uint32_t kernel_size,
724
                  uint32_t stack_addr, int boot_device)
725
{
726
    char *p;
727
#if !defined (USE_OPEN_FIRMWARE)
728
    char *tmp;
729
    uint32_t tmpi[2];
730
#endif
731
    int PPC_io_memory;
732
    
733
#if defined (USE_OPEN_FIRMWARE)
734
    setup_memory(env, mem_size);
735
#endif
736
    /* Register 64 kB of IO space */
737
    PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write);
738
    cpu_register_physical_memory(0x80000000, 0x10000, PPC_io_memory);
739
    /* Register fake IO ports for PREP */
740
    register_ioport_read(0x398, 2, PREP_io_read, 1);
741
    register_ioport_write(0x398, 2, PREP_io_write, 1);
742
    /* System control ports */
743
    register_ioport_write(0x0092, 0x1, PREP_io_800_writeb, 1);
744
    register_ioport_read(0x0800, 0x52, PREP_io_800_readb, 1);
745
    register_ioport_write(0x0800, 0x52, PREP_io_800_writeb, 1);
746
    /* PCI intack location */
747
    PPC_io_memory = cpu_register_io_memory(0, PPC_ioB_read, PPC_ioB_write);
748
    cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
749
    /* NVRAM ports */
750
    NVRAM_init();
751
    register_ioport_read(0x0074, 0x04, NVRAM_readb, 1);
752
    register_ioport_write(0x0074, 0x04, NVRAM_writeb, 1);
753

    
754
    /* Fake bootloader */
755
    env->nip = kernel_addr + (3 * sizeof(uint32_t));
756
    /* Set up msr according to PREP specification */
757
    msr_ee = 0;
758
    msr_fp = 1;
759
    msr_pr = 0; /* Start in supervisor mode */
760
    msr_me = 1;
761
    msr_fe0 = msr_fe1 = 0;
762
    msr_ip = 0;
763
    msr_ir = msr_dr = 1;
764
//    msr_sf = 0;
765
    msr_le = msr_ile = 0;
766
    env->gpr[1] = stack_addr; /* Let's have a stack */
767
    env->gpr[2] = 0;
768
    env->gpr[8] = kernel_addr;
769
    /* There is a bug in  2.4 kernels:
770
     * if a decrementer exception is pending when it enables msr_ee,
771
     * it's not ready to handle it...
772
     */
773
    env->decr = 0xFFFFFFFF;
774
    p = (void *)(phys_ram_base + kernel_addr);
775
#if !defined (USE_OPEN_FIRMWARE)
776
    /* Let's register the whole memory available only in supervisor mode */
777
    setup_BAT(env, 0, 0x00000000, 0x00000000, mem_size, 1, 0, 2);
778
    /* Avoid open firmware init call (to get a console)
779
     * This will make the kernel think we are a PREP machine...
780
     */
781
    put_long(p, 0xdeadc0de);
782
    /* Build a real stack room */
783
    p = (void *)(phys_ram_base + stack_addr);
784
    put_long(p, stack_addr);
785
    p -= 32;
786
    env->gpr[1] -= 32;
787
    /* Pretend there are no residual data */
788
    env->gpr[3] = 0;
789
#if 1
790
    {
791
        int size;
792
        env->gpr[4] = 0x00800000;
793
        size = load_initrd("initrd",
794
                           (void *)((uint32_t)phys_ram_base + env->gpr[4]));
795
        if (size < 0) {
796
            /* No initrd */
797
            env->gpr[4] = env->gpr[5] = 0;
798
        } else {
799
            env->gpr[5] = size;
800
            boot_device = 'e';
801
        }
802
        printf("Initrd loaded at 0x%08x (%d)\n", env->gpr[4], env->gpr[5]);
803
    }
804
#else
805
    env->gpr[4] = env->gpr[5] = 0;
806
#endif
807
    /* We have to put bootinfos after the BSS
808
     * The BSS starts after the kernel end.
809
     */
810
#if 0
811
    p = (void *)(((uint32_t)phys_ram_base + kernel_addr +
812
                  kernel_size + (1 << 20) - 1) & ~((1 << 20) - 1));
813
#else
814
    p = (void *)((uint32_t)phys_ram_base + kernel_addr + 0x400000);
815
#endif
816
    if (loglevel > 0) {
817
        fprintf(logfile, "bootinfos: %p 0x%08x\n",
818
                p, (uint32_t)p - (uint32_t)phys_ram_base);
819
    } else {
820
        printf("bootinfos: %p 0x%08x\n",
821
               p, (uint32_t)p - (uint32_t)phys_ram_base);
822
    }
823
    /* Command line: let's put it after bootinfos */
824
#if 0
825
    sprintf(p + 0x1000, "console=ttyS0,9600 root=%02x%02x mem=%dM",
826
            boot_devs[boot_device - 'a'].major,
827
            boot_devs[boot_device - 'a'].minor,
828
            phys_ram_size >> 20);
829
#else
830
    sprintf(p + 0x1000, "console=ttyS0,9600 console=tty0 root=%s mem=%dM load_ramdisk=1",
831
            boot_devs[boot_device - 'a'].name,
832
            phys_ram_size >> 20);
833
#endif
834
    env->gpr[6] = (uint32_t)p + 0x1000 - (uint32_t)phys_ram_base;
835
    env->gpr[7] = env->gpr[6] + strlen(p + 0x1000);
836
    if (loglevel > 0) {
837
        fprintf(logfile, "cmdline: %p 0x%08x [%s]\n",
838
                p + 0x1000, env->gpr[6], p + 0x1000);
839
    } else {
840
        printf("cmdline: %p 0x%08x [%s]\n",
841
               p + 0x1000, env->gpr[6], p + 0x1000);
842
    }
843
    /* BI_FIRST */
844
    p = set_bootinfo_tag(p, 0x1010, 0, 0);
845
    /* BI_CMD_LINE */
846
    p = set_bootinfo_tag(p, 0x1012, env->gpr[7] - env->gpr[6],
847
                         (void *)(env->gpr[6] + (uint32_t)phys_ram_base));
848
    /* BI_MEM_SIZE */
849
    tmp = (void *)tmpi;
850
    tmp[0] = (phys_ram_size >> 24) & 0xFF;
851
    tmp[1] = (phys_ram_size >> 16) & 0xFF;
852
    tmp[2] = (phys_ram_size >> 8) & 0xFF;
853
    tmp[3] = phys_ram_size & 0xFF;
854
    p = set_bootinfo_tag(p, 0x1017, 4, tmpi);
855
    /* BI_INITRD */
856
    tmp[0] = (env->gpr[4] >> 24) & 0xFF;
857
    tmp[1] = (env->gpr[4] >> 16) & 0xFF;
858
    tmp[2] = (env->gpr[4] >> 8) & 0xFF;
859
    tmp[3] = env->gpr[4] & 0xFF;
860
    tmp[4] = (env->gpr[5] >> 24) & 0xFF;
861
    tmp[5] = (env->gpr[5] >> 16) & 0xFF;
862
    tmp[6] = (env->gpr[5] >> 8) & 0xFF;
863
    tmp[7] = env->gpr[5] & 0xFF;
864
    p = set_bootinfo_tag(p, 0x1014, 8, tmpi);
865
    /* BI_LAST */
866
    p = set_bootinfo_tag(p, 0x1011, 0, 0);
867
#else
868
    /* Set up MMU:
869
     * kernel is loaded at kernel_addr and wants to be seen at 0x01000000
870
     */
871
    setup_BAT(env, 0, 0x01000000, kernel_addr, 0x00400000, 1, 0, 2);
872
    {
873
#if 0
874
        uint32_t offset = 
875
            *((uint32_t *)((uint32_t)phys_ram_base + kernel_addr));
876
#else
877
        uint32_t offset = 12;
878
#endif
879
        env->nip = 0x01000000 | (kernel_addr + offset);
880
        printf("Start address: 0x%08x\n", env->nip);
881
    }
882
    env->gpr[1] = env->nip + (1 << 22);
883
    p = (void *)(phys_ram_base + stack_addr);
884
    put_long(p - 32, stack_addr);
885
    env->gpr[1] -= 32;
886
    printf("Kernel starts at 0x%08x stack 0x%08x\n", env->nip, env->gpr[1]);
887
    /* We want all lower address not to be translated */
888
    setup_BAT(env, 1, 0x00000000, 0x00000000, 0x010000000, 1, 1, 2);
889
    /* We also need a BAT to access OF */
890
    setup_BAT(env, 2, 0xFFFE0000, mem_size - 131072, 131072, 1, 0, 1);
891
    /* Setup OF entry point */
892
    {
893
        char *p;
894
        p = (char *)phys_ram_base + mem_size - 131072;
895
        /* Special opcode to call OF */
896
        *p++ = 0x18; *p++ = 0x00; *p++ = 0x00; *p++ = 0x02;
897
        /* blr */
898
        *p++ = 0x4E; *p++ = 0x80; *p++ = 0x00; *p++ = 0x20;
899
    }
900
    env->gpr[5] = 0xFFFE0000;
901
    /* Register translations */
902
    {
903
        OF_transl_t translations[3] = {
904
            { 0x01000000, 0x00400000, kernel_addr, 0x00000002, },
905
            { 0x00000000, 0x01000000, 0x00000000, 0x00000002, },
906
            { 0xFFFE0000, 0x00020000, mem_size - (128 * 1024),
907
              0x00000001, },
908
        };
909
        OF_register_translations(3, translations);
910
    }
911
    /* Quite artificial, for now */
912
    OF_register_bus("isa", "isa");
913
    OF_register_serial("isa", "serial", 4, 0x3f8);
914
    OF_register_stdio("serial", "serial");
915
    /* Set up RTAS service */
916
    RTAS_init();
917
    /* Command line: let's put it just over the stack */
918
#if 1
919
    sprintf(p, "console=ttyS0,9600 root=%02x%02x mem=%dM",
920
            boot_devs[boot_device - 'a'].major,
921
            boot_devs[boot_device - 'a'].minor,
922
            phys_ram_size >> 20);
923
#else
924
    sprintf(p, "console=ttyS0,9600 root=%s mem=%dM ne2000=0x300,9",
925
            boot_devs[boot_device - 'a'].name,
926
            phys_ram_size >> 20);
927
#endif
928
    OF_register_bootargs(p);
929
#endif
930
}
931

    
932
void PPC_end_init (void)
933
{
934
    VGA_init();
935
}