ppc_prep.c 19.6 KB
Newer Older
1
/*
2 3
 * QEMU PPC PREP hardware System Emulator
 * 
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 24
 */
#include "vl.h"
25

26
//#define HARD_DEBUG_PPC_IO
27
//#define DEBUG_PPC_IO
28

B
bellard 已提交
29 30 31
#define BIOS_FILENAME "ppc_rom.bin"
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
B
bellard 已提交
32

33 34 35 36 37 38 39 40 41 42
extern int loglevel;
extern FILE *logfile;

#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
#define DEBUG_PPC_IO
#endif

#if defined (HARD_DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, args...)                     \
do {                                                     \
B
bellard 已提交
43
    if (loglevel & CPU_LOG_IOPORT) {                     \
44 45 46 47 48 49 50 51
        fprintf(logfile, "%s: " fmt, __func__ , ##args); \
    } else {                                             \
        printf("%s : " fmt, __func__ , ##args);          \
    }                                                    \
} while (0)
#elif defined (DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, args...)                     \
do {                                                     \
B
bellard 已提交
52
    if (loglevel & CPU_LOG_IOPORT) {                     \
53 54 55 56 57 58 59
        fprintf(logfile, "%s: " fmt, __func__ , ##args); \
    }                                                    \
} while (0)
#else
#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
#endif

B
bellard 已提交
60
/* Constants for devices init */
61 62 63 64 65 66 67 68
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 };
69

B
bellard 已提交
70 71 72
//static PITState *pit;

/* ISA IO ports bridge */
73 74
#define PPC_IO_BASE 0x80000000

B
bellard 已提交
75 76 77 78 79
/* Speaker port 0x61 */
int speaker_data_on;
int dummy_refresh_clock;

static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
80
{
81
#if 0
B
bellard 已提交
82 83
    speaker_data_on = (val >> 1) & 1;
    pit_set_gate(pit, 2, val & 1);
84
#endif
85 86
}

87
static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
88
{
89
#if 0
B
bellard 已提交
90 91 92 93
    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) |
94
        (dummy_refresh_clock << 4);
95
#endif
B
bellard 已提交
96
    return 0;
97 98
}

B
bellard 已提交
99 100
/* PCI intack register */
/* Read-only register (?) */
101 102
static void _PPC_intack_write (void *opaque,
                               target_phys_addr_t addr, uint32_t value)
B
bellard 已提交
103 104 105 106 107 108 109 110 111
{
    //    printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
}

static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
{
    uint32_t retval = 0;

    if (addr == 0xBFFFFFF0)
B
bellard 已提交
112
        retval = pic_intack_read(isa_pic);
B
bellard 已提交
113 114 115 116 117
       //   printf("%s: 0x%08x <= %d\n", __func__, addr, retval);

    return retval;
}

B
bellard 已提交
118
static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
119 120 121 122
{
    return _PPC_intack_read(addr);
}

B
bellard 已提交
123
static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
124
{
B
bellard 已提交
125
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
126 127 128
    return bswap16(_PPC_intack_read(addr));
#else
    return _PPC_intack_read(addr);
B
bellard 已提交
129
#endif
130 131
}

B
bellard 已提交
132
static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
133
{
B
bellard 已提交
134
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
135 136 137
    return bswap32(_PPC_intack_read(addr));
#else
    return _PPC_intack_read(addr);
B
bellard 已提交
138
#endif
139 140
}

B
bellard 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
static CPUWriteMemoryFunc *PPC_intack_write[] = {
    &_PPC_intack_write,
    &_PPC_intack_write,
    &_PPC_intack_write,
};

static CPUReadMemoryFunc *PPC_intack_read[] = {
    &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;

B
bellard 已提交
180
static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
B
bellard 已提交
181 182 183 184
{
    printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}

B
bellard 已提交
185
static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
186
{
B
bellard 已提交
187
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
188
    value = bswap16(value);
B
bellard 已提交
189
#endif
B
bellard 已提交
190
    printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
191 192
}

B
bellard 已提交
193
static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
194
{
B
bellard 已提交
195
#ifdef TARGET_WORDS_BIGENDIAN
B
bellard 已提交
196
    value = bswap32(value);
B
bellard 已提交
197
#endif
B
bellard 已提交
198
    printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
199 200
}

B
bellard 已提交
201
static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
B
bellard 已提交
202 203
{
    uint32_t retval = 0;
204

B
bellard 已提交
205
    printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
206

B
bellard 已提交
207 208 209
    return retval;
}

B
bellard 已提交
210
static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
211
{
B
bellard 已提交
212 213 214 215 216 217 218 219
    uint32_t retval = 0;

    printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
#ifdef TARGET_WORDS_BIGENDIAN
    retval = bswap16(retval);
#endif

    return retval;
220 221
}

B
bellard 已提交
222
static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
223 224 225
{
    uint32_t retval = 0;

B
bellard 已提交
226 227 228 229
    printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
#ifdef TARGET_WORDS_BIGENDIAN
    retval = bswap32(retval);
#endif
230 231 232 233

    return retval;
}

B
bellard 已提交
234 235 236 237
static CPUWriteMemoryFunc *PPC_XCSR_write[] = {
    &PPC_XCSR_writeb,
    &PPC_XCSR_writew,
    &PPC_XCSR_writel,
238 239
};

B
bellard 已提交
240 241 242 243
static CPUReadMemoryFunc *PPC_XCSR_read[] = {
    &PPC_XCSR_readb,
    &PPC_XCSR_readw,
    &PPC_XCSR_readl,
244
};
B
bellard 已提交
245
#endif
246

B
bellard 已提交
247 248 249 250 251 252
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
typedef struct sysctrl_t {
    m48t59_t *nvram;
    uint8_t state;
    uint8_t syscontrol;
    uint8_t fake_io[2];
B
bellard 已提交
253
    int contiguous_map;
B
bellard 已提交
254
    int endian;
B
bellard 已提交
255
} sysctrl_t;
256

B
bellard 已提交
257 258
enum {
    STATE_HARDFILE = 0x01,
259 260
};

B
bellard 已提交
261
static sysctrl_t *sysctrl;
262

263
static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
264
{
B
bellard 已提交
265 266 267 268
    sysctrl_t *sysctrl = opaque;

    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
    sysctrl->fake_io[addr - 0x0398] = val;
269 270
}

271
static uint32_t PREP_io_read (void *opaque, uint32_t addr)
272
{
B
bellard 已提交
273
    sysctrl_t *sysctrl = opaque;
274

B
bellard 已提交
275 276 277 278
    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
                   sysctrl->fake_io[addr - 0x0398]);
    return sysctrl->fake_io[addr - 0x0398];
}
279

280
static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
281
{
B
bellard 已提交
282 283 284
    sysctrl_t *sysctrl = opaque;

    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
285 286 287 288
    switch (addr) {
    case 0x0092:
        /* Special port 92 */
        /* Check soft reset asked */
B
bellard 已提交
289
        if (val & 0x01) {
290
            //            cpu_interrupt(first_cpu, PPC_INTERRUPT_RESET);
291 292
        }
        /* Check LE mode */
B
bellard 已提交
293
        if (val & 0x02) {
B
bellard 已提交
294 295 296
            sysctrl->endian = 1;
        } else {
            sysctrl->endian = 0;
297 298
        }
        break;
B
bellard 已提交
299 300 301 302 303 304 305 306 307
    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;
308
    case 0x0808:
B
bellard 已提交
309 310 311 312 313
        /* Hardfile light register */
        if (val & 1)
            sysctrl->state |= STATE_HARDFILE;
        else
            sysctrl->state &= ~STATE_HARDFILE;
314 315 316
        break;
    case 0x0810:
        /* Password protect 1 register */
B
bellard 已提交
317 318
        if (sysctrl->nvram != NULL)
            m48t59_toggle_lock(sysctrl->nvram, 1);
319 320 321
        break;
    case 0x0812:
        /* Password protect 2 register */
B
bellard 已提交
322 323
        if (sysctrl->nvram != NULL)
            m48t59_toggle_lock(sysctrl->nvram, 2);
324 325
        break;
    case 0x0814:
B
bellard 已提交
326
        /* L2 invalidate register */
B
bellard 已提交
327
        //        tlb_flush(first_cpu, 1);
328 329 330
        break;
    case 0x081C:
        /* system control register */
B
bellard 已提交
331
        sysctrl->syscontrol = val & 0x0F;
332 333 334
        break;
    case 0x0850:
        /* I/O map type register */
B
bellard 已提交
335
        sysctrl->contiguous_map = val & 0x01;
336 337
        break;
    default:
B
bellard 已提交
338 339
        printf("ERROR: unaffected IO port write: %04lx => %02x\n",
               (long)addr, val);
340 341 342 343
        break;
    }
}

344
static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
345
{
B
bellard 已提交
346
    sysctrl_t *sysctrl = opaque;
347 348 349 350 351
    uint32_t retval = 0xFF;

    switch (addr) {
    case 0x0092:
        /* Special port 92 */
B
bellard 已提交
352 353 354 355 356 357 358 359 360 361 362 363 364
        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 */
365 366 367 368 369 370 371 372
        break;
    case 0x080C:
        /* Equipment present register:
         *  no L2 cache
         *  no upgrade processor
         *  no cards in PCI slots
         *  SCSI fuse is bad
         */
B
bellard 已提交
373 374 375 376 377
        retval = 0x3C;
        break;
    case 0x0810:
        /* Motorola base module extended feature register */
        retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
378
        break;
B
bellard 已提交
379 380 381
    case 0x0814:
        /* L2 invalidate: don't care */
        break;
382 383 384 385 386 387 388 389
    case 0x0818:
        /* Keylock */
        retval = 0x00;
        break;
    case 0x081C:
        /* system control register
         * 7 - 6 / 1 - 0: L2 cache enable
         */
B
bellard 已提交
390
        retval = sysctrl->syscontrol;
391 392 393 394 395 396 397
        break;
    case 0x0823:
        /* */
        retval = 0x03; /* no L2 cache */
        break;
    case 0x0850:
        /* I/O map type register */
B
bellard 已提交
398
        retval = sysctrl->contiguous_map;
399 400
        break;
    default:
B
bellard 已提交
401
        printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
402 403
        break;
    }
B
bellard 已提交
404
    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
405 406 407 408

    return retval;
}

B
bellard 已提交
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
static inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl,
                                                  target_phys_addr_t addr)
{
    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;
}

