Add fd_readv handler to tap
[qemu-kvm/fedora.git] / hw / ppc4xx_devs.c
blobfca3b86e0cb292a1bafc8efcaa39b46ca28d480a
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);
64 register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
66 return env;
69 /*****************************************************************************/
70 /* Fake device used to map multiple devices in a single memory page */
71 #define MMIO_AREA_BITS 8
72 #define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
73 #define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
74 #define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
75 struct ppc4xx_mmio_t {
76 target_phys_addr_t base;
77 CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
78 CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
79 void *opaque[MMIO_AREA_NB];
82 static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
84 #ifdef DEBUG_UNASSIGNED
85 ppc4xx_mmio_t *mmio;
87 mmio = opaque;
88 printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
89 addr, mmio->base);
90 #endif
92 return 0;
95 static void unassigned_mmio_writeb (void *opaque,
96 target_phys_addr_t addr, uint32_t val)
98 #ifdef DEBUG_UNASSIGNED
99 ppc4xx_mmio_t *mmio;
101 mmio = opaque;
102 printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
103 addr, val, mmio->base);
104 #endif
107 static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
108 unassigned_mmio_readb,
109 unassigned_mmio_readb,
110 unassigned_mmio_readb,
113 static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
114 unassigned_mmio_writeb,
115 unassigned_mmio_writeb,
116 unassigned_mmio_writeb,
119 static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
120 target_phys_addr_t addr, int len)
122 CPUReadMemoryFunc **mem_read;
123 uint32_t ret;
124 int idx;
126 idx = MMIO_IDX(addr - mmio->base);
127 #if defined(DEBUG_MMIO)
128 printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
129 mmio, len, addr, idx);
130 #endif
131 mem_read = mmio->mem_read[idx];
132 ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
134 return ret;
137 static void mmio_writelen (ppc4xx_mmio_t *mmio,
138 target_phys_addr_t addr, uint32_t value, int len)
140 CPUWriteMemoryFunc **mem_write;
141 int idx;
143 idx = MMIO_IDX(addr - mmio->base);
144 #if defined(DEBUG_MMIO)
145 printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08" PRIx32 "\n",
146 __func__, mmio, len, addr, idx, value);
147 #endif
148 mem_write = mmio->mem_write[idx];
149 (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
152 static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
154 #if defined(DEBUG_MMIO)
155 printf("%s: addr " PADDRX "\n", __func__, addr);
156 #endif
158 return mmio_readlen(opaque, addr, 0);
161 static void mmio_writeb (void *opaque,
162 target_phys_addr_t addr, uint32_t value)
164 #if defined(DEBUG_MMIO)
165 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
166 #endif
167 mmio_writelen(opaque, addr, value, 0);
170 static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
172 #if defined(DEBUG_MMIO)
173 printf("%s: addr " PADDRX "\n", __func__, addr);
174 #endif
176 return mmio_readlen(opaque, addr, 1);
179 static void mmio_writew (void *opaque,
180 target_phys_addr_t addr, uint32_t value)
182 #if defined(DEBUG_MMIO)
183 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
184 #endif
185 mmio_writelen(opaque, addr, value, 1);
188 static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
190 #if defined(DEBUG_MMIO)
191 printf("%s: addr " PADDRX "\n", __func__, addr);
192 #endif
194 return mmio_readlen(opaque, addr, 2);
197 static void mmio_writel (void *opaque,
198 target_phys_addr_t addr, uint32_t value)
200 #if defined(DEBUG_MMIO)
201 printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
202 #endif
203 mmio_writelen(opaque, addr, value, 2);
206 static CPUReadMemoryFunc *mmio_read[] = {
207 &mmio_readb,
208 &mmio_readw,
209 &mmio_readl,
212 static CPUWriteMemoryFunc *mmio_write[] = {
213 &mmio_writeb,
214 &mmio_writew,
215 &mmio_writel,
218 int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
219 target_phys_addr_t offset, uint32_t len,
220 CPUReadMemoryFunc **mem_read,
221 CPUWriteMemoryFunc **mem_write, void *opaque)
223 target_phys_addr_t end;
224 int idx, eidx;
226 if ((offset + len) > TARGET_PAGE_SIZE)
227 return -1;
228 idx = MMIO_IDX(offset);
229 end = offset + len - 1;
230 eidx = MMIO_IDX(end);
231 #if defined(DEBUG_MMIO)
232 printf("%s: offset " PADDRX " len %08" PRIx32 " " PADDRX " %d %d\n",
233 __func__, offset, len, end, idx, eidx);
234 #endif
235 for (; idx <= eidx; idx++) {
236 mmio->mem_read[idx] = mem_read;
237 mmio->mem_write[idx] = mem_write;
238 mmio->opaque[idx] = opaque;
241 return 0;
244 ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
246 ppc4xx_mmio_t *mmio;
247 int mmio_memory;
249 mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
250 if (mmio != NULL) {
251 mmio->base = base;
252 mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
253 #if defined(DEBUG_MMIO)
254 printf("%s: base " PADDRX " len %08x %d\n", __func__,
255 base, TARGET_PAGE_SIZE, mmio_memory);
256 #endif
257 cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
258 ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
259 unassigned_mmio_read, unassigned_mmio_write,
260 mmio);
263 return mmio;
266 /*****************************************************************************/
267 /* "Universal" Interrupt controller */
268 enum {
269 DCR_UICSR = 0x000,
270 DCR_UICSRS = 0x001,
271 DCR_UICER = 0x002,
272 DCR_UICCR = 0x003,
273 DCR_UICPR = 0x004,
274 DCR_UICTR = 0x005,
275 DCR_UICMSR = 0x006,
276 DCR_UICVR = 0x007,
277 DCR_UICVCR = 0x008,
278 DCR_UICMAX = 0x009,
281 #define UIC_MAX_IRQ 32
282 typedef struct ppcuic_t ppcuic_t;
283 struct ppcuic_t {
284 uint32_t dcr_base;
285 int use_vectors;
286 uint32_t level; /* Remembers the state of level-triggered interrupts. */
287 uint32_t uicsr; /* Status register */
288 uint32_t uicer; /* Enable register */
289 uint32_t uiccr; /* Critical register */
290 uint32_t uicpr; /* Polarity register */
291 uint32_t uictr; /* Triggering register */
292 uint32_t uicvcr; /* Vector configuration register */
293 uint32_t uicvr;
294 qemu_irq *irqs;
297 static void ppcuic_trigger_irq (ppcuic_t *uic)
299 uint32_t ir, cr;
300 int start, end, inc, i;
302 /* Trigger interrupt if any is pending */
303 ir = uic->uicsr & uic->uicer & (~uic->uiccr);
304 cr = uic->uicsr & uic->uicer & uic->uiccr;
305 #ifdef DEBUG_UIC
306 if (loglevel & CPU_LOG_INT) {
307 fprintf(logfile, "%s: uicsr %08" PRIx32 " uicer %08" PRIx32
308 " uiccr %08" PRIx32 "\n"
309 " %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
310 __func__, uic->uicsr, uic->uicer, uic->uiccr,
311 uic->uicsr & uic->uicer, ir, cr);
313 #endif
314 if (ir != 0x0000000) {
315 #ifdef DEBUG_UIC
316 if (loglevel & CPU_LOG_INT) {
317 fprintf(logfile, "Raise UIC interrupt\n");
319 #endif
320 qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
321 } else {
322 #ifdef DEBUG_UIC
323 if (loglevel & CPU_LOG_INT) {
324 fprintf(logfile, "Lower UIC interrupt\n");
326 #endif
327 qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
329 /* Trigger critical interrupt if any is pending and update vector */
330 if (cr != 0x0000000) {
331 qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
332 if (uic->use_vectors) {
333 /* Compute critical IRQ vector */
334 if (uic->uicvcr & 1) {
335 start = 31;
336 end = 0;
337 inc = -1;
338 } else {
339 start = 0;
340 end = 31;
341 inc = 1;
343 uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
344 for (i = start; i <= end; i += inc) {
345 if (cr & (1 << i)) {
346 uic->uicvr += (i - start) * 512 * inc;
347 break;
351 #ifdef DEBUG_UIC
352 if (loglevel & CPU_LOG_INT) {
353 fprintf(logfile, "Raise UIC critical interrupt - "
354 "vector %08" PRIx32 "\n", uic->uicvr);
356 #endif
357 } else {
358 #ifdef DEBUG_UIC
359 if (loglevel & CPU_LOG_INT) {
360 fprintf(logfile, "Lower UIC critical interrupt\n");
362 #endif
363 qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
364 uic->uicvr = 0x00000000;
368 static void ppcuic_set_irq (void *opaque, int irq_num, int level)
370 ppcuic_t *uic;
371 uint32_t mask, sr;
373 uic = opaque;
374 mask = 1 << (31-irq_num);
375 #ifdef DEBUG_UIC
376 if (loglevel & CPU_LOG_INT) {
377 fprintf(logfile, "%s: irq %d level %d uicsr %08" PRIx32
378 " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
379 __func__, irq_num, level,
380 uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
382 #endif
383 if (irq_num < 0 || irq_num > 31)
384 return;
385 sr = uic->uicsr;
387 /* Update status register */
388 if (uic->uictr & mask) {
389 /* Edge sensitive interrupt */
390 if (level == 1)
391 uic->uicsr |= mask;
392 } else {
393 /* Level sensitive interrupt */
394 if (level == 1) {
395 uic->uicsr |= mask;
396 uic->level |= mask;
397 } else {
398 uic->uicsr &= ~mask;
399 uic->level &= ~mask;
402 #ifdef DEBUG_UIC
403 if (loglevel & CPU_LOG_INT) {
404 fprintf(logfile, "%s: irq %d level %d sr %" PRIx32 " => "
405 "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
407 #endif
408 if (sr != uic->uicsr)
409 ppcuic_trigger_irq(uic);
412 static target_ulong dcr_read_uic (void *opaque, int dcrn)
414 ppcuic_t *uic;
415 target_ulong ret;
417 uic = opaque;
418 dcrn -= uic->dcr_base;
419 switch (dcrn) {
420 case DCR_UICSR:
421 case DCR_UICSRS:
422 ret = uic->uicsr;
423 break;
424 case DCR_UICER:
425 ret = uic->uicer;
426 break;
427 case DCR_UICCR:
428 ret = uic->uiccr;
429 break;
430 case DCR_UICPR:
431 ret = uic->uicpr;
432 break;
433 case DCR_UICTR:
434 ret = uic->uictr;
435 break;
436 case DCR_UICMSR:
437 ret = uic->uicsr & uic->uicer;
438 break;
439 case DCR_UICVR:
440 if (!uic->use_vectors)
441 goto no_read;
442 ret = uic->uicvr;
443 break;
444 case DCR_UICVCR:
445 if (!uic->use_vectors)
446 goto no_read;
447 ret = uic->uicvcr;
448 break;
449 default:
450 no_read:
451 ret = 0x00000000;
452 break;
455 return ret;
458 static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
460 ppcuic_t *uic;
462 uic = opaque;
463 dcrn -= uic->dcr_base;
464 #ifdef DEBUG_UIC
465 if (loglevel & CPU_LOG_INT) {
466 fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
468 #endif
469 switch (dcrn) {
470 case DCR_UICSR:
471 uic->uicsr &= ~val;
472 uic->uicsr |= uic->level;
473 ppcuic_trigger_irq(uic);
474 break;
475 case DCR_UICSRS:
476 uic->uicsr |= val;
477 ppcuic_trigger_irq(uic);
478 break;
479 case DCR_UICER:
480 uic->uicer = val;
481 ppcuic_trigger_irq(uic);
482 break;
483 case DCR_UICCR:
484 uic->uiccr = val;
485 ppcuic_trigger_irq(uic);
486 break;
487 case DCR_UICPR:
488 uic->uicpr = val;
489 break;
490 case DCR_UICTR:
491 uic->uictr = val;
492 ppcuic_trigger_irq(uic);
493 break;
494 case DCR_UICMSR:
495 break;
496 case DCR_UICVR:
497 break;
498 case DCR_UICVCR:
499 uic->uicvcr = val & 0xFFFFFFFD;
500 ppcuic_trigger_irq(uic);
501 break;
505 static void ppcuic_reset (void *opaque)
507 ppcuic_t *uic;
509 uic = opaque;
510 uic->uiccr = 0x00000000;
511 uic->uicer = 0x00000000;
512 uic->uicpr = 0x00000000;
513 uic->uicsr = 0x00000000;
514 uic->uictr = 0x00000000;
515 if (uic->use_vectors) {
516 uic->uicvcr = 0x00000000;
517 uic->uicvr = 0x0000000;
521 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
522 uint32_t dcr_base, int has_ssr, int has_vr)
524 ppcuic_t *uic;
525 int i;
527 uic = qemu_mallocz(sizeof(ppcuic_t));
528 if (uic != NULL) {
529 uic->dcr_base = dcr_base;
530 uic->irqs = irqs;
531 if (has_vr)
532 uic->use_vectors = 1;
533 for (i = 0; i < DCR_UICMAX; i++) {
534 ppc_dcr_register(env, dcr_base + i, uic,
535 &dcr_read_uic, &dcr_write_uic);
537 qemu_register_reset(ppcuic_reset, uic);
538 ppcuic_reset(uic);
541 return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
547 #define PCIC0_CFGADDR 0x0
548 #define PCIC0_CFGDATA 0x4
550 #define PCIL0_PMM0LA 0x0
551 #define PCIL0_PMM0MA 0x4
552 #define PCIL0_PMM0PCILA 0x8
553 #define PCIL0_PMM0PCIHA 0xc
554 #define PCIL0_PMM1LA 0x10
555 #define PCIL0_PMM1MA 0x14
556 #define PCIL0_PMM1PCILA 0x18
557 #define PCIL0_PMM1PCIHA 0x1c
558 #define PCIL0_PMM2LA 0x20
559 #define PCIL0_PMM2MA 0x24
560 #define PCIL0_PMM2PCILA 0x28
561 #define PCIL0_PMM2PCIHA 0x2c
562 #define PCIL0_PTM1MS 0x30
563 #define PCIL0_PTM1LA 0x34
564 #define PCIL0_PTM2MS 0x38
565 #define PCIL0_PTM2LA 0x3c
566 #define PCI_REG_SIZE 0x40
568 #define PPC44x_PCI_MA_MASK 0xfffff000
569 #define PPC44x_PCI_MA_ENABLE 0x1
572 static uint32_t pci4xx_cfgaddr_read4(void *opaque, target_phys_addr_t addr)
574 ppc4xx_pci_t *ppc4xx_pci = opaque;
575 return cpu_to_le32(ppc4xx_pci->pcic0_cfgaddr);
578 static CPUReadMemoryFunc *pci4xx_cfgaddr_read[] = {
579 &pci4xx_cfgaddr_read4,
580 &pci4xx_cfgaddr_read4,
581 &pci4xx_cfgaddr_read4,
584 static void pci4xx_cfgaddr_write4(void *opaque, target_phys_addr_t addr,
585 uint32_t value)
587 ppc4xx_pci_t *ppc4xx_pci = opaque;
589 value = le32_to_cpu(value);
591 ppc4xx_pci->pcic0_cfgaddr = value & ~0x3;
594 static CPUWriteMemoryFunc *pci4xx_cfgaddr_write[] = {
595 &pci4xx_cfgaddr_write4,
596 &pci4xx_cfgaddr_write4,
597 &pci4xx_cfgaddr_write4,
600 static uint32_t pci4xx_cfgdata_read1(void *opaque, target_phys_addr_t addr)
602 ppc4xx_pci_t *ppc4xx_pci = opaque;
603 int offset = addr & 0x3;
604 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
605 uint32_t value;
607 if (!(cfgaddr & (1<<31)))
608 return 0xffffffff;
610 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 1);
612 return value;
615 static uint32_t pci4xx_cfgdata_read2(void *opaque, target_phys_addr_t addr)
617 ppc4xx_pci_t *ppc4xx_pci = opaque;
618 int offset = addr & 0x3;
619 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
620 uint32_t value;
622 if (!(cfgaddr & (1<<31)))
623 return 0xffffffff;
625 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 2);
627 return cpu_to_le16(value);
630 static uint32_t pci4xx_cfgdata_read4(void *opaque, target_phys_addr_t addr)
632 ppc4xx_pci_t *ppc4xx_pci = opaque;
633 int offset = addr & 0x3;
634 uint32_t cfgaddr = ppc4xx_pci->pcic0_cfgaddr;
635 uint32_t value;
637 if (!(cfgaddr & (1<<31)))
638 return 0xffffffff;
640 value = pci_data_read(ppc4xx_pci->bus, cfgaddr | offset, 4);
642 return cpu_to_le32(value);
645 static CPUReadMemoryFunc *pci4xx_cfgdata_read[] = {
646 &pci4xx_cfgdata_read1,
647 &pci4xx_cfgdata_read2,
648 &pci4xx_cfgdata_read4,
651 static void pci4xx_cfgdata_write1(void *opaque, target_phys_addr_t addr,
652 uint32_t value)
654 ppc4xx_pci_t *ppc4xx_pci = opaque;
655 int offset = addr & 0x3;
657 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
658 value, 1);
661 static void pci4xx_cfgdata_write2(void *opaque, target_phys_addr_t addr,
662 uint32_t value)
664 ppc4xx_pci_t *ppc4xx_pci = opaque;
665 int offset = addr & 0x3;
667 value = le16_to_cpu(value);
669 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
670 value, 2);
673 static void pci4xx_cfgdata_write4(void *opaque, target_phys_addr_t addr,
674 uint32_t value)
676 ppc4xx_pci_t *ppc4xx_pci = opaque;
677 int offset = addr & 0x3;
679 value = le32_to_cpu(value);
681 pci_data_write(ppc4xx_pci->bus, ppc4xx_pci->pcic0_cfgaddr | offset,
682 value, 4);
685 static CPUWriteMemoryFunc *pci4xx_cfgdata_write[] = {
686 &pci4xx_cfgdata_write1,
687 &pci4xx_cfgdata_write2,
688 &pci4xx_cfgdata_write4,
691 static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
692 uint32_t value)
694 struct ppc4xx_pci_t *pci = opaque;
695 unsigned long offset = addr - pci->registers;
697 value = le32_to_cpu(value);
699 switch (offset) {
700 case PCIL0_PMM0LA:
701 pci->pmm[0].la = value;
702 break;
703 case PCIL0_PMM1LA:
704 pci->pmm[0].la = value;
705 break;
706 case PCIL0_PMM2LA:
707 pci->pmm[0].la = value;
708 break;
709 default:
710 //printf(" unhandled PCI internal register 0x%lx\n", offset);
711 break;
715 static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
717 struct ppc4xx_pci_t *pci = opaque;
718 unsigned long offset = addr - pci->registers;
719 uint32_t value;
721 switch (offset) {
722 case PCIL0_PMM0LA:
723 value = pci->pmm[0].la;
724 break;
725 case PCIL0_PMM0MA:
726 value = pci->pmm[0].ma;
727 break;
728 case PCIL0_PMM0PCIHA:
729 value = pci->pmm[0].pciha;
730 break;
731 case PCIL0_PMM0PCILA:
732 value = pci->pmm[0].pcila;
733 break;
735 case PCIL0_PMM1LA:
736 value = pci->pmm[1].la;
737 break;
738 case PCIL0_PMM1MA:
739 value = pci->pmm[1].ma;
740 break;
741 case PCIL0_PMM1PCIHA:
742 value = pci->pmm[1].pciha;
743 break;
744 case PCIL0_PMM1PCILA:
745 value = pci->pmm[1].pcila;
746 break;
748 case PCIL0_PMM2LA:
749 value = pci->pmm[2].la;
750 break;
751 case PCIL0_PMM2MA:
752 value = pci->pmm[2].ma;
753 break;
754 case PCIL0_PMM2PCIHA:
755 value = pci->pmm[2].pciha;
756 break;
757 case PCIL0_PMM2PCILA:
758 value = pci->pmm[2].pcila;
759 break;
761 case PCIL0_PTM1MS:
762 value = pci->ptm[0].ms;
763 break;
764 case PCIL0_PTM1LA:
765 value = pci->ptm[0].la;
766 break;
767 case PCIL0_PTM2MS:
768 value = pci->ptm[1].ms;
769 break;
770 case PCIL0_PTM2LA:
771 value = pci->ptm[1].la;
772 break;
774 default:
775 //printf(" read from invalid PCI internal register 0x%lx\n", offset);
776 value = 0;
779 value = cpu_to_le32(value);
781 return value;
784 static CPUReadMemoryFunc *pci_reg_read[] = {
785 &pci_reg_read4,
786 &pci_reg_read4,
787 &pci_reg_read4,
790 static CPUWriteMemoryFunc *pci_reg_write[] = {
791 &pci_reg_write4,
792 &pci_reg_write4,
793 &pci_reg_write4,
796 static uint32_t pci_int_ack_read4(void *opaque, target_phys_addr_t addr)
798 printf("%s\n", __func__);
799 return 0;
802 static CPUReadMemoryFunc *pci_int_ack_read[] = {
803 &pci_int_ack_read4,
804 &pci_int_ack_read4,
805 &pci_int_ack_read4,
808 static void pci_special_write4(void *opaque, target_phys_addr_t addr,
809 uint32_t value)
811 printf("%s\n", __func__);
814 static CPUWriteMemoryFunc *pci_special_write[] = {
815 &pci_special_write4,
816 &pci_special_write4,
817 &pci_special_write4,
820 static int bamboo_pci_map_irq(PCIDevice *pci_dev, int irq_num)
822 int slot = pci_dev->devfn >> 3;
824 #if 0
825 printf("### %s: devfn %x irq %d -> %d\n", __func__,
826 pci_dev->devfn, irq_num, slot+1);
827 #endif
829 /* All pins from each slot are tied to a single board IRQ (2-5) */
830 return slot + 1;
833 static void bamboo_pci_set_irq(qemu_irq *pic, int irq_num, int level)
835 #if 0
836 printf("### %s: PCI irq %d, UIC irq %d\n", __func__, irq_num, 30 - irq_num);
837 #endif
839 /* Board IRQs 2-5 are connected to UIC IRQs 28-25 */
840 qemu_set_irq(pic[30-irq_num], level);
843 /* XXX Needs some abstracting for boards other than Bamboo. */
844 ppc4xx_pci_t *ppc4xx_pci_init(CPUState *env, qemu_irq *pic,
845 target_phys_addr_t config_space,
846 target_phys_addr_t int_ack,
847 target_phys_addr_t special_cycle,
848 target_phys_addr_t registers)
850 ppc4xx_pci_t *pci;
851 PCIDevice *d;
852 int index;
854 pci = qemu_mallocz(sizeof(ppc4xx_pci_t));
855 if (!pci)
856 return NULL;
858 pci->config_space = config_space;
859 pci->registers = registers;
860 pci->pic = pic;
862 pci->bus = pci_register_bus(bamboo_pci_set_irq, bamboo_pci_map_irq,
863 pic, 0, 4);
864 d = pci_register_device(pci->bus, "host bridge", sizeof(PCIDevice),
865 0, NULL, NULL);
866 d->config[0x00] = 0x14; // vendor_id
867 d->config[0x01] = 0x10;
868 d->config[0x02] = 0x7f; // device_id
869 d->config[0x03] = 0x02;
870 d->config[0x0a] = 0x80; // class_sub = other bridge type
871 d->config[0x0b] = 0x06; // class_base = PCI_bridge
873 /* CFGADDR */
874 index = cpu_register_io_memory(0, pci4xx_cfgaddr_read,
875 pci4xx_cfgaddr_write, pci);
876 if (index < 0)
877 goto free;
878 cpu_register_physical_memory(config_space, 4, index);
880 /* CFGDATA */
881 index = cpu_register_io_memory(0, pci4xx_cfgdata_read,
882 pci4xx_cfgdata_write, pci);
883 if (index < 0)
884 goto free;
885 cpu_register_physical_memory(config_space + 4, 4, index);
887 /* "Special cycle" and interrupt acknowledge */
888 index = cpu_register_io_memory(0, pci_int_ack_read,
889 pci_special_write, pci);
890 if (index < 0)
891 goto free;
892 cpu_register_physical_memory(int_ack, 4, index);
894 /* Internal registers */
895 index = cpu_register_io_memory(0, pci_reg_read, pci_reg_write, pci);
896 if (index < 0)
897 goto free;
898 cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
900 /* XXX register_savevm() */
902 return pci;
904 free:
905 printf("%s error\n", __func__);
906 qemu_free(pci);
907 return NULL;