ppc_prep.c 21.9 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
Blue Swirl 已提交
85
//static ISADevice *pit;
B
bellard 已提交
86 87

/* 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
    return _PPC_intack_read(addr);
149 150
}

A
Anthony Liguori 已提交
151
static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
152
{
B
bellard 已提交
153
    return _PPC_intack_read(addr);
154 155
}

156
static CPUWriteMemoryFunc * const PPC_intack_write[] = {
B
bellard 已提交
157 158 159 160 161
    &_PPC_intack_write,
    &_PPC_intack_write,
    &_PPC_intack_write,
};

162
static CPUReadMemoryFunc * const PPC_intack_read[] = {
B
bellard 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
    &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;

195
static void PPC_XCSR_writeb (void *opaque,
A
Anthony Liguori 已提交
196
                             target_phys_addr_t addr, uint32_t value)
B
bellard 已提交
197
{
198 199
    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
           value);
B
bellard 已提交
200 201
}

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

209
static void PPC_XCSR_writel (void *opaque,
A
Anthony Liguori 已提交
210
                             target_phys_addr_t addr, uint32_t value)
211
{
212 213
    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
           value);
214 215
}

A
Anthony Liguori 已提交
216
static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
217 218
{
    uint32_t retval = 0;
219

220 221
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
222

B
bellard 已提交
223 224 225
    return retval;
}

A
Anthony Liguori 已提交
226
static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
227
{
B
bellard 已提交
228 229
    uint32_t retval = 0;

230 231
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
B
bellard 已提交
232 233

    return retval;
234 235
}

A
Anthony Liguori 已提交
236
static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
237 238 239
{
    uint32_t retval = 0;

240 241
    printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
           retval);
242 243 244 245

    return retval;
}

246
static CPUWriteMemoryFunc * const PPC_XCSR_write[] = {
B
bellard 已提交
247 248 249
    &PPC_XCSR_writeb,
    &PPC_XCSR_writew,
    &PPC_XCSR_writel,
250 251
};

252
static CPUReadMemoryFunc * const PPC_XCSR_read[] = {
B
bellard 已提交
253 254 255
    &PPC_XCSR_readb,
    &PPC_XCSR_readw,
    &PPC_XCSR_readl,
256
};
B
bellard 已提交
257
#endif
258

B
bellard 已提交
259
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
A
Anthony Liguori 已提交
260
typedef struct sysctrl_t {
J
j_mayer 已提交
261
    qemu_irq reset_irq;
262
    M48t59State *nvram;
B
bellard 已提交
263 264 265
    uint8_t state;
    uint8_t syscontrol;
    uint8_t fake_io[2];
B
bellard 已提交
266
    int contiguous_map;
B
bellard 已提交
267
    int endian;
A
Anthony Liguori 已提交
268
} sysctrl_t;
269

B
bellard 已提交
270 271
enum {
    STATE_HARDFILE = 0x01,
272 273
};

A
Anthony Liguori 已提交
274
static sysctrl_t *sysctrl;
275

276
static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
277
{
A
Anthony Liguori 已提交
278
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
279

280 281
    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
                   val);
B
bellard 已提交
282
    sysctrl->fake_io[addr - 0x0398] = val;
283 284
}

285
static uint32_t PREP_io_read (void *opaque, uint32_t addr)
286
{
A
Anthony Liguori 已提交
287
    sysctrl_t *sysctrl = opaque;
288

289
    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
B
bellard 已提交
290 291 292
                   sysctrl->fake_io[addr - 0x0398]);
    return sysctrl->fake_io[addr - 0x0398];
}
293

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

298 299
    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n",
                   addr - PPC_IO_BASE, val);
300 301 302 303
    switch (addr) {
    case 0x0092:
        /* Special port 92 */
        /* Check soft reset asked */
B
bellard 已提交
304
        if (val & 0x01) {
J
j_mayer 已提交
305 306 307
            qemu_irq_raise(sysctrl->reset_irq);
        } else {
            qemu_irq_lower(sysctrl->reset_irq);
308 309
        }
        /* Check LE mode */