static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr,
                                uint32_t value)
{
    sysctrl_t *sysctrl = opaque;

    addr = prep_IO_address(sysctrl, addr);
    cpu_outb(NULL, addr, value);
}

static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr)
{
    sysctrl_t *sysctrl = opaque;
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
    ret = cpu_inb(NULL, addr);

    return ret;
}

static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr,
                                uint32_t value)
{
    sysctrl_t *sysctrl = opaque;

    addr = prep_IO_address(sysctrl, addr);
#ifdef TARGET_WORDS_BIGENDIAN
    value = bswap16(value);
#endif
    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value);
    cpu_outw(NULL, addr, value);
}

static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
{
    sysctrl_t *sysctrl = opaque;
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
    ret = cpu_inw(NULL, addr);
#ifdef TARGET_WORDS_BIGENDIAN
    ret = bswap16(ret);
#endif
    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret);

    return ret;
}

static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr,
                                uint32_t value)
{
    sysctrl_t *sysctrl = opaque;

    addr = prep_IO_address(sysctrl, addr);
#ifdef TARGET_WORDS_BIGENDIAN
    value = bswap32(value);
#endif
    PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value);
    cpu_outl(NULL, addr, value);
}

static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
{
    sysctrl_t *sysctrl = opaque;
    uint32_t ret;

    addr = prep_IO_address(sysctrl, addr);
    ret = cpu_inl(NULL, addr);
#ifdef TARGET_WORDS_BIGENDIAN
    ret = bswap32(ret);
#endif
    PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret);

    return ret;
}

