ppc_prep.c 22.7 KB
Newer Older
1
/*
2
 * QEMU PPC PREP hardware System Emulator
3
 *
4
 * Copyright (c) 2003-2007 Jocelyn Mayer
5
 *
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * 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.
23
 */
P
pbrook 已提交
24 25 26 27 28 29 30 31
#include "hw.h"
#include "nvram.h"
#include "pc.h"
#include "fdc.h"
#include "net.h"
#include "sysemu.h"
#include "isa.h"
#include "pci.h"
32 33
#include "prep_pci.h"
#include "usb-ohci.h"
P
pbrook 已提交
34 35
#include "ppc.h"
#include "boards.h"
B
blueswir1 已提交
36
#include "qemu-log.h"
G
Gerd Hoffmann 已提交
37
#include "ide.h"
B
Blue Swirl 已提交
38
#include "loader.h"
39
#include "mc146818rtc.h"
B
Blue Swirl 已提交
40
#include "blockdev.h"
41

42
//#define HARD_DEBUG_PPC_IO
43
//#define DEBUG_PPC_IO
44

45 46 47
/* SMP is not enabled, for now */
#define MAX_CPUS 1

T
ths 已提交
48 49
#define MAX_IDE_BUS 2

50
#define BIOS_SIZE (1024 * 1024)
B
bellard 已提交
51 52 53
#define BIOS_FILENAME "ppc_rom.bin"
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
B
bellard 已提交
54

55 56 57 58 59
#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
#define DEBUG_PPC_IO
#endif

#if defined (HARD_DEBUG_PPC_IO)
60
#define PPC_IO_DPRINTF(fmt, ...)                         \
61
do {                                                     \
62
    if (qemu_loglevel_mask(CPU_LOG_IOPORT)) {            \
63
        qemu_log("%s: " fmt, __func__ , ## __VA_ARGS__); \
64
    } else {                                             \
65
        printf("%s : " fmt, __func__ , ## __VA_ARGS__);  \
66 67 68
    }                                                    \
} while (0)
#elif defined (DEBUG_PPC_IO)
69 70
#define PPC_IO_DPRINTF(fmt, ...) \
qemu_log_mask(CPU_LOG_IOPORT, fmt, ## __VA_ARGS__)
71
#else
72
#define PPC_IO_DPRINTF(fmt, ...) do { } while (0)
73 74
#endif

B
bellard 已提交
75
/* Constants for devices init */
76 77 78 79 80 81 82 83
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 13, 13 };

#define NE2000_NB_MAX 6

static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
84

B
bellard 已提交
85 86 87
//static PITState *pit;

/* ISA IO ports bridge */
88 89
#define PPC_IO_BASE 0x80000000

90
#if 0
B
bellard 已提交
91
/* Speaker port 0x61 */
92 93 94
static int speaker_data_on;
static int dummy_refresh_clock;
#endif
B
bellard 已提交
95

96
static void speaker_ioport_write (void *opaque, uint32_t addr, uint32_t val)
97
{
98
#if 0
B
bellard 已提交
99 100
    speaker_data_on = (val >> 1) & 1;
    pit_set_gate(pit, 2, val & 1);
101
#endif
102 103
}

104
static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
105
{
106
#if 0
B
bellard 已提交
107 108 109 110
    int out;
    out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
    dummy_refresh_clock ^= 1;
    return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
111
        (dummy_refresh_clock << 4);
112
#endif
B
bellard 已提交
113
    return 0;
114 115
}

B
bellard 已提交
116 117
/* PCI intack register */
/* Read-only register (?) */
118
static void _PPC_intack_write (void *opaque,
A
Anthony Liguori 已提交
119
                               target_phys_addr_t addr, uint32_t value)
B
bellard 已提交
120
{
121 122 123 124
#if 0
    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
           value);
#endif
B
bellard 已提交
125 126
}

A
Anthony Liguori 已提交
127
static inline uint32_t _PPC_intack_read(target_phys_addr_t addr)
B
bellard 已提交
128 129 130
{
    uint32_t retval = 0;

131
    if ((addr & 0xf) == 0)
B
bellard 已提交
132
        retval = pic_intack_read(isa_pic);
133 134 135 136
#if 0
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
#endif
B
bellard 已提交
137 138 139 140

    return retval;
}

A
Anthony Liguori 已提交
141
static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
142 143 144 145
{
    return _PPC_intack_read(addr);
}

A
Anthony Liguori 已提交
146
static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
147
{
B
bellard 已提交
148
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
149 150 151
    return bswap16(_PPC_intack_read(addr));
#else
    return _PPC_intack_read(addr);
B
bellard 已提交
152
#endif
153 154
}

A
Anthony Liguori 已提交
155
static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
156
{
B
bellard 已提交
157
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
158 159 160
    return bswap32(_PPC_intack_read(addr));
#else
    return _PPC_intack_read(addr);
B
bellard 已提交
161
#endif
162 163
}

164
static CPUWriteMemoryFunc * const PPC_intack_write[] = {
B
bellard 已提交
165 166 167 168 169
    &_PPC_intack_write,
    &_PPC_intack_write,
    &_PPC_intack_write,
};

170
static CPUReadMemoryFunc * const PPC_intack_read[] = {
B
bellard 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
    &PPC_intack_readb,
    &PPC_intack_readw,
    &PPC_intack_readl,
};

/* PowerPC control and status registers */
#if 0 // Not used
static struct {
    /* IDs */
    uint32_t veni_devi;
    uint32_t revi;
    /* Control and status */
    uint32_t gcsr;
    uint32_t xcfr;
    uint32_t ct32;
    uint32_t mcsr;
    /* General purpose registers */
    uint32_t gprg[6];
    /* Exceptions */
    uint32_t feen;
    uint32_t fest;
    uint32_t fema;
    uint32_t fecl;
    uint32_t eeen;
    uint32_t eest;
    uint32_t eecl;
    uint32_t eeint;
    uint32_t eemck0;
    uint32_t eemck1;
    /* Error diagnostic */
} XCSR;

203
static void PPC_XCSR_writeb (void *opaque,
A
Anthony Liguori 已提交
204
                             target_phys_addr_t addr, uint32_t value)
B
bellard 已提交
205
{
206 207
    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
           value);
B
bellard 已提交
208 209
}