B
bellard 已提交
310
        if (val & 0x02) {
B
bellard 已提交
311 312 313
            sysctrl->endian = 1;
        } else {
            sysctrl->endian = 0;
314 315
        }
        break;
B
bellard 已提交
316 317 318 319 320 321 322 323 324
    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;
325
    case 0x0808:
B
bellard 已提交
326 327 328 329 330
        /* Hardfile light register */
        if (val & 1)
            sysctrl->state |= STATE_HARDFILE;
        else
            sysctrl->state &= ~STATE_HARDFILE;
331 332 333
        break;
    case 0x0810:
        /* Password protect 1 register */
B
bellard 已提交
334 335
        if (sysctrl->nvram != NULL)
            m48t59_toggle_lock(sysctrl->nvram, 1);
336 337 338
        break;
    case 0x0812:
        /* Password protect 2 register */
B
bellard 已提交
339 340
        if (sysctrl->nvram != NULL)
            m48t59_toggle_lock(sysctrl->nvram, 2);
341 342
        break;
    case 0x0814:
B
bellard 已提交
343
        /* L2 invalidate register */
B
bellard 已提交
344
        //        tlb_flush(first_cpu, 1);
345 346 347
        break;
    case 0x081C:
        /* system control register */
B
bellard 已提交
348
        sysctrl->syscontrol = val & 0x0F;
349 350 351
        break;
    case 0x0850:
        /* I/O map type register */
B
bellard 已提交
352
        sysctrl->contiguous_map = val & 0x01;
353 354
        break;
    default:
355 356
        printf("ERROR: unaffected IO port write: %04" PRIx32
               " => %02" PRIx32"\n", addr, val);
357 358 359 360
        break;
    }
}

361
static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
362
{
A
Anthony Liguori 已提交
363
    sysctrl_t *sysctrl = opaque;
364 365 366 367 368
    uint32_t retval = 0xFF;

    switch (addr) {
    case 0x0092:
        /* Special port 92 */
B
bellard 已提交
369 370 371 372 373 374 375 376 377 378 379 380 381
        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 */
382 383 384 385 386 387 388 389
        break;
    case 0x080C:
        /* Equipment present register:
         *  no L2 cache
         *  no upgrade processor
         *  no cards in PCI slots
         *  SCSI fuse is bad
         */
B
bellard 已提交
390 391 392 393 394
        retval = 0x3C;
        break;
    case 0x0810:
        /* Motorola base module extended feature register */
        retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
395
        break;
B
bellard 已提交
396 397 398
    case 0x0814:
        /* L2 invalidate: don't care */
        break;
399 400 401 402 403 404 405 406
    case 0x0818:
        /* Keylock */
        retval = 0x00;
        break;
    case 0x081C:
        /* system control register
         * 7 - 6 / 1 - 0: L2 cache enable
         */
B
bellard 已提交
407
        retval = sysctrl->syscontrol;
408 409 410 411 412 413 414
        break;
    case 0x0823:
        /* */
        retval = 0x03; /* no L2 cache */
        break;
    case 0x0850:
        /* I/O map type register */
B
bellard 已提交
415
        retval = sysctrl->contiguous_map;
416 417
        break;
    default:
418
        printf("ERROR: unaffected IO port: %04" PRIx32 " read\n", addr);
419 420
        break;
    }
421 422
    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n",
                   addr - PPC_IO_BASE, retval);
423 424 425 426

    return retval;
}

A
Anthony Liguori 已提交
427 428
static inline target_phys_addr_t prep_IO_address(sysctrl_t *sysctrl,
                                                 target_phys_addr_t addr)
B
bellard 已提交
429 430 431 432 433 434 435 436 437 438 439 440
{
    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 已提交
441
static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr,
B
bellard 已提交
442 443
                                uint32_t value)
{
A
Anthony Liguori 已提交
444
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
445 446

    addr = prep_IO_address(sysctrl, addr);
447
    cpu_outb(addr, value);
B
bellard 已提交
448 449
}