CPUWriteMemoryFunc *PPC_prep_io_write[] = {
    &PPC_prep_io_writeb,
    &PPC_prep_io_writew,
    &PPC_prep_io_writel,
};

CPUReadMemoryFunc *PPC_prep_io_read[] = {
    &PPC_prep_io_readb,
    &PPC_prep_io_readw,
    &PPC_prep_io_readl,
};

B
bellard 已提交
511
#define NVRAM_SIZE        0x2000
512

513
/* PowerPC PREP hardware initialisation */
514 515 516 517 518 519
static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
                           DisplayState *ds, const char **fd_filename,
                           int snapshot, const char *kernel_filename,
                           const char *kernel_cmdline,
                           const char *initrd_filename,
                           const char *cpu_model)
520
{
B
bellard 已提交
521
    CPUState *env;
522
    char buf[1024];
B
bellard 已提交
523
    m48t59_t *nvram;
524
    int PPC_io_memory;
B
bellard 已提交
525
    int linux_boot, i, nb_nics1, bios_size;
B
bellard 已提交
526 527
    unsigned long bios_offset;
    uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
528
    ppc_def_t *def;
B
bellard 已提交
529
    PCIBus *pci_bus;
P
pbrook 已提交
530
    qemu_irq *i8259;
B
bellard 已提交
531 532 533 534

    sysctrl = qemu_mallocz(sizeof(sysctrl_t));
    if (sysctrl == NULL)
	return;
535 536

    linux_boot = (kernel_filename != NULL);
B
bellard 已提交
537 538 539 540 541
    
    /* init CPUs */

    env = cpu_init();
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
542 543 544 545 546

    /* Default CPU is a 604 */
    if (cpu_model == NULL)
        cpu_model = "604";
    ppc_find_by_name(cpu_model, &def);
B
bellard 已提交
547 548 549 550 551 552
    if (def == NULL) {
        cpu_abort(env, "Unable to find PowerPC CPU definition\n");
    }
    cpu_ppc_register(env, def);
    /* Set time-base frequency to 100 Mhz */
    cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
553 554

    /* allocate RAM */
B
bellard 已提交
555 556 557 558 559
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    /* allocate and load BIOS */
    bios_offset = ram_size + vga_ram_size;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
B
bellard 已提交
560 561
    bios_size = load_image(buf, phys_ram_base + bios_offset);
    if (bios_size < 0 || bios_size > BIOS_SIZE) {
B
bellard 已提交
562 563 564
        fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
        exit(1);
    }
B
bellard 已提交
565 566 567
    bios_size = (bios_size + 0xfff) & ~0xfff;
    cpu_register_physical_memory((uint32_t)(-bios_size), 
                                 bios_size, bios_offset | IO_MEM_ROM);
568

569
    if (linux_boot) {
B
bellard 已提交
570
        kernel_base = KERNEL_LOAD_ADDR;
571
        /* now we can load the kernel */
B
bellard 已提交
572 573
        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
        if (kernel_size < 0) {
574 575 576 577 578 579
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
                    kernel_filename);
            exit(1);
        }
        /* load initrd */
        if (initrd_filename) {
B
bellard 已提交
580 581 582
            initrd_base = INITRD_LOAD_ADDR;
            initrd_size = load_image(initrd_filename,
                                     phys_ram_base + initrd_base);
583 584 585 586 587
            if (initrd_size < 0) {
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
                        initrd_filename);
                exit(1);
            }
B
bellard 已提交
588 589 590
        } else {
            initrd_base = 0;
            initrd_size = 0;
591
        }