210
static void PPC_XCSR_writew (void *opaque,
A
Anthony Liguori 已提交
211
                             target_phys_addr_t addr, uint32_t value)
212
{
B
bellard 已提交
213
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
214
    value = bswap16(value);
B
bellard 已提交
215
#endif
216 217
    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
           value);
218 219
}

220
static void PPC_XCSR_writel (void *opaque,
A
Anthony Liguori 已提交
221
                             target_phys_addr_t addr, uint32_t value)
222
{
B
bellard 已提交
223
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
224
    value = bswap32(value);
B
bellard 已提交
225
#endif
226 227
    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
           value);
228 229
}

A
Anthony Liguori 已提交
230
static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
231 232
{
    uint32_t retval = 0;
233

234 235
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
236

B
bellard 已提交
237 238 239
    return retval;
}

A
Anthony Liguori 已提交
240
static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
241
{
B
bellard 已提交
242 243
    uint32_t retval = 0;

244 245
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
B
bellard 已提交
246 247 248 249 250
#ifdef TARGET_WORDS_BIGENDIAN
    retval = bswap16(retval);
#endif

    return retval;
251 252
}

A
Anthony Liguori 已提交
253
static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
254 255 256
{
    uint32_t retval = 0;

257 258
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
B
bellard 已提交
259 260 261
#ifdef TARGET_WORDS_BIGENDIAN
    retval = bswap32(retval);
#endif
262 263 264 265

    return retval;
}

266
static CPUWriteMemoryFunc * const PPC_XCSR_write[] = {
B
bellard 已提交
267 268 269
    &PPC_XCSR_writeb,
    &PPC_XCSR_writew,
    &PPC_XCSR_writel,
270 271
};

272
static CPUReadMemoryFunc * const PPC_XCSR_read[] = {
B
bellard 已提交
273 274 275
    &PPC_XCSR_readb,
    &PPC_XCSR_readw,
    &PPC_XCSR_readl,
276
};
B
bellard 已提交
277
#endif
278

