kvm: external module: Make KVM compile on split source/object kernel configurations
[qemu-kvm/fedora.git] / hw / ppc4xx_devs.c
blob5f0c49cbc9ceb2e600027a44e28dd948ad038498
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 "qemu-log.h"
32 #include "pci.h"
33 #include "bswap.h"
35 //#define DEBUG_MMIO
36 //#define DEBUG_UNASSIGNED
37 #define DEBUG_UIC
39 /*****************************************************************************/
40 /* Generic PowerPC 4xx processor instanciation */
41 CPUState *ppc4xx_init (const char *cpu_model,
42 clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
43 uint32_t sysclk)
45 CPUState *env;
47 /* init CPUs */
48 env = cpu_init(cpu_model);
49 if (!env) {
50 fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
51 cpu_model);
52 exit(1);
54 cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
55 cpu_clk->opaque = env;
56 /* Set time-base frequency to sysclk */
57 tb_clk->cb = ppc_emb_timers_init(env, sysclk);
58 tb_clk->opaque = env;
59 ppc_dcr_init(env, NULL, NULL);
60 /* Register qemu callbacks */
61 qemu_register_reset(&cpu_ppc_reset, env);
63 return env;
66 /*****************************************************************************/
67 /* Fake device used to map multiple devices in a single memory page */
68 #define MMIO_AREA_BITS 8
69 #define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
70 #define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
71 #define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
72 struct ppc4xx_mmio_t {
73 target_phys_addr_t base;
74 CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
75 CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
76 void *opaque[MMIO_AREA_NB];
79 static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
81 #ifdef DEBUG_UNASSIGNED
82 ppc4xx_mmio_t *mmio;
84 mmio = opaque;
85 printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
86 addr, mmio->base);
87 #endif
89 return 0;
92 static void unassigned_mmio_writeb (void *opaque,
93 target_phys_addr_t addr, uint32_t val)
95 #ifdef DEBUG_UNASSIGNED
96 ppc4xx_mmio_t *mmio;
98 mmio = opaque;
99 printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
100 addr, val, mmio->base);
101 #endif
104 static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
105 unassigned_mmio_readb,
106 unassigned_mmio_readb,
107 unassigned_mmio_readb,
110 static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
111 unassigned_mmio_writeb,
112 unassigned_mmio_writeb,
113 unassigned_mmio_writeb,
116 static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
117 target_phys_addr_t addr, int len)
119 CPUReadMemoryFunc **mem_read;
120 uint32_t ret;
121 int idx;
123 idx = MMIO_IDX(addr - mmio->base);
124 #if defined(DEBUG_MMIO)
125 printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
126 mmio, len, addr, idx);
127 #endif
128 mem_read = mmio->mem_read[idx];
129 ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
131 return ret;
134 static void mmio_writelen (ppc4xx_mmio_t *mmio,
135 target_phys_addr_t addr, uint32_t value, int len)
137 CPUWriteMemoryFunc **mem_write;
138 int idx;
140 idx = MMIO_IDX(addr - mmio->base);
141 #if defined(DEBUG_MMIO)
142 printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08" PRIx32 "\n",
143 __func__, mmio, len, addr, idx, value);
144 #endif
145 mem_write = mmio->mem_write[idx];
146 (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
149 static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
151 #if defined(DEBUG_MMIO)
152 printf("%s: addr " PADDRX "\n", __func__, addr);
153 #endif
155 return mmio_readlen(opaque, addr, 0);
158 static void mmio_writeb (void *opaque,
159 target_phys_addr_t addr, uint32_t value)
161 #if defined(DEBUG_MMIO)
162 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
163 #endif
164 mmio_writelen(opaque, addr, value, 0);
167 static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
169 #if defined(DEBUG_MMIO)
170 printf("%s: addr " PADDRX "\n", __func__, addr);
171 #endif
173 return mmio_readlen(opaque, addr, 1);
176 static void mmio_writew (void *opaque,
177 target_phys_addr_t addr, uint32_t value)
179 #if defined(DEBUG_MMIO)
180 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
181 #endif
182 mmio_writelen(opaque, addr, value, 1);
185 static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
187 #if defined(DEBUG_MMIO)
188 printf("%s: addr " PADDRX "\n", __func__, addr);
189 #endif
191 return mmio_readlen(opaque, addr, 2);
194 static void mmio_writel (void *opaque,
195 target_phys_addr_t addr, uint32_t value)
197 #if defined(DEBUG_MMIO)
198 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
199 #endif
200 mmio_writelen(opaque, addr, value, 2);
203 static CPUReadMemoryFunc *mmio_read[] = {
204 &mmio_readb,
205 &mmio_readw,
206 &mmio_readl,
209 static CPUWriteMemoryFunc *mmio_write[] = {
210 &mmio_writeb,
211 &mmio_writew,
212 &mmio_writel,
215 int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
216 target_phys_addr_t offset, uint32_t len,
217 CPUReadMemoryFunc **mem_read,
218 CPUWriteMemoryFunc **mem_write, void *opaque)
220 target_phys_addr_t end;
221 int idx, eidx;
223 if ((offset + len) > TARGET_PAGE_SIZE)
224 return -1;
225 idx = MMIO_IDX(offset);
226 end = offset + len - 1;
227 eidx = MMIO_IDX(end);
228 #if defined(DEBUG_MMIO)
229 printf("%s: offset " PADDRX " len %08" PRIx32 " " PADDRX " %d %d\n",
230 __func__, offset, len, end, idx, eidx);
231 #endif
232 for (; idx <= eidx; idx++) {
233 mmio->mem_read[idx] = mem_read;
234 mmio->mem_write[idx] = mem_write;
235 mmio->opaque[idx] = opaque;
238 return 0;
241 ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
243 ppc4xx_mmio_t *mmio;
244 int mmio_memory;
246 mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
247 if (mmio != NULL) {
248 mmio->base = base;
249 mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
250 #if defined(DEBUG_MMIO)
251 printf("%s: base " PADDRX " len %08x %d\n", __func__,
252 base, TARGET_PAGE_SIZE, mmio_memory);
253 #endif
254 cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
255 ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
256 unassigned_mmio_read, unassigned_mmio_write,
257 mmio);
260 return mmio;
263 /*****************************************************************************/
264 /* "Universal" Interrupt controller */
265 enum {
266 DCR_UICSR = 0x000,
267 DCR_UICSRS = 0x001,
268 DCR_UICER = 0x002,
269 DCR_UICCR = 0x003,
270 DCR_UICPR = 0x004,
271 DCR_UICTR = 0x005,
272 DCR_UICMSR = 0x006,
273 DCR_UICVR = 0x007,
274 DCR_UICVCR = 0x008,
275 DCR_UICMAX = 0x009,
278 #define UIC_MAX_IRQ 32
279 typedef struct ppcuic_t ppcuic_t;
280 struct ppcuic_t {
281 uint32_t dcr_base;
282 int use_vectors;
283 uint32_t level; /* Remembers the state of level-triggered interrupts. */
284 uint32_t uicsr; /* Status register */
285 uint32_t uicer; /* Enable register */
286 uint32_t uiccr; /* Critical register */
287 uint32_t uicpr; /* Polarity register */
288 uint32_t uictr; /* Triggering register */
289 uint32_t uicvcr; /* Vector configuration register */
290 uint32_t uicvr;
291 qemu_irq *irqs;
294 static void ppcuic_trigger_irq (ppcuic_t *uic)
296 uint32_t ir, cr;
297 int start, end, inc, i;
299 /* Trigger interrupt if any is pending */
300 ir = uic->uicsr & uic->uicer & (~uic->uiccr);
301 cr = uic->uicsr & uic->uicer & uic->uiccr;
302 #ifdef DEBUG_UIC
303 if (loglevel & CPU_LOG_INT) {
304 fprintf(logfile, "%s: uicsr %08" PRIx32 " uicer %08" PRIx32
305 " uiccr %08" PRIx32 "\n"
306 " %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
307 __func__, uic->uicsr, uic->uicer, uic->uiccr,
308 uic->uicsr & uic->uicer, ir, cr);
310 #endif
311 if (ir != 0x0000000) {
312 #ifdef DEBUG_UIC
313 if (loglevel & CPU_LOG_INT) {
314 fprintf(logfile, "Raise UIC interrupt\n");
316 #endif
317 qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
318 } else {
319 #ifdef DEBUG_UIC
320 if (loglevel & CPU_LOG_INT) {
321 fprintf(logfile, "Lower UIC interrupt\n");
323 #endif
324 qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
326 /* Trigger critical interrupt if any is pending and update vector */
327 if (cr != 0x0000000) {
328 qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
329 if (uic->use_vectors) {
330 /* Compute critical IRQ vector */
331 if (uic->uicvcr & 1) {
332 start = 31;
333 end = 0;
334 inc = -1;
335 } else {
336 start = 0;
337 end = 31;
338 inc = 1;
340 uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
341 for (i = start; i <= end; i += inc) {
342 if (cr & (1 << i)) {
343 uic->uicvr += (i - start) * 512 * inc;
344 break;
348 #ifdef DEBUG_UIC
349 if (loglevel & CPU_LOG_INT) {
350 fprintf(logfile, "Raise UIC critical interrupt - "
351 "vector %08" PRIx32 "\n", uic->uicvr);
353 #endif
354 } else {
355 #ifdef DEBUG_UIC
356 if (loglevel & CPU_LOG_INT) {
357 fprintf(logfile, "Lower UIC critical interrupt\n");
359 #endif
360 qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
361 uic->uicvr = 0x00000000;
365 static void ppcuic_set_irq (void *opaque, int irq_num, int level)
367 ppcuic_t *uic;
368 uint32_t mask, sr;
370 uic = opaque;
371 mask = 1 << (31-irq_num);
372 #ifdef DEBUG_UIC
373 if (loglevel & CPU_LOG_INT) {
374 fprintf(logfile, "%s: irq %d level %d uicsr %08" PRIx32
375 " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
376 __func__, irq_num, level,
377 uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
379 #endif
380 if (irq_num < 0 || irq_num > 31)
381 return;
382 sr = uic->uicsr;
384 /* Update status register */
385 if (uic->uictr & mask) {
386 /* Edge sensitive interrupt */
387 if (level == 1)
388 uic->uicsr |= mask;
389 } else {
390 /* Level sensitive interrupt */
391 if (level == 1) {
392 uic->uicsr |= mask;
393 uic->level |= mask;
394 } else {
395 uic->uicsr &= ~mask;
396 uic->level &= ~mask;
399 #ifdef DEBUG_UIC
400 if (loglevel & CPU_LOG_INT) {
401 fprintf(logfile, "%s: irq %d level %d sr %" PRIx32 " => "
402 "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
404 #endif
405 if (sr != uic->uicsr)
406 ppcuic_trigger_irq(uic);
409 static target_ulong dcr_read_uic (void *opaque, int dcrn)
411 ppcuic_t *uic;
412 target_ulong ret;
414 uic = opaque;
415 dcrn -= uic->dcr_base;
416 switch (dcrn) {
417 case DCR_UICSR:
418 case DCR_UICSRS:
419 ret = uic->uicsr;
420 break;
421 case DCR_UICER:
422 ret = uic->uicer;
423 break;
424 case DCR_UICCR:
425 ret = uic->uiccr;
426 break;
427 case DCR_UICPR:
428 ret = uic->uicpr;
429 break;
430 case DCR_UICTR:
431 ret = uic->uictr;
432 break;
433 case DCR_UICMSR:
434 ret = uic->uicsr & uic->uicer;
435 break;
436 case DCR_UICVR:
437 if (!uic->use_vectors)
438 goto no_read;
439 ret = uic->uicvr;
440 break;
441 case DCR_UICVCR:
442 if (!uic->use_vectors)
443 goto no_read;
444 ret = uic->uicvcr;
445 break;
446 default:
447 no_read:
448 ret = 0x00000000;
449 break;
452 return ret;
455 static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
457 ppcuic_t *uic;
459 uic = opaque;
460 dcrn -= uic->dcr_base;
461 #ifdef DEBUG_UIC
462 if (loglevel & CPU_LOG_INT) {
463 fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
465 #endif
466 switch (dcrn) {
467 case DCR_UICSR:
468 uic->uicsr &= ~val;
469 uic->uicsr |= uic->level;
470 ppcuic_trigger_irq(uic);
471 break;
472 case DCR_UICSRS:
473 uic->uicsr |= val;
474 ppcuic_trigger_irq(uic);
475 break;
476 case DCR_UICER:
477 uic->uicer = val;
478 ppcuic_trigger_irq(uic);
479 break;
480 case DCR_UICCR:
481 uic->uiccr = val;
482 ppcuic_trigger_irq(uic);
483 break;
484 case DCR_UICPR:
485 uic->uicpr = val;
486 break;
487 case DCR_UICTR:
488 uic->uictr = val;
489 ppcuic_trigger_irq(uic);
490 break;
491 case DCR_UICMSR:
492 break;
493 case DCR_UICVR:
494 break;
495 case DCR_UICVCR:
496 uic->uicvcr = val & 0xFFFFFFFD;
497 ppcuic_trigger_irq(uic);
498 break;
502 static void ppcuic_reset (void *opaque)
504 ppcuic_t *uic;
506 uic = opaque;
507 uic->uiccr = 0x00000000;
508 uic->uicer = 0x00000000;
509 uic->uicpr = 0x00000000;
510 uic->uicsr = 0x00000000;
511 uic->uictr = 0x00000000;
512 if (uic->use_vectors) {
513 uic->uicvcr = 0x00000000;
514 uic->uicvr = 0x0000000;
518 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
519 uint32_t dcr_base, int has_ssr, int has_vr)
521 ppcuic_t *uic;
522 int i;
524 uic = qemu_mallocz(sizeof(ppcuic_t));
525 if (uic != NULL) {
526 uic->dcr_base = dcr_base;
527 uic->irqs = irqs;
528 if (has_vr)
529 uic->use_vectors = 1;
530 for (i = 0; i < DCR_UICMAX; i++) {
531 ppc_dcr_register(env, dcr_base + i, uic,
532 &dcr_read_uic, &dcr_write_uic);
534 qemu_register_reset(ppcuic_reset, uic);
535 ppcuic_reset(uic);
538 return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
544 #define PCIC0_CFGADDR 0x0
545 #define PCIC0_CFGDATA 0x4
547 #define PCIL0_PMM0LA 0x0
548 #define PCIL0_PMM0MA 0x4
549 #define PCIL0_PMM0PCILA 0x8
550 #define PCIL0_PMM0PCIHA 0xc
551 #define PCIL0_PMM1LA 0x10
552 #define PCIL0_PMM1MA 0x14
553 #define PCIL0_PMM1PCILA 0x18
554 #define PCIL0_PMM1PCIHA 0x1c
555 #define PCIL0_PMM2LA 0x20
556 #define PCIL0_PMM2MA 0x24
557 #define PCIL0_PMM2PCILA 0x28
558 #define PCIL0_PMM2PCIHA 0x2c
559 #define PCIL0_PTM1MS 0x30
560 #define PCIL0_PTM1LA 0x34
561 #define PCIL0_PTM2MS 0x38
562 #define PCIL0_PTM2LA 0x3c
563 #define PCI_REG_SIZE 0x40
565 #define PPC44x_PCI_MA_MASK 0xfffff000
566 #define PPC44x_PCI_MA_ENABLE 0x1
569 static uint32_t pci4xx_cfgaddr_read4(void *opaque, target_phys_addr_t addr)
571 ppc4xx_pci_t *ppc4xx_pci = opaque;
572 return cpu_to_le32(ppc4xx_pci->pcic0_cfgaddr);
575 static CPUReadMemoryFunc *pci4xx_cfgaddr_read[] = {
576 &pci4xx_cfgaddr_read4,
577 &pci4xx_cfgaddr_read4,
578 &pci4xx_cfgaddr_read4,
581 static void pci4xx_cfgaddr_write4(void *opaque, target_phys_addr_t addr,
582 uint32_t value)
584 ppc4xx_pci_t *ppc4xx_pci = opaque;
586 value = le32_to_cpu(value);
588 ppc4xx_pci->pcic0_cfgaddr = value & ~0x3;
591 static CPUWriteMemoryFunc *pci4xx_cfgaddr_write[] = {
592 &pci4xx_cfgaddr_write4,
593 &pci4xx_cfgaddr_write4,
594 &pci4xx_cfgaddr_write4,
597 static uint32_t pci4xx_cfgdata_read1(void *opaque, target_phys_addr_t addr)
599 ppc4xx_pci_t *ppc4xx_pci = opaque;
600 int offset = addr & 0x3;
601 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
602 uint32_t value;
604 if (!(cfgaddr & (1<<31)))
605 return 0xffffffff;
607 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 1);
609 return value;
612 static uint32_t pci4xx_cfgdata_read2(void *opaque, target_phys_addr_t addr)
614 ppc4xx_pci_t *ppc4xx_pci = opaque;
615 int offset = addr & 0x3;
616 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
617 uint32_t value;
619 if (!(cfgaddr & (1<<31)))
620 return 0xffffffff;
622 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 2);
624 return cpu_to_le16(value);
627 static uint32_t pci4xx_cfgdata_read4(void *opaque, target_phys_addr_t addr)
629 ppc4xx_pci_t *ppc4xx_pci = opaque;
630 int offset = addr & 0x3;
631 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
632 uint32_t value;
634 if (!(cfgaddr & (1<<31)))
635 return 0xffffffff;
637 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 4);
639 return cpu_to_le32(value);
642 static CPUReadMemoryFunc *pci4xx_cfgdata_read[] = {
643 &pci4xx_cfgdata_read1,
644 &pci4xx_cfgdata_read2,
645 &pci4xx_cfgdata_read4,
648 static void pci4xx_cfgdata_write1(void *opaque, target_phys_addr_t addr,
649 uint32_t value)
651 ppc4xx_pci_t *ppc4xx_pci = opaque;
652 int offset = addr & 0x3;
654 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
655 value, 1);
658 static void pci4xx_cfgdata_write2(void *opaque, target_phys_addr_t addr,
659 uint32_t value)
661 ppc4xx_pci_t *ppc4xx_pci = opaque;
662 int offset = addr & 0x3;
664 value = le16_to_cpu(value);
666 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
667 value, 2);
670 static void pci4xx_cfgdata_write4(void *opaque, target_phys_addr_t addr,
671 uint32_t value)
673 ppc4xx_pci_t *ppc4xx_pci = opaque;
674 int offset = addr & 0x3;
676 value = le32_to_cpu(value);
678 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
679 value, 4);
682 static CPUWriteMemoryFunc *pci4xx_cfgdata_write[] = {
683 &pci4xx_cfgdata_write1,
684 &pci4xx_cfgdata_write2,
685 &pci4xx_cfgdata_write4,
688 static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
689 uint32_t value)
691 struct ppc4xx_pci_t *pci = opaque;
692 unsigned long offset = addr - pci->registers;
694 value = le32_to_cpu(value);
696 switch (offset) {
697 case PCIL0_PMM0LA:
698 pci->pmm[0].la = value;
699 break;
700 case PCIL0_PMM1LA:
701 pci->pmm[0].la = value;
702 break;
703 case PCIL0_PMM2LA:
704 pci->pmm[0].la = value;
705 break;
706 default:
707 //printf(" unhandled PCI internal register 0x%lx\n", offset);
708 break;
712 static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
714 struct ppc4xx_pci_t *pci = opaque;
715 unsigned long offset = addr - pci->registers;
716 uint32_t value;
718 switch (offset) {
719 case PCIL0_PMM0LA:
720 value = pci->pmm[0].la;
721 break;
722 case PCIL0_PMM0MA:
723 value = pci->pmm[0].ma;
724 break;
725 case PCIL0_PMM0PCIHA:
726 value = pci->pmm[0].pciha;
727 break;
728 case PCIL0_PMM0PCILA:
729 value = pci->pmm[0].pcila;
730 break;
732 case PCIL0_PMM1LA:
733 value = pci->pmm[1].la;
734 break;
735 case PCIL0_PMM1MA:
736 value = pci->pmm[1].ma;
737 break;
738 case PCIL0_PMM1PCIHA:
739 value = pci->pmm[1].pciha;
740 break;
741 case PCIL0_PMM1PCILA:
742 value = pci->pmm[1].pcila;
743 break;
745 case PCIL0_PMM2LA:
746 value = pci->pmm[2].la;
747 break;
748 case PCIL0_PMM2MA:
749 value = pci->pmm[2].ma;
750 break;
751 case PCIL0_PMM2PCIHA:
752 value = pci->pmm[2].pciha;
753 break;
754 case PCIL0_PMM2PCILA:
755 value = pci->pmm[2].pcila;
756 break;
758 case PCIL0_PTM1MS:
759 value = pci->ptm[0].ms;
760 break;
761 case PCIL0_PTM1LA:
762 value = pci->ptm[0].la;
763 break;
764 case PCIL0_PTM2MS:
765 value = pci->ptm[1].ms;
766 break;
767 case PCIL0_PTM2LA:
768 value = pci->ptm[1].la;
769 break;
771 default:
772 //printf(" read from invalid PCI internal register 0x%lx\n", offset);
773 value = 0;
776 value = cpu_to_le32(value);
778 return value;
781 static CPUReadMemoryFunc *pci_reg_read[] = {
782 &pci_reg_read4,
783 &pci_reg_read4,
784 &pci_reg_read4,
787 static CPUWriteMemoryFunc *pci_reg_write[] = {
788 &pci_reg_write4,
789 &pci_reg_write4,
790 &pci_reg_write4,
793 static uint32_t pci_int_ack_read4(void *opaque, target_phys_addr_t addr)
795 printf("%s\n", __func__);
796 return 0;
799 static CPUReadMemoryFunc *pci_int_ack_read[] = {
800 &pci_int_ack_read4,
801 &pci_int_ack_read4,
802 &pci_int_ack_read4,
805 static void pci_special_write4(void *opaque, target_phys_addr_t addr,
806 uint32_t value)
808 printf("%s\n", __func__);
811 static CPUWriteMemoryFunc *pci_special_write[] = {
812 &pci_special_write4,
813 &pci_special_write4,
814 &pci_special_write4,
817 static int bamboo_pci_map_irq(PCIDevice *pci_dev, int irq_num)
819 int slot = pci_dev->devfn >> 3;
821 #if 0
822 printf("### %s: devfn %x irq %d -> %d\n", __func__,
823 pci_dev->devfn, irq_num, slot+1);
824 #endif
826 /* All pins from each slot are tied to a single board IRQ (2-5) */
827 return slot + 1;
830 static void bamboo_pci_set_irq(qemu_irq *pic, int irq_num, int level)
832 #if 0
833 printf("### %s: PCI irq %d, UIC irq %d\n", __func__, irq_num, 30 - irq_num);
834 #endif
836 /* Board IRQs 2-5 are connected to UIC IRQs 28-25 */
837 qemu_set_irq(pic[30-irq_num], level);
840 /* XXX Needs some abstracting for boards other than Bamboo. */
841 ppc4xx_pci_t *ppc4xx_pci_init(CPUState *env, qemu_irq *pic,
842 target_phys_addr_t config_space,
843 target_phys_addr_t int_ack,
844 target_phys_addr_t special_cycle,
845 target_phys_addr_t registers)
847 ppc4xx_pci_t *pci;
848 PCIDevice *d;
849 int index;
851 pci = qemu_mallocz(sizeof(ppc4xx_pci_t));
852 if (!pci)
853 return NULL;
855 pci->config_space = config_space;
856 pci->registers = registers;
857 pci->pic = pic;
859 pci->bus = pci_register_bus(bamboo_pci_set_irq, bamboo_pci_map_irq,
860 pic, 0, 4);
861 d = pci_register_device(pci->bus, "host bridge", sizeof(PCIDevice),
862 0, NULL, NULL);
863 d->config[0x00] = 0x14; // vendor_id
864 d->config[0x01] = 0x10;
865 d->config[0x02] = 0x7f; // device_id
866 d->config[0x03] = 0x02;
867 d->config[0x0a] = 0x80; // class_sub = other bridge type
868 d->config[0x0b] = 0x06; // class_base = PCI_bridge
870 /* CFGADDR */
871 index = cpu_register_io_memory(0, pci4xx_cfgaddr_read,
872 pci4xx_cfgaddr_write, pci);
873 if (index < 0)
874 goto free;
875 cpu_register_physical_memory(config_space, 4, index);
877 /* CFGDATA */
878 index = cpu_register_io_memory(0, pci4xx_cfgdata_read,
879 pci4xx_cfgdata_write, pci);
880 if (index < 0)
881 goto free;
882 cpu_register_physical_memory(config_space + 4, 4, index);
884 /* "Special cycle" and interrupt acknowledge */
885 index = cpu_register_io_memory(0, pci_int_ack_read,
886 pci_special_write, pci);
887 if (index < 0)
888 goto free;
889 cpu_register_physical_memory(int_ack, 4, index);
891 /* Internal registers */
892 index = cpu_register_io_memory(0, pci_reg_read, pci_reg_write, pci);
893 if (index < 0)
894 goto free;
895 cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
897 /* XXX register_savevm() */
899 return pci;
901 free:
902 printf("%s error\n", __func__);
903 qemu_free(pci);
904 return NULL;