B
bellard 已提交
592
        boot_device = 'm';
593
    } else {
B
bellard 已提交
594 595 596 597
        kernel_base = 0;
        kernel_size = 0;
        initrd_base = 0;
        initrd_size = 0;
598 599
    }

B
bellard 已提交
600
    isa_mem_base = 0xc0000000;
601 602 603 604
    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
        cpu_abort(env, "Only 6xx bus is supported on PREP machine\n");
        exit(1);
    }
605
    i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
P
pbrook 已提交
606
    pci_bus = pci_prep_init(i8259);
B
bellard 已提交
607 608 609 610 611
    //    pci_bus = i440fx_init();
    /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
    PPC_io_memory = cpu_register_io_memory(0, PPC_prep_io_read,
                                           PPC_prep_io_write, sysctrl);
    cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
B
bellard 已提交
612

613
    /* init basic PC hardware */
B
bellard 已提交
614 615
    pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
                 vga_ram_size, 0, 0);
B
bellard 已提交
616
    //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
P
pbrook 已提交
617 618
    //    pit = pit_init(0x40, i8259[0]);
    rtc_init(0x70, i8259[8]);
619

P
pbrook 已提交
620
    serial_init(0x3f8, i8259[4], serial_hds[0]);
621 622 623 624
    nb_nics1 = nb_nics;
    if (nb_nics1 > NE2000_NB_MAX)
        nb_nics1 = NE2000_NB_MAX;
    for(i = 0; i < nb_nics1; i++) {
625 626
        if (nd_table[0].model == NULL
            || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
P
pbrook 已提交
627
            isa_ne2000_init(ne2000_io[i], i8259[ne2000_irq[i]], &nd_table[i]);
628 629 630 631
        } else {
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
            exit (1);
        }
632 633 634
    }

    for(i = 0; i < 2; i++) {
P
pbrook 已提交
635
        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
B
bellard 已提交
636
                     bs_table[2 * i], bs_table[2 * i + 1]);