A
Anthony Liguori 已提交
450
static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
451
{
A
Anthony Liguori 已提交
452
    sysctrl_t *sysctrl = opaque;
B
bellard 已提交
453 454 455
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
456
    ret = cpu_inb(addr);
B
bellard 已提交
457 458 459 460

    return ret;
}

A
Anthony Liguori 已提交
461
static void PPC_prep_io_writew (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
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
468
    cpu_outw(addr, value);
B
bellard 已提交
469 470
}

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

    addr = prep_IO_address(sysctrl, addr);
477
    ret = cpu_inw(addr);
478
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
B
bellard 已提交
479 480 481 482

    return ret;
}

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

    addr = prep_IO_address(sysctrl, addr);
489
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
490
    cpu_outl(addr, value);
B
bellard 已提交
491 492
}

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

    addr = prep_IO_address(sysctrl, addr);
499
    ret = cpu_inl(addr);
500
    PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
B
bellard 已提交
501 502 503 504

    return ret;
}

505
static CPUWriteMemoryFunc * const PPC_prep_io_write[] = {
B
bellard 已提交
506 507 508 509 510
    &PPC_prep_io_writeb,
    &PPC_prep_io_writew,
    &PPC_prep_io_writel,
};

511
static CPUReadMemoryFunc * const PPC_prep_io_read[] = {
B
bellard 已提交
512 513 514 515 516
    &PPC_prep_io_readb,
    &PPC_prep_io_readw,
    &PPC_prep_io_readl,
};

B
bellard 已提交
517
#define NVRAM_SIZE        0x2000
518

B
Blue Swirl 已提交
519 520 521 522 523 524 525 526 527
static void cpu_request_exit(void *opaque, int irq, int level)
{
    CPUState *env = cpu_single_env;

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

528
/* PowerPC PREP hardware initialisation */
A
Anthony Liguori 已提交
529
static void ppc_prep_init (ram_addr_t ram_size,
530
                           const char *boot_device,
531
                           const char *kernel_filename,
532 533 534
                           const char *kernel_cmdline,
                           const char *initrd_filename,
                           const char *cpu_model)
535
{
B
Blue Swirl 已提交
536
    CPUState *env = NULL;
P
Paul Brook 已提交
537
    char *filename;
A
Anthony Liguori 已提交
538
    nvram_t nvram;
539
    M48t59State *m48t59;
540
    int PPC_io_memory;
B
bellard 已提交
541
    int linux_boot, i, nb_nics1, bios_size;
A
Anthony Liguori 已提交
542
    ram_addr_t ram_offset, bios_offset;
543 544
    uint32_t kernel_base, initrd_base;
    long kernel_size, initrd_size;
B
bellard 已提交
545
    PCIBus *pci_bus;
P
pbrook 已提交
546
    qemu_irq *i8259;
B
Blue Swirl 已提交
547
    qemu_irq *cpu_exit_irq;
548
    int ppc_boot_device;
549
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
G
Gerd Hoffmann 已提交
550
    DriveInfo *fd[MAX_FD];
B
bellard 已提交
551

A
Anthony Liguori 已提交
552
    sysctrl = qemu_mallocz(sizeof(sysctrl_t));
553 554

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

B
bellard 已提交
556
    /* init CPUs */
557
    if (cpu_model == NULL)
G
Gerd Hoffmann 已提交
558
        cpu_model = "602";
559
    for (i = 0; i < smp_cpus; i++) {
B
bellard 已提交
560 561 562 563 564
        env = cpu_init(cpu_model);
        if (!env) {
            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
            exit(1);
        }
565 566 567 568 569 570 571
        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);
        }
572
        qemu_register_reset((QEMUResetHandler*)&cpu_reset, env);
573
    }
574 575

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

B
bellard 已提交
579
    /* allocate and load BIOS */
