patch-2.4.4 linux/arch/sparc64/kernel/pci_sabre.c

Next file: linux/arch/sparc64/kernel/pci_schizo.c
Previous file: linux/arch/sparc64/kernel/pci_psycho.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.25 2001/02/28 03:28:55 davem Exp $
+/* $Id: pci_sabre.c,v 1.27 2001/04/24 05:14:12 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -215,6 +215,8 @@
 	 ((unsigned long)(DEVFN) << 8)  |	\
 	 ((unsigned long)(REG)))
 
+static int apb_present;
+
 static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
 				     unsigned char bus,
 				     unsigned int devfn,
@@ -229,6 +231,9 @@
 
 static int sabre_out_of_range(unsigned char devfn)
 {
+	if (!apb_present)
+		return 0;
+
 	return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
 		((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
 		(PCI_SLOT(devfn) > 1));
@@ -238,6 +243,9 @@
 				unsigned char bus,
 				unsigned char devfn)
 {
+	if (!apb_present)
+		return 0;
+
 	return ((pbm->parent == 0) ||
 		((pbm == &pbm->parent->pbm_B) &&
 		 (bus == pbm->pci_first_busno) &&
@@ -774,6 +782,8 @@
 		(SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR |
 		 SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |
 		 SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE);
+	if (!error_bits)
+		return;
 	sabre_write(afsr_reg, error_bits);
 
 	/* Log the error. */
@@ -829,6 +839,8 @@
 	error_bits = afsr &
 		(SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |
 		 SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR);
+	if (!error_bits)
+		return;
 	sabre_write(afsr_reg, error_bits);
 
 	/* Log the error. */
@@ -885,6 +897,8 @@
 		 SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR |
 		 SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA |
 		 SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR);
+	if (!error_bits)
+		return;
 	sabre_write(afsr_reg, error_bits);
 
 	/* Log the error. */
@@ -1102,7 +1116,9 @@
 {
 	static int once = 0;
 	struct pci_bus *sabre_bus;
+	struct pci_pbm_info *pbm;
 	struct list_head *walk;
+	int sabres_scanned;
 
 	/* The APB bridge speaks to the Sabre host PCI bridge
 	 * at 66Mhz, but the front side of APB runs at 33Mhz
@@ -1132,10 +1148,11 @@
 				 &p->pbm_A);
 	apb_init(p, sabre_bus);
 
+	sabres_scanned = 0;
+
 	walk = &sabre_bus->children;
 	for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
 		struct pci_bus *pbus = pci_bus_b(walk);
-		struct pci_pbm_info *pbm;
 
 		if (pbus->number == p->pbm_A.pci_first_busno) {
 			pbm = &p->pbm_A;
@@ -1144,6 +1161,8 @@
 		} else
 			continue;
 
+		sabres_scanned++;
+
 		pbus->sysdata = pbm;
 		pbm->pci_bus = pbus;
 		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);
@@ -1154,6 +1173,19 @@
 		pci_setup_busmastering(pbm, pbus);
 	}
 
+	if (!sabres_scanned) {
+		/* Hummingbird, no APBs. */
+		pbm = &p->pbm_A;
+		sabre_bus->sysdata = pbm;
+		pbm->pci_bus = sabre_bus;
+		pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node);
+		pci_record_assignments(pbm, sabre_bus);
+		pci_assign_unassigned(pbm, sabre_bus);
+		pci_fixup_irq(pbm, sabre_bus);
+		pci_determine_66mhz_disposition(pbm, sabre_bus);
+		pci_setup_busmastering(pbm, sabre_bus);
+	}
+
 	sabre_register_error_handlers(p);
 }
 
@@ -1296,15 +1328,16 @@
 	}
 }
 
-static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node)
+static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
 {
+	struct pci_pbm_info *pbm;
 	char namebuf[128];
 	u32 busrange[2];
-	int node;
+	int node, simbas_found;
 
+	simbas_found = 0;
 	node = prom_getchild(sabre_node);
 	while ((node = prom_searchsiblings(node, "pci")) != 0) {
-		struct pci_pbm_info *pbm;
 		int err;
 
 		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
@@ -1318,6 +1351,7 @@
 			prom_halt();
 		}
 
+		simbas_found++;
 		if (busrange[0] == 1)
 			pbm = &p->pbm_B;
 		else
@@ -1366,6 +1400,70 @@
 		if (!node)
 			break;
 	}
+	if (simbas_found == 0) {
+		int err;
+
+		/* No APBs underneath, probably this is a hummingbird
+		 * system.
+		 */
+		pbm = &p->pbm_A;
+		pbm->parent = p;
+		pbm->prom_node = sabre_node;
+		pbm->pci_first_busno = p->pci_first_busno;
+		pbm->pci_last_busno = p->pci_last_busno;
+		for (err = pbm->pci_first_busno;
+		     err <= pbm->pci_last_busno;
+		     err++)
+			pci_bus2pbm[err] = pbm;
+
+		prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name));
+		err = prom_getproperty(sabre_node, "ranges",
+				       (char *) pbm->pbm_ranges,
+				       sizeof(pbm->pbm_ranges));
+		if (err != -1)
+			pbm->num_pbm_ranges =
+				(err / sizeof(struct linux_prom_pci_ranges));
+		else
+			pbm->num_pbm_ranges = 0;
+
+		err = prom_getproperty(sabre_node, "interrupt-map",
+				       (char *) pbm->pbm_intmap,
+				       sizeof(pbm->pbm_intmap));
+
+		if (err != -1) {
+			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
+			err = prom_getproperty(sabre_node, "interrupt-map-mask",
+					       (char *)&pbm->pbm_intmask,
+					       sizeof(pbm->pbm_intmask));
+			if (err == -1) {
+				prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");
+				prom_halt();
+			}
+		} else {
+			pbm->num_pbm_intmap = 0;
+			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
+		}
+
+		/* Hack up top-level resources. */
+		pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;
+		pbm->io_space.end   = pbm->io_space.start + (1UL << 16) - 1UL;
+		pbm->io_space.flags = IORESOURCE_IO;
+
+		pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE;
+		pbm->mem_space.end   = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
+		pbm->mem_space.flags = IORESOURCE_MEM;
+
+		if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
+			prom_printf("Cannot register Hummingbird's IO space.\n");
+			prom_halt();
+		}
+		if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {
+			prom_printf("Cannot register Hummingbird's MEM space.\n");
+			prom_halt();
+		}
+	} else {
+		apb_present = 1;
+	}
 }
 
 void __init sabre_init(int pnode)
@@ -1493,5 +1591,5 @@
 	/*
 	 * Look for APB underneath.
 	 */
-	sabre_pbm_init(p, pnode);
+	sabre_pbm_init(p, pnode, vdma[0]);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)