637
    }
P
pbrook 已提交
638
    i8042_init(i8259[1], i8259[12], 0x60);
B
bellard 已提交
639
    DMA_init(1);
B
bellard 已提交
640
    //    AUD_init();
641 642
    //    SB16_init();

P
pbrook 已提交
643
    fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table);
644

B
bellard 已提交
645 646 647
    /* Register speaker port */
    register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
    register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
648
    /* Register fake IO ports for PREP */
B
bellard 已提交
649 650
    register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
    register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
651
    /* System control ports */
B
bellard 已提交
652 653 654 655 656 657
    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 */
    PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read,
B
bellard 已提交
658
                                           PPC_intack_write, NULL);
659
    cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
B
bellard 已提交
660
    /* PowerPC control and status register group */
B
bellard 已提交
661
#if 0
B
bellard 已提交
662
    PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL);
B
bellard 已提交
663
    cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
B
bellard 已提交
664
#endif
665

P
pbrook 已提交
666
    if (usb_enabled) {
667
        usb_ohci_init_pci(pci_bus, 3, -1);
P
pbrook 已提交
668 669
    }

P
pbrook 已提交
670
    nvram = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
B
bellard 已提交
671 672 673 674 675 676 677
    if (nvram == NULL)
        return;
    sysctrl->nvram = nvram;

    /* Initialise NVRAM */
    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
                         kernel_base, kernel_size,
B
bellard 已提交
678
                         kernel_cmdline,
B
bellard 已提交
679 680
                         initrd_base, initrd_size,
                         /* XXX: need an option to load a NVRAM image */
B
bellard 已提交
681 682
                         0,
                         graphic_width, graphic_height, graphic_depth);
B
bellard 已提交
683 684 685

    /* Special port to get debug messages from Open-Firmware */
    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
686
}
B
bellard 已提交
687 688 689 690 691 692

QEMUMachine prep_machine = {
    "prep",
    "PowerPC PREP platform",
    ppc_prep_init,
};