|
@@ -208,3 +208,111 @@ mcpcia_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|
|
case 1:
|
|
|
*value = __kernel_extbl(w, where & 3);
|
|
|
break;
|
|
|
+ case 2:
|
|
|
+ *value = __kernel_extwl(w, where & 3);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ *value = w;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return PCIBIOS_SUCCESSFUL;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+mcpcia_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|
|
+ int size, u32 value)
|
|
|
+{
|
|
|
+ struct pci_controller *hose = bus->sysdata;
|
|
|
+ unsigned long addr;
|
|
|
+ unsigned char type1;
|
|
|
+
|
|
|
+ if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
|
|
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
|
|
+
|
|
|
+ addr |= (size - 1) * 8;
|
|
|
+ value = __kernel_insql(value, where & 3);
|
|
|
+ conf_write(addr, value, type1, hose);
|
|
|
+ return PCIBIOS_SUCCESSFUL;
|
|
|
+}
|
|
|
+
|
|
|
+struct pci_ops mcpcia_pci_ops =
|
|
|
+{
|
|
|
+ .read = mcpcia_read_config,
|
|
|
+ .write = mcpcia_write_config,
|
|
|
+};
|
|
|
+
|
|
|
+void
|
|
|
+mcpcia_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
|
|
|
+{
|
|
|
+ wmb();
|
|
|
+ *(vuip)MCPCIA_SG_TBIA(MCPCIA_HOSE2MID(hose->index)) = 0;
|
|
|
+ mb();
|
|
|
+}
|
|
|
+
|
|
|
+static int __init
|
|
|
+mcpcia_probe_hose(int h)
|
|
|
+{
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+ int mid = MCPCIA_HOSE2MID(h);
|
|
|
+ unsigned int pci_rev;
|
|
|
+
|
|
|
+ /* Gotta be REAL careful. If hose is absent, we get an mcheck. */
|
|
|
+
|
|
|
+ mb();
|
|
|
+ mb();
|
|
|
+ draina();
|
|
|
+ wrmces(7);
|
|
|
+
|
|
|
+ mcheck_expected(cpu) = 2; /* indicates probing */
|
|
|
+ mcheck_taken(cpu) = 0;
|
|
|
+ mcheck_extra(cpu) = mid;
|
|
|
+ mb();
|
|
|
+
|
|
|
+ /* Access the bus revision word. */
|
|
|
+ pci_rev = *(vuip)MCPCIA_REV(mid);
|
|
|
+
|
|
|
+ mb();
|
|
|
+ mb(); /* magic */
|
|
|
+ if (mcheck_taken(cpu)) {
|
|
|
+ mcheck_taken(cpu) = 0;
|
|
|
+ pci_rev = 0xffffffff;
|
|
|
+ mb();
|
|
|
+ }
|
|
|
+ mcheck_expected(cpu) = 0;
|
|
|
+ mb();
|
|
|
+
|
|
|
+ return (pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST;
|
|
|
+}
|
|
|
+
|
|
|
+static void __init
|
|
|
+mcpcia_new_hose(int h)
|
|
|
+{
|
|
|
+ struct pci_controller *hose;
|
|
|
+ struct resource *io, *mem, *hae_mem;
|
|
|
+ int mid = MCPCIA_HOSE2MID(h);
|
|
|
+
|
|
|
+ hose = alloc_pci_controller();
|
|
|
+ if (h == 0)
|
|
|
+ pci_isa_hose = hose;
|
|
|
+ io = alloc_resource();
|
|
|
+ mem = alloc_resource();
|
|
|
+ hae_mem = alloc_resource();
|
|
|
+
|
|
|
+ hose->io_space = io;
|
|
|
+ hose->mem_space = hae_mem;
|
|
|
+ hose->sparse_mem_base = MCPCIA_SPARSE(mid) - IDENT_ADDR;
|
|
|
+ hose->dense_mem_base = MCPCIA_DENSE(mid) - IDENT_ADDR;
|
|
|
+ hose->sparse_io_base = MCPCIA_IO(mid) - IDENT_ADDR;
|
|
|
+ hose->dense_io_base = 0;
|
|
|
+ hose->config_space_base = MCPCIA_CONF(mid);
|
|
|
+ hose->index = h;
|
|
|
+
|
|
|
+ io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS;
|
|
|
+ io->end = io->start + 0xffff;
|
|
|
+ io->name = pci_io_names[h];
|
|
|
+ io->flags = IORESOURCE_IO;
|
|
|
+
|
|
|
+ mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS;
|
|
|
+ mem->end = mem->start + 0xffffffff;
|
|
|
+ mem->name = pci_mem_names[h];
|
|
|
+ mem->flags = IORESOURCE_MEM;
|