--- trunk/src/devices/dev_mpc10x.c 2007/10/12 19:40:03 60 +++ trunk/src/devices/dev_mpc10x.c 2007/10/12 22:06:53 61 @@ -27,7 +27,8 @@ * * $Id: dev_mpc10x.c,v 1.12 2007/06/15 18:13:04 debug Exp $ * - * COMMENT: IBM mpc10x bridge (PCI and interrupt controller) + * COMMENT: mpc10x bridge (PCI and interrupt controller) + * based on dev_uninorth.c */ #include @@ -42,64 +43,7 @@ #include "memory.h" #include "misc.h" -#include "mpc10xreg.h" - - -struct mpc10x_data { - struct interrupt ppc_irq; /* Connected to the CPU */ - - uint32_t sr; /* Interrupt Status register */ - uint32_t er; /* Interrupt Enable register */ - - struct pci_data *pci_data; /* PCI bus */ -}; - - -void mpc10x_interrupt_assert(struct interrupt *interrupt) -{ - struct mpc10x_data *d = interrupt->extra; - d->sr |= interrupt->line; - if (d->sr & d->er) - INTERRUPT_ASSERT(d->ppc_irq); -} -void mpc10x_interrupt_deassert(struct interrupt *interrupt) -{ - struct mpc10x_data *d = interrupt->extra; - d->sr &= ~interrupt->line; - if (!(d->sr & d->er)) - INTERRUPT_DEASSERT(d->ppc_irq); -} - - -/* - * dev_mpc10x_pci_access(): - * - * Passes PCI indirect addr and data accesses onto bus_pci. - */ -DEVICE_ACCESS(mpc10x_pci) -{ - uint64_t idata = 0, odata = 0; - int bus, dev, func, reg; - struct mpc10x_data *d = extra; - - if (writeflag == MEM_WRITE) { - idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN); - debug("mpc10x_pci WRITE offset 0x%x: 0x%x\n", relative_addr, odata); - } - - debug("relative: %d i: 0x%x o: 0x%x data: %s len: %d\n", relative_addr,idata, odata, data, len ); - - switch (relative_addr) { - case 0: /* Address: */ - bus_pci_decompose_1(idata, &bus, &dev, &func, ®); - bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg); - break; - - case 4: /* Data: */ - bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ? - &odata : &idata, len, writeflag); - break; - } +#if 0 #define PCI_VENDOR_ID_MOTOROLA 0x1057 #define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \ @@ -108,238 +52,127 @@ #define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA) #define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA) - debug("i: 0x%x o: 0x%x\n", idata, odata ); - if (writeflag == MEM_READ) { - memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata); - odata = MPC10X_BRIDGE_8245; - debug("mpc10x_pci READ offset 0x%x: 0x%x\n", relative_addr, odata); - } +#define MPC10X_MAPB_CNFG_ADDR 0xfec00000 +#define MPC10X_MAPB_CNFG_DATA 0xfee00000 - return 1; -} +#define MPC10X_MAPB_ISA_IO_BASE 0xfe000000 +#define MPC10X_MAPB_ISA_MEM_BASE 0x80000000 +#define MPC10X_MAPB_DRAM_OFFSET 0x00000000 +#define MPC10X_MAPB_PCI_IO_START 0x00000000 +#define MPC10X_MAPB_PCI_IO_END (0x00c00000 - 1) +#define MPC10X_MAPB_PCI_MEM_START 0x80000000 +#define MPC10X_MAPB_PCI_MEM_END (0xc0000000 - 1) -/* - * dev_mpc10x_int_access(): - * - * The interrupt controller. - */ -DEVICE_ACCESS(mpc10x_int) -{ - struct mpc10x_data *d = extra; - uint64_t idata = 0, odata = 0; +#define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \ + MPC10X_MAPB_PCI_MEM_START) - if (writeflag == MEM_WRITE) - idata = memory_readmax64(cpu, data, len); +#endif - switch (relative_addr) { +struct mpc10x_data { + int pciirq; - case MPC_UIC_SR: - /* Status register (cleared by writing ones): */ - if (writeflag == MEM_READ) { - odata = d->sr; - } else { - d->sr &= ~idata; - if (!(d->sr & d->er)) - INTERRUPT_DEASSERT(d->ppc_irq); - } - break; + struct pci_data *pci_data; + uint64_t cur_addr; +}; - case MPC_UIC_SRS: - /* Status register set: */ - if (writeflag == MEM_READ) { - fatal("[ mpc10x_int: read from MPC_UIC_SRS? ]\n"); - odata = d->sr; - } else { - d->sr = idata; - if (d->sr & d->er) - INTERRUPT_ASSERT(d->ppc_irq); - else - INTERRUPT_DEASSERT(d->ppc_irq); - } - break; - case MPC_UIC_ER: - /* Enable register: */ - if (writeflag == MEM_READ) { - odata = d->er; - } else { - d->er = idata; - if (d->sr & d->er) - INTERRUPT_ASSERT(d->ppc_irq); - else - INTERRUPT_DEASSERT(d->ppc_irq); - } - break; +DEVICE_ACCESS(mpc10x_addr) +{ + struct mpc10x_data *d = extra; - case MPC_UIC_MSR: - /* Masked status: */ - if (writeflag == MEM_READ) { - odata = d->sr & d->er; + if (writeflag == MEM_WRITE) { + uint64_t idata = memory_readmax64(cpu, data, len + | MEM_PCI_LITTLE_ENDIAN); + int bus, dev, func, reg; + + d->cur_addr = idata; + if (idata == 0) + return 0; + + /* Decompose the Uni-North tag: */ + if (idata & 1) { + idata &= ~1; + bus_pci_decompose_1(idata, &bus, &dev, &func, ®); } else { - fatal("[ mpc10x_int: write to MPC_UIC_MSR? ]\n"); - } - break; + bus = 0; + for (dev=11; dev<32; dev++) + if (idata & (1 << dev)) + break; + if (dev == 32) + fatal("[ dev_mpc10x_addr_access: no dev? " + "idata=0x%08x ]\n", (int)idata); - default:if (writeflag == MEM_WRITE) { - fatal("[ mpc10x_int: unimplemented write to " - "offset 0x%x: data=0x%x ]\n", (int) - relative_addr, (int)idata); - } else { - fatal("[ mpc10x_int: unimplemented read from " - "offset 0x%x ]\n", (int)relative_addr); + func = (idata >> 8) & 7; + reg = idata & 0xff; } - } - - if (writeflag == MEM_READ) - memory_writemax64(cpu, data, len, odata); - - return 1; -} - -/* - * dev_mpc10x_config_access(): - * - * Configuration - */ - -DEVICE_ACCESS(mpc10x_config) -{ - uint64_t idata = 0, odata = 0; - debug("mpc10x_config relative: %d i: 0x%x o: 0x%x data: %x len: %x write: %x w: %x r: %x\n", relative_addr,idata, odata, data, len, writeflag, MEM_WRITE, MEM_READ ); - if (writeflag == MEM_WRITE) { - idata = memory_readmax64(cpu, data, len); - debug("[ mpc10x_config WRITE offset 0x%x: 0x%x odata: 0x%x data: 0x%x len: %d ]\n", relative_addr, idata, odata, data, len); - } - if (writeflag == MEM_READ) { - fatal("[ mpc10x_config: read! ]\n"); + bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg); + } else { + /* TODO: is returning the current address like this + the correct behaviour? */ + memory_writemax64(cpu, data, len | MEM_PCI_LITTLE_ENDIAN, + d->cur_addr); } return 1; } -#define PCI_VENDOR_ID_MOTOROLA 0x1057 -#define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \ - PCI_VENDOR_ID_MOTOROLA) -#define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA) -#define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA) -#define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA) DEVICE_ACCESS(mpc10x_data) { + struct mpc10x_data *d = extra; uint64_t idata = 0, odata = 0; - debug("mpc10x_data: relative: %d i: 0x%x o: 0x%x data: %s len: %d write: %d\n", relative_addr,idata, odata, data, len, writeflag ); - if (writeflag == MEM_WRITE) { + if (writeflag == MEM_WRITE) idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN); - fatal("[ mpc10x_data: write -> %x ]\n", (int)idata); - } - if (writeflag == MEM_READ) { - odata = MPC10X_BRIDGE_8245; + + bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ? &odata : + &idata, len, writeflag); + + if (writeflag == MEM_READ) memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata); - debug("odata = %x\n", (int)odata); - debug("[ mpc10x_data: READ offset 0x%x: 0x%x odata: 0x%x data: 0x%x len: %d ]\n", relative_addr, idata, odata, data, len); - } return 1; } -DEVINIT(mpc10x) +struct pci_data *dev_mpc10x_init(struct machine *machine, struct memory *mem, + uint64_t addr, int isa_irqbase, int pciirq) { struct mpc10x_data *d; - char tmp[300]; - int i; +// char tmp[100]; + uint64_t pci_io_offset, pci_mem_offset; + uint64_t isa_portbase = 0, isa_membase = 0; + uint64_t pci_portbase = 0, pci_membase = 0; CHECK_ALLOCATION(d = malloc(sizeof(struct mpc10x_data))); memset(d, 0, sizeof(struct mpc10x_data)); - /* Connect to the CPU's interrupt pin: */ - INTERRUPT_CONNECT(devinit->interrupt_path, d->ppc_irq); - - /* Register 32 mpc10x interrupts: */ - for (i=0; i<32; i++) { - struct interrupt template; - char n[300]; - snprintf(n, sizeof(n), "%s.mpc10x.%i", - devinit->interrupt_path, i); - memset(&template, 0, sizeof(template)); - template.line = 1 << i; - template.name = n; - template.extra = d; - template.interrupt_assert = mpc10x_interrupt_assert; - template.interrupt_deassert = mpc10x_interrupt_deassert; - interrupt_handler_register(&template); - } - -#define MPC10X_MAPB_CNFG_ADDR 0xfec00000 -#define MPC10X_MAPB_CNFG_DATA 0xfee00000 - -#define MPC10X_MAPB_ISA_IO_BASE 0xfe000000 -#define MPC10X_MAPB_ISA_MEM_BASE 0x80000000 -#define MPC10X_MAPB_DRAM_OFFSET 0x00000000 - -#define MPC10X_MAPB_PCI_IO_START 0x00000000 -#define MPC10X_MAPB_PCI_IO_END (0x00c00000 - 1) -#define MPC10X_MAPB_PCI_MEM_START 0x80000000 -#define MPC10X_MAPB_PCI_MEM_END (0xc0000000 - 1) - -#define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \ - MPC10X_MAPB_PCI_MEM_START) - + d->pciirq = pciirq; + pci_io_offset = 0x00000000ULL; + pci_mem_offset = 0x00000000ULL; + pci_portbase = 0xd0000000ULL; + pci_membase = 0xd1000000ULL; + isa_portbase = 0xd2000000ULL; + isa_membase = 0xd3000000ULL; + + /* Create a PCI bus: */ + d->pci_data = bus_pci_init(machine, "ZZZ_irq_stuff", + pci_io_offset, pci_mem_offset, + pci_portbase, pci_membase, "XXX_pci_irqbase", + isa_portbase, isa_membase, "YYY_isa_irqbase"); + + /* Add the PCI glue for the controller itself: */ + bus_pci_add(machine, d->pci_data, mem, 0, 0x1f, 0, "mpc10x"); + + /* ADDR and DATA configuration ports: */ + memory_device_register(mem, "mpc10x_pci_addr", addr + 0xc00000, + 4, dev_mpc10x_addr_access, d, DM_DEFAULT, NULL); + memory_device_register(mem, "mpc10x_pci_data", addr + 0xe00000, + 8, dev_mpc10x_data_access, d, DM_DEFAULT, NULL); - /* Register a PCI bus: */ - snprintf(tmp, sizeof(tmp), "%s.mpc10x", devinit->interrupt_path); - d->pci_data = bus_pci_init( - devinit->machine, - tmp, /* pciirq path */ - 0x00000000, /* pci device io offset */ - 0x00000000, /* pci device mem offset */ - 0xfe000000, /* PCI portbase */ - 0x80000000, /* PCI membase: TODO */ - tmp, /* PCI irqbase */ - 0xfe000000, /* ISA portbase: TODO */ - 0x80000000, /* ISA membase: TODO */ - tmp); /* ISA irqbase */ - - /* PCI host bridge */ - bus_pci_add(devinit->machine, d->pci_data, - devinit->machine->memory, 0, 0, 0, "mpc10x_host_bridge"); - - /* MPC10x configuration */ - memory_device_register(devinit->machine->memory, "mpc10x_config", - 0xfec00000, 1, dev_mpc10x_config_access, d, DM_DEFAULT, NULL); - memory_device_register(devinit->machine->memory, "mpc10x_data", - 0xfee00000, 8, dev_mpc10x_data_access, d, DM_DEFAULT, NULL); - -#if 0 - /* PCI configuration registers: */ - memory_device_register(devinit->machine->memory, "mpc10x_pci", - 0xfee00000, 8, dev_mpc10x_pci_access, d, DM_DEFAULT, NULL); - - /* Interrupt controller: */ - memory_device_register(devinit->machine->memory, "mpc10x_int", - MPC_UIC_BASE, MPC_UIC_SIZE, dev_mpc10x_int_access, d, - DM_DEFAULT, NULL); -#endif - - /* Two serial ports: */ - snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx " - "name2=tty0", devinit->interrupt_path, 31 - MPC_IB_UART_0, - (long long)MPC_COM0); - devinit->machine->main_console_handle = (size_t) - device_add(devinit->machine, tmp); -#if 0 - snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx " - "name2=tty1", devinit->interrupt_path, 31 - MPC_IB_UART_1, - (long long)MPC_COM1); - device_add(devinit->machine, tmp); -#endif - - devinit->return_ptr = d->pci_data; - - return 1; + return d->pci_data; }