B
bellard 已提交
279
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
A
Anthony Liguori 已提交
280
typedef struct sysctrl_t {
J
j_mayer 已提交
281
    qemu_irq reset_irq;
282
    M48t59State *nvram;
B
bellard 已提交
283 284 285
    uint8_t state;
    uint8_t syscontrol;
    uint8_t fake_io[2];
B
bellard 已提交
286
    int contiguous_map;
B
bellard 已提交
287
    int endian;
A
Anthony Liguori 已提交
288
} sysctrl_t;
289

B
bellard 已提交
290 291
enum {
    STATE_HARDFILE = 0x01,
292 293
};

A
Anthony Liguori 已提交
294
static sysctrl_t *sysctrl;
295

296
static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
297
{
A
Anthony Liguori 已提交
298
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
299

300 301
    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
                   val);
B
bellard 已提交
302
    sysctrl->fake_io[addr - 0x0398] = val;
303 304
}

305
static uint32_t PREP_io_read (void *opaque, uint32_t addr)
306
{
A
Anthony Liguori 已提交
307
    sysctrl_t *sysctrl = opaque;
308

309
    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
B
bellard 已提交
310 311 312
                   sysctrl->fake_io[addr - 0x0398]);
    return sysctrl->fake_io[addr - 0x0398];
}
313

314
static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
315
{
A
Anthony Liguori 已提交
316
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
317

318 319
    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n",
                   addr - PPC_IO_BASE, val);
320 321 322 323
    switch (addr) {
    case 0x0092:
        /* Special port 92 */
        /* Check soft reset asked */
B
bellard 已提交
324
        if (val & 0x01) {
J
j_mayer 已提交
325 326 327
            qemu_irq_raise(sysctrl->reset_irq);
        } else {
            qemu_irq_lower(sysctrl->reset_irq);
328 329
        }
        /* Check LE mode */
B
bellard 已提交
330
        if (val & 0x02) {
B
bellard 已提交
331 332 333
            sysctrl->endian = 1;
        } else {
            sysctrl->endian = 0;
334 335
        }
        break;
B
bellard 已提交
336 337 338 339 340 341 342 343 344
    case 0x0800:
        /* Motorola CPU configuration register : read-only */
        break;
    case 0x0802:
        /* Motorola base module feature register : read-only */
        break;
    case 0x0803:
        /* Motorola base module status register : read-only */
        break;
345
    case 0x0808:
B
bellard 已提交
346 347 348 349 350
        /* Hardfile light register */
        if (val & 1)
            sysctrl->state |= STATE_HARDFILE;
        else
            sysctrl->state &= ~STATE_HARDFILE;
351 352 353
        break;
    case 0x0810:
        /* Password protect 1 register */
B
bellard 已提交
354 355
        if (sysctrl->nvram != NULL)
            m48t59_toggle_lock(sysctrl->nvram, 1);
356 357 358
        break;
    case 0x0812:
        /* Password protect 2 register */
B
bellard 已提交
359 360
        if (sysctrl->nvram != NULL)
            m48t59_toggle_lock(sysctrl->nvram, 2);
361 362
        break;
    case 0x0814:
B
bellard 已提交
363
        /* L2 invalidate register */
B
bellard 已提交
364
        //        tlb_flush(first_cpu, 1);
365 366 367
        break;
    case 0x081C:
        /* system control register */
B
bellard 已提交
368
        sysctrl->syscontrol = val & 0x0F;
369 370 371
        break;
    case 0x0850:
        /* I/O map type register */
B
bellard 已提交
372
        sysctrl->contiguous_map = val & 0x01;
373 374
        break;
    default:
375 376
        printf("ERROR: unaffected IO port write: %04" PRIx32
               " => %02" PRIx32"\n", addr, val);
377 378 379 380
        break;
    }
}

