2 * QEMU PPC CHRP/PMAC hardware System Emulator
4 * Copyright (c) 2004 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #define BIOS_FILENAME "ppc_rom.bin"
27 #define NVRAM_SIZE 0x2000
29 #define KERNEL_LOAD_ADDR 0x01000000
30 #define INITRD_LOAD_ADDR 0x01800000
32 /* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
33 NVRAM (not implemented). */
35 static int dbdma_mem_index
;
36 static int cuda_mem_index
;
37 static int ide0_mem_index
;
38 static int ide1_mem_index
;
39 static int openpic_mem_index
;
41 /* DBDMA: currently no op - should suffice right now */
43 static void dbdma_writeb (void *opaque
, target_phys_addr_t addr
, uint32_t value
)
45 printf("%s: 0x%08x <= 0x%08x\n", __func__
, addr
, value
);
48 static void dbdma_writew (void *opaque
, target_phys_addr_t addr
, uint32_t value
)
52 static void dbdma_writel (void *opaque
, target_phys_addr_t addr
, uint32_t value
)
56 static uint32_t dbdma_readb (void *opaque
, target_phys_addr_t addr
)
58 printf("%s: 0x%08x => 0x00000000\n", __func__
, addr
);
62 static uint32_t dbdma_readw (void *opaque
, target_phys_addr_t addr
)
67 static uint32_t dbdma_readl (void *opaque
, target_phys_addr_t addr
)
72 static CPUWriteMemoryFunc
*dbdma_write
[] = {
78 static CPUReadMemoryFunc
*dbdma_read
[] = {
84 static void macio_map(PCIDevice
*pci_dev
, int region_num
,
85 uint32_t addr
, uint32_t size
, int type
)
87 cpu_register_physical_memory(addr
+ 0x08000, 0x1000, dbdma_mem_index
);
88 cpu_register_physical_memory(addr
+ 0x16000, 0x2000, cuda_mem_index
);
89 cpu_register_physical_memory(addr
+ 0x1f000, 0x1000, ide0_mem_index
);
90 cpu_register_physical_memory(addr
+ 0x20000, 0x1000, ide1_mem_index
);
91 cpu_register_physical_memory(addr
+ 0x40000, 0x40000, openpic_mem_index
);
94 static void macio_init(PCIBus
*bus
)
98 d
= pci_register_device(bus
, "macio", sizeof(PCIDevice
),
100 /* Note: this code is strongly inspirated from the corresponding code
102 d
->config
[0x00] = 0x6b; // vendor_id
103 d
->config
[0x01] = 0x10;
104 d
->config
[0x02] = 0x22;
105 d
->config
[0x03] = 0x00;
107 d
->config
[0x0a] = 0x00; // class_sub = pci2pci
108 d
->config
[0x0b] = 0xff; // class_base = bridge
109 d
->config
[0x0e] = 0x00; // header_type
111 d
->config
[0x3d] = 0x01; // interrupt on pin 1
113 dbdma_mem_index
= cpu_register_io_memory(0, dbdma_read
, dbdma_write
, NULL
);
115 pci_register_io_region(d
, 0, 0x80000,
116 PCI_ADDRESS_SPACE_MEM
, macio_map
);
119 /* PowerPC PREP hardware initialisation */
120 void ppc_chrp_init(int ram_size
, int vga_ram_size
, int boot_device
,
121 DisplayState
*ds
, const char **fd_filename
, int snapshot
,
122 const char *kernel_filename
, const char *kernel_cmdline
,
123 const char *initrd_filename
)
129 int ret
, linux_boot
, i
;
130 unsigned long bios_offset
;
131 uint32_t kernel_base
, kernel_size
, initrd_base
, initrd_size
;
134 linux_boot
= (kernel_filename
!= NULL
);
137 cpu_register_physical_memory(0, ram_size
, IO_MEM_RAM
);
139 /* allocate and load BIOS */
140 bios_offset
= ram_size
+ vga_ram_size
;
141 snprintf(buf
, sizeof(buf
), "%s/%s", bios_dir
, BIOS_FILENAME
);
142 ret
= load_image(buf
, phys_ram_base
+ bios_offset
);
143 if (ret
!= BIOS_SIZE
) {
144 fprintf(stderr
, "qemu: could not load PPC PREP bios '%s'\n", buf
);
147 cpu_register_physical_memory((uint32_t)(-BIOS_SIZE
),
148 BIOS_SIZE
, bios_offset
| IO_MEM_ROM
);
149 cpu_single_env
->nip
= 0xfffffffc;
152 kernel_base
= KERNEL_LOAD_ADDR
;
153 /* now we can load the kernel */
154 kernel_size
= load_image(kernel_filename
, phys_ram_base
+ kernel_base
);
155 if (kernel_size
< 0) {
156 fprintf(stderr
, "qemu: could not load kernel '%s'\n",
161 if (initrd_filename
) {
162 initrd_base
= INITRD_LOAD_ADDR
;
163 initrd_size
= load_image(initrd_filename
,
164 phys_ram_base
+ initrd_base
);
165 if (initrd_size
< 0) {
166 fprintf(stderr
, "qemu: could not load initial ram disk '%s'\n",
181 /* Register CPU as a 74x/75x */
182 cpu_ppc_register(cpu_single_env
, 0x00080000);
183 /* Set time-base frequency to 100 Mhz */
184 cpu_ppc_tb_init(cpu_single_env
, 100UL * 1000UL * 1000UL);
186 isa_mem_base
= 0x80000000;
187 pci_bus
= pci_pmac_init();
189 /* Register 8 MB of ISA IO space */
190 PPC_io_memory
= cpu_register_io_memory(0, PPC_io_read
, PPC_io_write
, NULL
);
191 cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory
);
193 /* init basic PC hardware */
194 vga_initialize(pci_bus
, ds
, phys_ram_base
+ ram_size
, ram_size
,
196 openpic
= openpic_init(NULL
, &openpic_mem_index
, 1);
197 pci_pmac_set_openpic(pci_bus
, openpic
);
199 /* XXX: suppress that */
202 /* XXX: use Mac Serial port */
203 serial_init(0x3f8, 4, serial_hds
[0]);
205 for(i
= 0; i
< nb_nics
; i
++) {
206 pci_ne2000_init(pci_bus
, &nd_table
[i
]);
209 ide0_mem_index
= pmac_ide_init(&bs_table
[0], openpic
, 0x13);
210 ide1_mem_index
= pmac_ide_init(&bs_table
[2], openpic
, 0x14);
212 /* cuda also initialize ADB */
213 cuda_mem_index
= cuda_init(openpic
, 0x19);
215 adb_kbd_init(&adb_bus
);
216 adb_mouse_init(&adb_bus
);
220 nvram
= m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE
);
222 if (graphic_depth
!= 15 && graphic_depth
!= 32 && graphic_depth
!= 8)
225 PPC_NVRAM_set_params(nvram
, NVRAM_SIZE
, "CHRP", ram_size
, boot_device
,
226 kernel_base
, kernel_size
,
228 initrd_base
, initrd_size
,
229 /* XXX: need an option to load a NVRAM image */
231 graphic_width
, graphic_height
, graphic_depth
);
232 /* No PCI init: the BIOS will do it */