kvm: build: Make "make sync" get correct header files with latest Linux source
[kvm-userspace.git] / qemu / hw / ppc4xx_devs.c
blob80baf308b677d14c5b8c1680c238b93fde820641
1 /*
2 * QEMU PowerPC 4xx embedded processors shared devices emulation
4 * Copyright (c) 2007 Jocelyn Mayer
6 * Copyright 2008 IBM Corp.
7 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
27 #include "hw.h"
28 #include "ppc.h"
29 #include "ppc4xx.h"
30 #include "sysemu.h"
31 #include "pci.h"
32 #include "bswap.h"
34 extern int loglevel;
35 extern FILE *logfile;
37 //#define DEBUG_MMIO
38 //#define DEBUG_UNASSIGNED
39 #define DEBUG_UIC
41 /*****************************************************************************/
42 /* Generic PowerPC 4xx processor instanciation */
43 CPUState *ppc4xx_init (const unsigned char *cpu_model,
44 clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
45 uint32_t sysclk)
47 CPUState *env;
49 /* init CPUs */
50 env = cpu_init(cpu_model);
51 if (!env) {
52 fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
53 cpu_model);
54 exit(1);
56 cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
57 cpu_clk->opaque = env;
58 /* Set time-base frequency to sysclk */
59 tb_clk->cb = ppc_emb_timers_init(env, sysclk);
60 tb_clk->opaque = env;
61 ppc_dcr_init(env, NULL, NULL);
62 /* Register qemu callbacks */
63 qemu_register_reset(&cpu_ppc_reset, env);
65 return env;
68 /*****************************************************************************/
69 /* Fake device used to map multiple devices in a single memory page */
70 #define MMIO_AREA_BITS 8
71 #define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
72 #define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
73 #define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
74 struct ppc4xx_mmio_t {
75 target_phys_addr_t base;
76 CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
77 CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
78 void *opaque[MMIO_AREA_NB];
81 static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
83 #ifdef DEBUG_UNASSIGNED
84 ppc4xx_mmio_t *mmio;
86 mmio = opaque;
87 printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
88 addr, mmio->base);
89 #endif
91 return 0;
94 static void unassigned_mmio_writeb (void *opaque,
95 target_phys_addr_t addr, uint32_t val)
97 #ifdef DEBUG_UNASSIGNED
98 ppc4xx_mmio_t *mmio;
100 mmio = opaque;
101 printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
102 addr, val, mmio->base);
103 #endif
106 static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
107 unassigned_mmio_readb,
108 unassigned_mmio_readb,
109 unassigned_mmio_readb,
112 static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
113 unassigned_mmio_writeb,
114 unassigned_mmio_writeb,
115 unassigned_mmio_writeb,
118 static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
119 target_phys_addr_t addr, int len)
121 CPUReadMemoryFunc **mem_read;
122 uint32_t ret;
123 int idx;
125 idx = MMIO_IDX(addr - mmio->base);
126 #if defined(DEBUG_MMIO)
127 printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
128 mmio, len, addr, idx);
129 #endif
130 mem_read = mmio->mem_read[idx];
131 ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
133 return ret;
136 static void mmio_writelen (ppc4xx_mmio_t *mmio,
137 target_phys_addr_t addr, uint32_t value, int len)
139 CPUWriteMemoryFunc **mem_write;
140 int idx;
142 idx = MMIO_IDX(addr - mmio->base);
143 #if defined(DEBUG_MMIO)
144 printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08" PRIx32 "\n",
145 __func__, mmio, len, addr, idx, value);
146 #endif
147 mem_write = mmio->mem_write[idx];
148 (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
151 static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
153 #if defined(DEBUG_MMIO)
154 printf("%s: addr " PADDRX "\n", __func__, addr);
155 #endif
157 return mmio_readlen(opaque, addr, 0);
160 static void mmio_writeb (void *opaque,
161 target_phys_addr_t addr, uint32_t value)
163 #if defined(DEBUG_MMIO)
164 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
165 #endif
166 mmio_writelen(opaque, addr, value, 0);
169 static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
171 #if defined(DEBUG_MMIO)
172 printf("%s: addr " PADDRX "\n", __func__, addr);
173 #endif
175 return mmio_readlen(opaque, addr, 1);
178 static void mmio_writew (void *opaque,
179 target_phys_addr_t addr, uint32_t value)
181 #if defined(DEBUG_MMIO)
182 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
183 #endif
184 mmio_writelen(opaque, addr, value, 1);
187 static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
189 #if defined(DEBUG_MMIO)
190 printf("%s: addr " PADDRX "\n", __func__, addr);
191 #endif
193 return mmio_readlen(opaque, addr, 2);
196 static void mmio_writel (void *opaque,
197 target_phys_addr_t addr, uint32_t value)
199 #if defined(DEBUG_MMIO)
200 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
201 #endif
202 mmio_writelen(opaque, addr, value, 2);
205 static CPUReadMemoryFunc *mmio_read[] = {
206 &mmio_readb,
207 &mmio_readw,
208 &mmio_readl,
211 static CPUWriteMemoryFunc *mmio_write[] = {
212 &mmio_writeb,
213 &mmio_writew,
214 &mmio_writel,
217 int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
218 target_phys_addr_t offset, uint32_t len,
219 CPUReadMemoryFunc **mem_read,
220 CPUWriteMemoryFunc **mem_write, void *opaque)
222 target_phys_addr_t end;
223 int idx, eidx;
225 if ((offset + len) > TARGET_PAGE_SIZE)
226 return -1;
227 idx = MMIO_IDX(offset);
228 end = offset + len - 1;
229 eidx = MMIO_IDX(end);
230 #if defined(DEBUG_MMIO)
231 printf("%s: offset " PADDRX " len %08" PRIx32 " " PADDRX " %d %d\n",
232 __func__, offset, len, end, idx, eidx);
233 #endif
234 for (; idx <= eidx; idx++) {
235 mmio->mem_read[idx] = mem_read;
236 mmio->mem_write[idx] = mem_write;
237 mmio->opaque[idx] = opaque;
240 return 0;
243 ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
245 ppc4xx_mmio_t *mmio;
246 int mmio_memory;
248 mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
249 if (mmio != NULL) {
250 mmio->base = base;
251 mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
252 #if defined(DEBUG_MMIO)
253 printf("%s: base " PADDRX " len %08x %d\n", __func__,
254 base, TARGET_PAGE_SIZE, mmio_memory);
255 #endif
256 cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
257 ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
258 unassigned_mmio_read, unassigned_mmio_write,
259 mmio);
262 return mmio;
265 /*****************************************************************************/
266 /* "Universal" Interrupt controller */
267 enum {
268 DCR_UICSR = 0x000,
269 DCR_UICSRS = 0x001,
270 DCR_UICER = 0x002,
271 DCR_UICCR = 0x003,
272 DCR_UICPR = 0x004,
273 DCR_UICTR = 0x005,
274 DCR_UICMSR = 0x006,
275 DCR_UICVR = 0x007,
276 DCR_UICVCR = 0x008,
277 DCR_UICMAX = 0x009,
280 #define UIC_MAX_IRQ 32
281 typedef struct ppcuic_t ppcuic_t;
282 struct ppcuic_t {
283 uint32_t dcr_base;
284 int use_vectors;
285 uint32_t level; /* Remembers the state of level-triggered interrupts. */
286 uint32_t uicsr; /* Status register */
287 uint32_t uicer; /* Enable register */
288 uint32_t uiccr; /* Critical register */
289 uint32_t uicpr; /* Polarity register */
290 uint32_t uictr; /* Triggering register */
291 uint32_t uicvcr; /* Vector configuration register */
292 uint32_t uicvr;
293 qemu_irq *irqs;
296 static void ppcuic_trigger_irq (ppcuic_t *uic)
298 uint32_t ir, cr;
299 int start, end, inc, i;
301 /* Trigger interrupt if any is pending */
302 ir = uic->uicsr & uic->uicer & (~uic->uiccr);
303 cr = uic->uicsr & uic->uicer & uic->uiccr;
304 #ifdef DEBUG_UIC
305 if (loglevel & CPU_LOG_INT) {
306 fprintf(logfile, "%s: uicsr %08" PRIx32 " uicer %08" PRIx32
307 " uiccr %08" PRIx32 "\n"
308 " %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
309 __func__, uic->uicsr, uic->uicer, uic->uiccr,
310 uic->uicsr & uic->uicer, ir, cr);
312 #endif
313 if (ir != 0x0000000) {
314 #ifdef DEBUG_UIC
315 if (loglevel & CPU_LOG_INT) {
316 fprintf(logfile, "Raise UIC interrupt\n");
318 #endif
319 qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
320 } else {
321 #ifdef DEBUG_UIC
322 if (loglevel & CPU_LOG_INT) {
323 fprintf(logfile, "Lower UIC interrupt\n");
325 #endif
326 qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
328 /* Trigger critical interrupt if any is pending and update vector */
329 if (cr != 0x0000000) {
330 qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
331 if (uic->use_vectors) {
332 /* Compute critical IRQ vector */
333 if (uic->uicvcr & 1) {
334 start = 31;
335 end = 0;
336 inc = -1;
337 } else {
338 start = 0;
339 end = 31;
340 inc = 1;
342 uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
343 for (i = start; i <= end; i += inc) {
344 if (cr & (1 << i)) {
345 uic->uicvr += (i - start) * 512 * inc;
346 break;
350 #ifdef DEBUG_UIC
351 if (loglevel & CPU_LOG_INT) {
352 fprintf(logfile, "Raise UIC critical interrupt - "
353 "vector %08" PRIx32 "\n", uic->uicvr);
355 #endif
356 } else {
357 #ifdef DEBUG_UIC
358 if (loglevel & CPU_LOG_INT) {
359 fprintf(logfile, "Lower UIC critical interrupt\n");
361 #endif
362 qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
363 uic->uicvr = 0x00000000;
367 static void ppcuic_set_irq (void *opaque, int irq_num, int level)
369 ppcuic_t *uic;
370 uint32_t mask, sr;
372 uic = opaque;
373 mask = 1 << (31-irq_num);
374 #ifdef DEBUG_UIC
375 if (loglevel & CPU_LOG_INT) {
376 fprintf(logfile, "%s: irq %d level %d uicsr %08" PRIx32
377 " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
378 __func__, irq_num, level,
379 uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
381 #endif
382 if (irq_num < 0 || irq_num > 31)
383 return;
384 sr = uic->uicsr;
386 /* Update status register */
387 if (uic->uictr & mask) {
388 /* Edge sensitive interrupt */
389 if (level == 1)
390 uic->uicsr |= mask;
391 } else {
392 /* Level sensitive interrupt */
393 if (level == 1) {
394 uic->uicsr |= mask;
395 uic->level |= mask;
396 } else {
397 uic->uicsr &= ~mask;
398 uic->level &= ~mask;
401 #ifdef DEBUG_UIC
402 if (loglevel & CPU_LOG_INT) {
403 fprintf(logfile, "%s: irq %d level %d sr %" PRIx32 " => "
404 "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
406 #endif
407 if (sr != uic->uicsr)
408 ppcuic_trigger_irq(uic);
411 static target_ulong dcr_read_uic (void *opaque, int dcrn)
413 ppcuic_t *uic;
414 target_ulong ret;
416 uic = opaque;
417 dcrn -= uic->dcr_base;
418 switch (dcrn) {
419 case DCR_UICSR:
420 case DCR_UICSRS:
421 ret = uic->uicsr;
422 break;
423 case DCR_UICER:
424 ret = uic->uicer;
425 break;
426 case DCR_UICCR:
427 ret = uic->uiccr;
428 break;
429 case DCR_UICPR:
430 ret = uic->uicpr;
431 break;
432 case DCR_UICTR:
433 ret = uic->uictr;
434 break;
435 case DCR_UICMSR:
436 ret = uic->uicsr & uic->uicer;
437 break;
438 case DCR_UICVR:
439 if (!uic->use_vectors)
440 goto no_read;
441 ret = uic->uicvr;
442 break;
443 case DCR_UICVCR:
444 if (!uic->use_vectors)
445 goto no_read;
446 ret = uic->uicvcr;
447 break;
448 default:
449 no_read:
450 ret = 0x00000000;
451 break;
454 return ret;
457 static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
459 ppcuic_t *uic;
461 uic = opaque;
462 dcrn -= uic->dcr_base;
463 #ifdef DEBUG_UIC
464 if (loglevel & CPU_LOG_INT) {
465 fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
467 #endif
468 switch (dcrn) {
469 case DCR_UICSR:
470 uic->uicsr &= ~val;
471 uic->uicsr |= uic->level;
472 ppcuic_trigger_irq(uic);
473 break;
474 case DCR_UICSRS:
475 uic->uicsr |= val;
476 ppcuic_trigger_irq(uic);
477 break;
478 case DCR_UICER:
479 uic->uicer = val;
480 ppcuic_trigger_irq(uic);
481 break;
482 case DCR_UICCR:
483 uic->uiccr = val;
484 ppcuic_trigger_irq(uic);
485 break;
486 case DCR_UICPR:
487 uic->uicpr = val;
488 break;
489 case DCR_UICTR:
490 uic->uictr = val;
491 ppcuic_trigger_irq(uic);
492 break;
493 case DCR_UICMSR:
494 break;
495 case DCR_UICVR:
496 break;
497 case DCR_UICVCR:
498 uic->uicvcr = val & 0xFFFFFFFD;
499 ppcuic_trigger_irq(uic);
500 break;
504 static void ppcuic_reset (void *opaque)
506 ppcuic_t *uic;
508 uic = opaque;
509 uic->uiccr = 0x00000000;
510 uic->uicer = 0x00000000;
511 uic->uicpr = 0x00000000;
512 uic->uicsr = 0x00000000;
513 uic->uictr = 0x00000000;
514 if (uic->use_vectors) {
515 uic->uicvcr = 0x00000000;
516 uic->uicvr = 0x0000000;
520 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
521 uint32_t dcr_base, int has_ssr, int has_vr)
523 ppcuic_t *uic;
524 int i;
526 uic = qemu_mallocz(sizeof(ppcuic_t));
527 if (uic != NULL) {
528 uic->dcr_base = dcr_base;
529 uic->irqs = irqs;
530 if (has_vr)
531 uic->use_vectors = 1;
532 for (i = 0; i < DCR_UICMAX; i++) {
533 ppc_dcr_register(env, dcr_base + i, uic,
534 &dcr_read_uic, &dcr_write_uic);
536 qemu_register_reset(ppcuic_reset, uic);
537 ppcuic_reset(uic);
540 return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
546 #define PCIC0_CFGADDR 0x0
547 #define PCIC0_CFGDATA 0x4
549 #define PCIL0_PMM0LA 0x0
550 #define PCIL0_PMM0MA 0x4
551 #define PCIL0_PMM0PCILA 0x8
552 #define PCIL0_PMM0PCIHA 0xc
553 #define PCIL0_PMM1LA 0x10
554 #define PCIL0_PMM1MA 0x14
555 #define PCIL0_PMM1PCILA 0x18
556 #define PCIL0_PMM1PCIHA 0x1c
557 #define PCIL0_PMM2LA 0x20
558 #define PCIL0_PMM2MA 0x24
559 #define PCIL0_PMM2PCILA 0x28
560 #define PCIL0_PMM2PCIHA 0x2c
561 #define PCIL0_PTM1MS 0x30
562 #define PCIL0_PTM1LA 0x34
563 #define PCIL0_PTM2MS 0x38
564 #define PCIL0_PTM2LA 0x3c
565 #define PCI_REG_SIZE 0x40
567 #define PPC44x_PCI_MA_MASK 0xfffff000
568 #define PPC44x_PCI_MA_ENABLE 0x1
571 static uint32_t pci4xx_cfgaddr_read4(void *opaque, target_phys_addr_t addr)
573 ppc4xx_pci_t *ppc4xx_pci = opaque;
574 return cpu_to_le32(ppc4xx_pci->pcic0_cfgaddr);
577 static CPUReadMemoryFunc *pci4xx_cfgaddr_read[] = {
578 &pci4xx_cfgaddr_read4,
579 &pci4xx_cfgaddr_read4,
580 &pci4xx_cfgaddr_read4,
583 static void pci4xx_cfgaddr_write4(void *opaque, target_phys_addr_t addr,
584 uint32_t value)
586 ppc4xx_pci_t *ppc4xx_pci = opaque;
588 value = le32_to_cpu(value);
590 ppc4xx_pci->pcic0_cfgaddr = value & ~0x3;
593 static CPUWriteMemoryFunc *pci4xx_cfgaddr_write[] = {
594 &pci4xx_cfgaddr_write4,
595 &pci4xx_cfgaddr_write4,
596 &pci4xx_cfgaddr_write4,
599 static uint32_t pci4xx_cfgdata_read1(void *opaque, target_phys_addr_t addr)
601 ppc4xx_pci_t *ppc4xx_pci = opaque;
602 int offset = addr & 0x3;
603 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
604 uint32_t value;
606 if (!(cfgaddr & (1<<31)))
607 return 0xffffffff;
609 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 1);
611 return value;
614 static uint32_t pci4xx_cfgdata_read2(void *opaque, target_phys_addr_t addr)
616 ppc4xx_pci_t *ppc4xx_pci = opaque;
617 int offset = addr & 0x3;
618 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
619 uint32_t value;
621 if (!(cfgaddr & (1<<31)))
622 return 0xffffffff;
624 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 2);
626 return cpu_to_le16(value);
629 static uint32_t pci4xx_cfgdata_read4(void *opaque, target_phys_addr_t addr)
631 ppc4xx_pci_t *ppc4xx_pci = opaque;
632 int offset = addr & 0x3;
633 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
634 uint32_t value;
636 if (!(cfgaddr & (1<<31)))
637 return 0xffffffff;
639 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 4);
641 return cpu_to_le32(value);
644 static CPUReadMemoryFunc *pci4xx_cfgdata_read[] = {
645 &pci4xx_cfgdata_read1,
646 &pci4xx_cfgdata_read2,
647 &pci4xx_cfgdata_read4,
650 static void pci4xx_cfgdata_write1(void *opaque, target_phys_addr_t addr,
651 uint32_t value)
653 ppc4xx_pci_t *ppc4xx_pci = opaque;
654 int offset = addr & 0x3;
656 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
657 value, 1);
660 static void pci4xx_cfgdata_write2(void *opaque, target_phys_addr_t addr,
661 uint32_t value)
663 ppc4xx_pci_t *ppc4xx_pci = opaque;
664 int offset = addr & 0x3;
666 value = le16_to_cpu(value);
668 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
669 value, 2);
672 static void pci4xx_cfgdata_write4(void *opaque, target_phys_addr_t addr,
673 uint32_t value)
675 ppc4xx_pci_t *ppc4xx_pci = opaque;
676 int offset = addr & 0x3;
678 value = le32_to_cpu(value);
680 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
681 value, 4);
684 static CPUWriteMemoryFunc *pci4xx_cfgdata_write[] = {
685 &pci4xx_cfgdata_write1,
686 &pci4xx_cfgdata_write2,
687 &pci4xx_cfgdata_write4,
690 static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
691 uint32_t value)
693 struct ppc4xx_pci_t *pci = opaque;
694 unsigned long offset = addr - pci->registers;
696 value = le32_to_cpu(value);
698 switch (offset) {
699 case PCIL0_PMM0LA:
700 pci->pmm[0].la = value;
701 break;
702 case PCIL0_PMM1LA:
703 pci->pmm[0].la = value;
704 break;
705 case PCIL0_PMM2LA:
706 pci->pmm[0].la = value;
707 break;
708 default:
709 //printf(" unhandled PCI internal register 0x%lx\n", offset);
710 break;
714 static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
716 struct ppc4xx_pci_t *pci = opaque;
717 unsigned long offset = addr - pci->registers;
718 uint32_t value;
720 switch (offset) {
721 case PCIL0_PMM0LA:
722 value = pci->pmm[0].la;
723 break;
724 case PCIL0_PMM0MA:
725 value = pci->pmm[0].ma;
726 break;
727 case PCIL0_PMM0PCIHA:
728 value = pci->pmm[0].pciha;
729 break;
730 case PCIL0_PMM0PCILA:
731 value = pci->pmm[0].pcila;
732 break;
734 case PCIL0_PMM1LA:
735 value = pci->pmm[1].la;
736 break;
737 case PCIL0_PMM1MA:
738 value = pci->pmm[1].ma;
739 break;
740 case PCIL0_PMM1PCIHA:
741 value = pci->pmm[1].pciha;
742 break;
743 case PCIL0_PMM1PCILA:
744 value = pci->pmm[1].pcila;
745 break;
747 case PCIL0_PMM2LA:
748 value = pci->pmm[2].la;
749 break;
750 case PCIL0_PMM2MA:
751 value = pci->pmm[2].ma;
752 break;
753 case PCIL0_PMM2PCIHA:
754 value = pci->pmm[2].pciha;
755 break;
756 case PCIL0_PMM2PCILA:
757 value = pci->pmm[2].pcila;
758 break;
760 case PCIL0_PTM1MS:
761 value = pci->ptm[0].ms;
762 break;
763 case PCIL0_PTM1LA:
764 value = pci->ptm[0].la;
765 break;
766 case PCIL0_PTM2MS:
767 value = pci->ptm[1].ms;
768 break;
769 case PCIL0_PTM2LA:
770 value = pci->ptm[1].la;
771 break;
773 default:
774 //printf(" read from invalid PCI internal register 0x%lx\n", offset);
775 value = 0;
778 value = cpu_to_le32(value);
780 return value;
783 static CPUReadMemoryFunc *pci_reg_read[] = {
784 &pci_reg_read4,
785 &pci_reg_read4,
786 &pci_reg_read4,
789 static CPUWriteMemoryFunc *pci_reg_write[] = {
790 &pci_reg_write4,
791 &pci_reg_write4,
792 &pci_reg_write4,
795 static uint32_t pci_int_ack_read4(void *opaque, target_phys_addr_t addr)
797 printf("%s\n", __func__);
798 return 0;
801 static CPUReadMemoryFunc *pci_int_ack_read[] = {
802 &pci_int_ack_read4,
803 &pci_int_ack_read4,
804 &pci_int_ack_read4,
807 static void pci_special_write4(void *opaque, target_phys_addr_t addr,
808 uint32_t value)
810 printf("%s\n", __func__);
813 static CPUWriteMemoryFunc *pci_special_write[] = {
814 &pci_special_write4,
815 &pci_special_write4,
816 &pci_special_write4,
819 static int bamboo_pci_map_irq(PCIDevice *pci_dev, int irq_num)
821 int slot = pci_dev->devfn >> 3;
823 #if 0
824 printf("### %s: devfn %x irq %d -> %d\n", __func__,
825 pci_dev->devfn, irq_num, slot+1);
826 #endif
828 /* All pins from each slot are tied to a single board IRQ (2-5) */
829 return slot + 1;
832 static void bamboo_pci_set_irq(qemu_irq *pic, int irq_num, int level)
834 #if 0
835 printf("### %s: PCI irq %d, UIC irq %d\n", __func__, irq_num, 30 - irq_num);
836 #endif
838 /* Board IRQs 2-5 are connected to UIC IRQs 28-25 */
839 qemu_set_irq(pic[30-irq_num], level);
842 /* XXX Needs some abstracting for boards other than Bamboo. */
843 ppc4xx_pci_t *ppc4xx_pci_init(CPUState *env, qemu_irq *pic,
844 target_phys_addr_t config_space,
845 target_phys_addr_t int_ack,
846 target_phys_addr_t special_cycle,
847 target_phys_addr_t registers)
849 ppc4xx_pci_t *pci;
850 PCIDevice *d;
851 int index;
853 pci = qemu_mallocz(sizeof(ppc4xx_pci_t));
854 if (!pci)
855 return NULL;
857 pci->config_space = config_space;
858 pci->registers = registers;
859 pci->pic = pic;
861 pci->bus = pci_register_bus(bamboo_pci_set_irq, bamboo_pci_map_irq,
862 pic, 0, 4);
863 d = pci_register_device(pci->bus, "host bridge", sizeof(PCIDevice),
864 0, NULL, NULL);
865 d->config[0x00] = 0x14; // vendor_id
866 d->config[0x01] = 0x10;
867 d->config[0x02] = 0x7f; // device_id
868 d->config[0x03] = 0x02;
869 d->config[0x0a] = 0x80; // class_sub = other bridge type
870 d->config[0x0b] = 0x06; // class_base = PCI_bridge
872 /* CFGADDR */
873 index = cpu_register_io_memory(0, pci4xx_cfgaddr_read,
874 pci4xx_cfgaddr_write, pci);
875 if (index < 0)
876 goto free;
877 cpu_register_physical_memory(config_space, 4, index);
879 /* CFGDATA */
880 index = cpu_register_io_memory(0, pci4xx_cfgdata_read,
881 pci4xx_cfgdata_write, pci);
882 if (index < 0)
883 goto free;
884 cpu_register_physical_memory(config_space + 4, 4, index);
886 /* "Special cycle" and interrupt acknowledge */
887 index = cpu_register_io_memory(0, pci_int_ack_read,
888 pci_special_write, pci);
889 if (index < 0)
890 goto free;
891 cpu_register_physical_memory(int_ack, 4, index);
893 /* Internal registers */
894 index = cpu_register_io_memory(0, pci_reg_read, pci_reg_write, pci);
895 if (index < 0)
896 goto free;
897 cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
899 /* XXX register_savevm() */
901 return pci;
903 free:
904 printf("%s error\n", __func__);
905 qemu_free(pci);
906 return NULL;