381
static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
382
{
A
Anthony Liguori 已提交
383
    sysctrl_t *sysctrl = opaque;
384 385 386 387 388
    uint32_t retval = 0xFF;

    switch (addr) {
    case 0x0092:
        /* Special port 92 */
B
bellard 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401
        retval = 0x00;
        break;
    case 0x0800:
        /* Motorola CPU configuration register */
        retval = 0xEF; /* MPC750 */
        break;
    case 0x0802:
        /* Motorola Base module feature register */
        retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
        break;
    case 0x0803:
        /* Motorola base module status register */
        retval = 0xE0; /* Standard MPC750 */
402 403 404 405 406 407 408 409
        break;
    case 0x080C:
        /* Equipment present register:
         *  no L2 cache
         *  no upgrade processor
         *  no cards in PCI slots
         *  SCSI fuse is bad
         */
B
bellard 已提交
410 411 412 413 414
        retval = 0x3C;
        break;
    case 0x0810:
        /* Motorola base module extended feature register */
        retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
415
        break;
B
bellard 已提交
416 417 418
    case 0x0814:
        /* L2 invalidate: don't care */
        break;
419 420 421 422 423 424 425 426
    case 0x0818:
        /* Keylock */
        retval = 0x00;
        break;
    case 0x081C:
        /* system control register
         * 7 - 6 / 1 - 0: L2 cache enable
         */
B
bellard 已提交
427
        retval = sysctrl->syscontrol;
428 429 430 431 432 433 434
        break;
    case 0x0823:
        /* */
        retval = 0x03; /* no L2 cache */
        break;
    case 0x0850:
        /* I/O map type register */
B
bellard 已提交
435
        retval = sysctrl->contiguous_map;
436 437
        break;
    default:
438
        printf("ERROR: unaffected IO port: %04" PRIx32 " read\n", addr);
439 440
        break;
    }
441 442
    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n",
                   addr - PPC_IO_BASE, retval);
443 444 445 446

    return retval;
}

A
Anthony Liguori 已提交
447 448
static inline target_phys_addr_t prep_IO_address(sysctrl_t *sysctrl,
                                                 target_phys_addr_t addr)
B
bellard 已提交
449 450 451 452 453 454 455 456 457 458 459 460
{
    if (sysctrl->contiguous_map == 0) {
        /* 64 KB contiguous space for IOs */
        addr &= 0xFFFF;
    } else {
        /* 8 MB non-contiguous space for IOs */
        addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
    }

    return addr;
}

A
Anthony Liguori 已提交
461
static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr,
B
bellard 已提交
462 463
                                uint32_t value)
{
A
Anthony Liguori 已提交
464
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
465 466

    addr = prep_IO_address(sysctrl, addr);
467
    cpu_outb(addr, value);
B
bellard 已提交
468 469
}

A
Anthony Liguori 已提交
470
static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
471
{
A
Anthony Liguori 已提交
472
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
473 474 475
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
476
    ret = cpu_inb(addr);
B
bellard 已提交
477 478 479 480

    return ret;
}

A
Anthony Liguori 已提交
481
static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr,
B
bellard 已提交
482 483
                                uint32_t value)
{
A
Anthony Liguori 已提交
484
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
485 486 487 488 489

    addr = prep_IO_address(sysctrl, addr);
#ifdef TARGET_WORDS_BIGENDIAN
    value = bswap16(value);
#endif
490
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
491
    cpu_outw(addr, value);
B
bellard 已提交
492 493
}

A
Anthony Liguori 已提交
494
static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
495
{
A
Anthony Liguori 已提交
496
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
497 498 499
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
500
    ret = cpu_inw(addr);
B
bellard 已提交
501 502 503
#ifdef TARGET_WORDS_BIGENDIAN
    ret = bswap16(ret);
#endif
504
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
B
bellard 已提交
505 506 507 508

    return ret;
}

A
Anthony Liguori 已提交
509
static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr,
B
bellard 已提交
510 511
                                uint32_t value)
{
A
Anthony Liguori 已提交
512
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
513 514 515 516 517

    addr = prep_IO_address(sysctrl, addr);
#ifdef TARGET_WORDS_BIGENDIAN
    value = bswap32(value);
#endif
518
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
519
    cpu_outl(addr, value);
B
bellard 已提交
520 521
}