580
    bios_offset = qemu_ram_alloc(NULL, "ppc_prep.bios", BIOS_SIZE);
581 582
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
P
Paul Brook 已提交
583 584 585 586 587 588
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = get_image_size(filename);
    } else {
        bios_size = -1;
    }
589
    if (bios_size > 0 && bios_size <= BIOS_SIZE) {
A
Anthony Liguori 已提交
590
        target_phys_addr_t bios_addr;
591 592 593 594
        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 已提交
595
        bios_size = load_image_targphys(filename, bios_addr, bios_size);
596
    }
B
bellard 已提交
597
    if (bios_size < 0 || bios_size > BIOS_SIZE) {
P
Paul Brook 已提交
598 599 600 601
        hw_error("qemu: could not load PPC PREP bios '%s'\n", bios_name);
    }
    if (filename) {
        qemu_free(filename);
B
bellard 已提交
602
    }
603

604
    if (linux_boot) {
B
bellard 已提交
605
        kernel_base = KERNEL_LOAD_ADDR;
606
        /* now we can load the kernel */
607 608
        kernel_size = load_image_targphys(kernel_filename, kernel_base,
                                          ram_size - kernel_base);
B
bellard 已提交
609
        if (kernel_size < 0) {
P
Paul Brook 已提交
610
            hw_error("qemu: could not load kernel '%s'\n", kernel_filename);
611 612 613 614
            exit(1);
        }
        /* load initrd */
        if (initrd_filename) {
B
bellard 已提交
615
            initrd_base = INITRD_LOAD_ADDR;
616 617
            initrd_size = load_image_targphys(initrd_filename, initrd_base,
                                              ram_size - initrd_base);
618
            if (initrd_size < 0) {
P
Paul Brook 已提交
619
                hw_error("qemu: could not load initial ram disk '%s'\n",
J
j_mayer 已提交
620
                          initrd_filename);
621
            }
B
bellard 已提交
622 623 624
        } else {
            initrd_base = 0;
            initrd_size = 0;
625
        }
626
        ppc_boot_device = 'm';
627
    } else {
B
bellard 已提交
628 629 630 631
        kernel_base = 0;
        kernel_size = 0;
        initrd_base = 0;
        initrd_size = 0;
632 633
        ppc_boot_device = '\0';
        /* For now, OHW cannot boot from the network. */
J
j_mayer 已提交
634 635 636
        for (i = 0; boot_device[i] != '\0'; i++) {
            if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {
                ppc_boot_device = boot_device[i];
637
                break;
J
j_mayer 已提交
638
            }
639 640 641 642 643
        }
        if (ppc_boot_device == '\0') {
            fprintf(stderr, "No valid boot device for Mac99 machine\n");
            exit(1);
        }
644 645
    }

B
bellard 已提交
646
    isa_mem_base = 0xc0000000;
647
    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
P
Paul Brook 已提交
648
        hw_error("Only 6xx bus is supported on PREP machine\n");
649
    }
650
    i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
P
pbrook 已提交
651
    pci_bus = pci_prep_init(i8259);
G
Gerd Hoffmann 已提交
652 653 654
    /* Hmm, prep has no pci-isa bridge ??? */
    isa_bus_new(NULL);
    isa_bus_irqs(i8259);
B
bellard 已提交
655 656
    //    pci_bus = i440fx_init();
    /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
657
    PPC_io_memory = cpu_register_io_memory(PPC_prep_io_read,
658
                                           PPC_prep_io_write, sysctrl,
A
Alexander Graf 已提交
659
                                           DEVICE_LITTLE_ENDIAN);
B
bellard 已提交
660
    cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
B
bellard 已提交
661

662
    /* init basic PC hardware */
G
Gerd Hoffmann 已提交
663
    pci_vga_init(pci_bus);
B
bellard 已提交
664
    //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
B
Blue Swirl 已提交
665
    //    pit = pit_init(0x40, 0);
666
    rtc_init(2000, NULL);