A
Anthony Liguori 已提交
522
static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
523
{
A
Anthony Liguori 已提交
524
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
525 526 527
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
528
    ret = cpu_inl(addr);
B
bellard 已提交
529 530 531
#ifdef TARGET_WORDS_BIGENDIAN
    ret = bswap32(ret);
#endif
532
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
B
bellard 已提交
533 534 535 536

    return ret;
}

537
static CPUWriteMemoryFunc * const PPC_prep_io_write[] = {
B
bellard 已提交
538 539 540 541 542
    &PPC_prep_io_writeb,
    &PPC_prep_io_writew,
    &PPC_prep_io_writel,
};

543
static CPUReadMemoryFunc * const PPC_prep_io_read[] = {
B
bellard 已提交
544 545 546 547 548
    &PPC_prep_io_readb,
    &PPC_prep_io_readw,
    &PPC_prep_io_readl,
};

B
bellard 已提交
549
#define NVRAM_SIZE        0x2000
550

B
Blue Swirl 已提交
551 552 553 554 555 556 557 558 559
static void cpu_request_exit(void *opaque, int irq, int level)
{
    CPUState *env = cpu_single_env;

    if (env && level) {
        cpu_exit(env);
    }
}

560
/* PowerPC PREP hardware initialisation */
A
Anthony Liguori 已提交
561
static void ppc_prep_init (ram_addr_t ram_size,
562
                           const char *boot_device,
563
                           const char *kernel_filename,
564 565 566
                           const char *kernel_cmdline,
                           const char *initrd_filename,
                           const char *cpu_model)
567
{
B
Blue Swirl 已提交
568
    CPUState *env = NULL;
P
Paul Brook 已提交
569
    char *filename;
A
Anthony Liguori 已提交
570
    nvram_t nvram;
571
    M48t59State *m48t59;
572
    int PPC_io_memory;
B
bellard 已提交
573
    int linux_boot, i, nb_nics1, bios_size;
A
Anthony Liguori 已提交
574
    ram_addr_t ram_offset, bios_offset;
575 576
    uint32_t kernel_base, initrd_base;
    long kernel_size, initrd_size;
B
bellard 已提交
577
    PCIBus *pci_bus;
P
pbrook 已提交
578
    qemu_irq *i8259;
B
Blue Swirl 已提交
579
    qemu_irq *cpu_exit_irq;
580
    int ppc_boot_device;
581
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
G
Gerd Hoffmann 已提交
582
    DriveInfo *fd[MAX_FD];
B
bellard 已提交
583

A
Anthony Liguori 已提交
584
    sysctrl = qemu_mallocz(sizeof(sysctrl_t));
585 586

    linux_boot = (kernel_filename != NULL);
J
j_mayer 已提交
587

B
bellard 已提交
588
    /* init CPUs */
589
    if (cpu_model == NULL)
G
Gerd Hoffmann 已提交
590
        cpu_model = "602";
591
    for (i = 0; i < smp_cpus; i++) {
B
bellard 已提交
592 593 594 595 596
        env = cpu_init(cpu_model);
        if (!env) {
            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
            exit(1);
        }
597 598 599 600 601 602 603
        if (env->flags & POWERPC_FLAG_RTC_CLK) {
            /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
            cpu_ppc_tb_init(env, 7812500UL);
        } else {
            /* Set time-base frequency to 100 Mhz */
            cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
        }
604
        qemu_register_reset((QEMUResetHandler*)&cpu_reset, env);
605
    }
606 607

    /* allocate RAM */
608
    ram_offset = qemu_ram_alloc(NULL, "ppc_prep.ram", ram_size);
B
blueswir1 已提交
609 610
    cpu_register_physical_memory(0, ram_size, ram_offset);

B
bellard 已提交
611
    /* allocate and load BIOS */
612
    bios_offset = qemu_ram_alloc(NULL, "ppc_prep.bios", BIOS_SIZE);
613 614
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
P
Paul Brook 已提交
615 616 617 618 619 620
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = get_image_size(filename);
    } else {
        bios_size = -1;
    }
621
    if (bios_size > 0 && bios_size <= BIOS_SIZE) {
A
Anthony Liguori 已提交
622
        target_phys_addr_t bios_addr;
623 624 625 626
        bios_size = (bios_size + 0xfff) & ~0xfff;
        bios_addr = (uint32_t)(-bios_size);
        cpu_register_physical_memory(bios_addr, bios_size,
                                     bios_offset | IO_MEM_ROM);
P
Paul Brook 已提交
627
        bios_size = load_image_targphys(filename, bios_addr, bios_size);
628
    }
B
bellard 已提交
629
    if (bios_size < 0 || bios_size > BIOS_SIZE) {
P
Paul Brook 已提交
630 631 632 633
        hw_error("qemu: could not load PPC PREP bios '%s'\n", bios_name);
    }
    if (filename) {
        qemu_free(filename);
B
bellard 已提交
634
    }
635
    if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
P
Paul Brook 已提交
636
        hw_error("PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
637
    }
638

639
    if (linux_boot) {
B
bellard 已提交
640
        kernel_base = KERNEL_LOAD_ADDR;
641
        /* now we can load the kernel */
642 643
        kernel_size = load_image_targphys(kernel_filename, kernel_base,
                                          ram_size - kernel_base);
B
bellard 已提交
644
        if (kernel_size < 0) {
P
Paul Brook 已提交
645
            hw_error("qemu: could not load kernel '%s'\n", kernel_filename);
646 647 648 649
            exit(1);
        }
        /* load initrd */
        if (initrd_filename) {
B
bellard 已提交
650
            initrd_base = INITRD_LOAD_ADDR;
651 652
            initrd_size = load_image_targphys(initrd_filename, initrd_base,
                                              ram_size - initrd_base);
653
            if (initrd_size < 0) {
P
Paul Brook 已提交
654
                hw_error("qemu: could not load initial ram disk '%s'\n",
J
j_mayer 已提交
655
                          initrd_filename);
656
            }
B
bellard 已提交
657 658 659
        } else {
            initrd_base = 0;
            initrd_size = 0;
660
        }
661
        ppc_boot_device = 'm';
662
    } else {
B
bellard 已提交
663 664 665 666
        kernel_base = 0;
        kernel_size = 0;
        initrd_base = 0;
        initrd_size = 0;
667 668
        ppc_boot_device = '\0';
        /* For now, OHW cannot boot from the network. */
J
j_mayer 已提交
669 670 671
        for (i = 0; boot_device[i] != '\0'; i++) {
            if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {
                ppc_boot_device = boot_device[i];
672
                break;
J
j_mayer 已提交
673
            }
674 675 676 677 678
        }
        if (ppc_boot_device == '\0') {
            fprintf(stderr, "No valid boot device for Mac99 machine\n");
            exit(1);
        }
679 680
    }

B
bellard 已提交
681
    isa_mem_base = 0xc0000000;
682
    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
P
Paul Brook 已提交
683
        hw_error("Only 6xx bus is supported on PREP machine\n");
684
    }
685
    i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
P
pbrook 已提交
686
    pci_bus = pci_prep_init(i8259);
G
Gerd Hoffmann 已提交
687 688 689
    /* Hmm, prep has no pci-isa bridge ??? */
    isa_bus_new(NULL);
    isa_bus_irqs(i8259);
B
bellard 已提交
690 691
    //    pci_bus = i440fx_init();
    /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
692
    PPC_io_memory = cpu_register_io_memory(PPC_prep_io_read,
693 694
                                           PPC_prep_io_write, sysctrl,
                                           DEVICE_NATIVE_ENDIAN);
B
bellard 已提交
695
    cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
B
bellard 已提交
696

697
    /* init basic PC hardware */
G
Gerd Hoffmann 已提交
698
    pci_vga_init(pci_bus);
B
bellard 已提交
699
    //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
P
pbrook 已提交
700
    //    pit = pit_init(0x40, i8259[0]);
701
    rtc_init(2000, NULL);
702