667

G
Gerd Hoffmann 已提交
668 669
    if (serial_hds[0])
        serial_isa_init(0, serial_hds[0]);
670 671 672 673
    nb_nics1 = nb_nics;
    if (nb_nics1 > NE2000_NB_MAX)
        nb_nics1 = NE2000_NB_MAX;
    for(i = 0; i < nb_nics1; i++) {
674
        if (nd_table[i].model == NULL) {
675
	    nd_table[i].model = qemu_strdup("ne2k_isa");
676 677
        }
        if (strcmp(nd_table[i].model, "ne2k_isa") == 0) {
G
Gerd Hoffmann 已提交
678
            isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
679
        } else {
680
            pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
681
        }
682 683
    }

T
ths 已提交
684 685 686 687 688 689
    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++) {
690
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
T
ths 已提交
691 692
    }

693
    for(i = 0; i < MAX_IDE_BUS; i++) {
G
Gerd Hoffmann 已提交
694
        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
T
ths 已提交
695 696
                     hd[2 * i],
		     hd[2 * i + 1]);
697
    }
698
    isa_create_simple("i8042");
B
Blue Swirl 已提交
699 700 701 702

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

703 704
    //    SB16_init();

T
ths 已提交
705
    for(i = 0; i < MAX_FD; i++) {
G
Gerd Hoffmann 已提交
706
        fd[i] = drive_get(IF_FLOPPY, 0, i);
T
ths 已提交
707
    }
708
    fdctrl_init_isa(fd);
709

B
bellard 已提交
710 711 712
    /* Register speaker port */
    register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
    register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
713
    /* Register fake IO ports for PREP */
J
j_mayer 已提交
714
    sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
B
bellard 已提交
715 716
    register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
    register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
717
    /* System control ports */
B
bellard 已提交
718 719 720 721 722
    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 */
723
    PPC_io_memory = cpu_register_io_memory(PPC_intack_read,
724
                                           PPC_intack_write, NULL,
A
Alexander Graf 已提交
725
                                           DEVICE_LITTLE_ENDIAN);
726
    cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
B
bellard 已提交
727
    /* PowerPC control and status register group */
B
bellard 已提交
728
#if 0
729
    PPC_io_memory = cpu_register_io_memory(PPC_XCSR_read, PPC_XCSR_write,
A
Alexander Graf 已提交
730
                                           NULL, DEVICE_LITTLE_ENDIAN);
B
bellard 已提交
731
    cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
B
bellard 已提交
732
#endif
733

P
pbrook 已提交
734
    if (usb_enabled) {
P
Paul Brook 已提交
735
        usb_ohci_init_pci(pci_bus, -1);
P
pbrook 已提交
736 737
    }

J
j_mayer 已提交
738 739
    m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
    if (m48t59 == NULL)
B
bellard 已提交
740
        return;
J
j_mayer 已提交
741
    sysctrl->nvram = m48t59;
B
bellard 已提交
742 743

    /* Initialise NVRAM */
J
j_mayer 已提交
744 745 746
    nvram.opaque = m48t59;
    nvram.read_fn = &m48t59_read;
    nvram.write_fn = &m48t59_write;
747
    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, ppc_boot_device,
B
bellard 已提交
748
                         kernel_base, kernel_size,
B
bellard 已提交
749
                         kernel_cmdline,
B
bellard 已提交
750 751
                         initrd_base, initrd_size,
                         /* XXX: need an option to load a NVRAM image */
B
bellard 已提交
752 753
                         0,
                         graphic_width, graphic_height, graphic_depth);
B
bellard 已提交
754 755 756

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

759
static QEMUMachine prep_machine = {
760 761 762
    .name = "prep",
    .desc = "PowerPC PREP platform",
    .init = ppc_prep_init,
B
balrog 已提交
763
    .max_cpus = MAX_CPUS,
B
bellard 已提交
764
};
765 766 767 768 769 770 771

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

machine_init(prep_machine_init);