G
Gerd Hoffmann 已提交
703 704
    if (serial_hds[0])
        serial_isa_init(0, serial_hds[0]);
705 706 707 708
    nb_nics1 = nb_nics;
    if (nb_nics1 > NE2000_NB_MAX)
        nb_nics1 = NE2000_NB_MAX;
    for(i = 0; i < nb_nics1; i++) {
709
        if (nd_table[i].model == NULL) {
710
	    nd_table[i].model = qemu_strdup("ne2k_isa");
711 712
        }
        if (strcmp(nd_table[i].model, "ne2k_isa") == 0) {
G
Gerd Hoffmann 已提交
713
            isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
714
        } else {
715
            pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
716
        }
717 718
    }

T
ths 已提交
719 720 721 722 723 724
    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++) {
725
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
T
ths 已提交
726 727 728
    }

    for(i = 0; i < MAX_IDE_BUS; i++) {
G
Gerd Hoffmann 已提交
729
        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
T
ths 已提交
730 731
                     hd[2 * i],
		     hd[2 * i + 1]);
732
    }
733
    isa_create_simple("i8042");
B
Blue Swirl 已提交
734 735 736 737

    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
    DMA_init(1, cpu_exit_irq);

738 739
    //    SB16_init();

T
ths 已提交
740
    for(i = 0; i < MAX_FD; i++) {
G
Gerd Hoffmann 已提交
741
        fd[i] = drive_get(IF_FLOPPY, 0, i);
T
ths 已提交
742
    }
743
    fdctrl_init_isa(fd);
744

B
bellard 已提交
745 746 747
    /* Register speaker port */
    register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
    register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
748
    /* Register fake IO ports for PREP */
J
j_mayer 已提交
749
    sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
B
bellard 已提交
750 751
    register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
    register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
752
    /* System control ports */
B
bellard 已提交
753 754 755 756 757
    register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
    register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
    register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
    register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
    /* PCI intack location */
758
    PPC_io_memory = cpu_register_io_memory(PPC_intack_read,
759 760
                                           PPC_intack_write, NULL,
                                           DEVICE_NATIVE_ENDIAN);
761
    cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
B
bellard 已提交
762
    /* PowerPC control and status register group */
B
bellard 已提交
763
#if 0
764
    PPC_io_memory = cpu_register_io_memory(PPC_XCSR_read, PPC_XCSR_write,
765
                                           NULL, DEVICE_NATIVE_ENDIAN);
B
bellard 已提交
766
    cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
B
bellard 已提交
767
#endif
768

P
pbrook 已提交
769
    if (usb_enabled) {
P
Paul Brook 已提交
770
        usb_ohci_init_pci(pci_bus, -1);
P
pbrook 已提交
771 772
    }

J
j_mayer 已提交
773 774
    m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
    if (m48t59 == NULL)
B
bellard 已提交
775
        return;
J
j_mayer 已提交
776
    sysctrl->nvram = m48t59;
B
bellard 已提交
777 778

    /* Initialise NVRAM */
J
j_mayer 已提交
779 780 781
    nvram.opaque = m48t59;
    nvram.read_fn = &m48t59_read;
    nvram.write_fn = &m48t59_write;
782
    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, ppc_boot_device,
B
bellard 已提交
783
                         kernel_base, kernel_size,
B
bellard 已提交
784
                         kernel_cmdline,
B
bellard 已提交
785 786
                         initrd_base, initrd_size,
                         /* XXX: need an option to load a NVRAM image */
B
bellard 已提交
787 788
                         0,
                         graphic_width, graphic_height, graphic_depth);
B
bellard 已提交
789 790 791

    /* Special port to get debug messages from Open-Firmware */
    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
792
}
B
bellard 已提交
793

794
static QEMUMachine prep_machine = {
795 796 797
    .name = "prep",
    .desc = "PowerPC PREP platform",
    .init = ppc_prep_init,
B
balrog 已提交
798
    .max_cpus = MAX_CPUS,
B
bellard 已提交
799
};
800 801 802 803 804 805 806

static void prep_machine_init(void)
{
    qemu_register_machine(&prep_machine);
}

machine_init(prep_machine_init);