patch-pre2.0.8 linux/arch/ppc/kernel/pci.c

Next file: linux/arch/ppc/kernel/port_io.c
Previous file: linux/arch/ppc/kernel/no_ramdisk.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.7/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
@@ -1,5 +1,9 @@
 /*
  * PCI support
+ * -- rough emulation of "PCI BIOS" functions
+ *
+ * Note: these are very motherboard specific!  Some way needs to
+ * be worked out to handle the differences.
  */
 
 #include <linux/config.h>
@@ -7,15 +11,149 @@
 #include <linux/bios32.h>
 #include <linux/pci.h>
 
+/*
+ * PCI interrupt configuration.  This is motherboard specific.
+ */
+ 
+ 
+/* Which PCI interrupt line does a given device [slot] use? */
+/* Note: This really should be two dimensional based in slot/pin used */
+unsigned char *Motherboard_map;
+
+/* How is the 82378 PIRQ mapping setup? */
+unsigned char *Motherboard_routes;
+
+/* Tables for known hardware */   
+
+/* Motorola PowerStack */
+static char Blackhawk_pci_IRQ_map[16] =
+  {
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+  };
+
+static char Blackhawk_pci_IRQ_routes[] =
+   {
+   	0,	/* Line 0 - Unused */
+   	9,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+   };
+   
+/* Motorola MVME16xx */
+static char Genesis_pci_IRQ_map[16] =
+  {
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+  };
+
+static char Genesis_pci_IRQ_routes[] =
+   {
+   	0,	/* Line 0 - Unused */
+   	10,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+   };
+   
+/* Motorola Series-E */
+static char Comet_pci_IRQ_map[16] =
+  {
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+  };
+
+static char Comet_pci_IRQ_routes[] =
+   {
+   	0,	/* Line 0 - Unused */
+   	10,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+   };
+
+/* BeBox */
+static char BeBox_pci_IRQ_map[16] =
+  {
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	16,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	0,	/* Slot 14 - unused */
+  	0,	/* Slot 15 - unused */
+  };
+
+static char BeBox_pci_IRQ_routes[] =
+   {
+   	0,	/* Line 0 - Unused */
+   	9,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+   };
+
 /* #define PCI_DEBUG */
 
+#ifdef PCI_STATS
 int PCI_conversions[2];
+#endif
 
 unsigned long pcibios_init(unsigned long mem_start,
 			   unsigned long mem_end)
 {
-	printk("PPC init stub -- cort\n");
-
 	return mem_start;
 }
 
@@ -24,11 +162,14 @@
   return mem_start;
 }
 
+
 unsigned long
 _LE_to_BE_long(unsigned long val)
 {
 	unsigned char *p = (unsigned char *)&val;
+#ifdef PCI_STATS
 	PCI_conversions[0]++;
+#endif	
 	return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0));
 }
 
@@ -36,7 +177,9 @@
 _LE_to_BE_short(unsigned long val)
 {
 	unsigned char *p = (unsigned char *)&val;
+#ifdef PCI_STATS
 	PCI_conversions[1]++;
+#endif	
 	return ((p[3] << 8) | (p[2] << 0));
 }
 
@@ -44,7 +187,7 @@
 pcibios_present (void)
 {
 #ifdef PCI_DEBUG	
-	_printk("PCI [BIOS] present?\n");
+	printk("PCI [BIOS] present?\n");
 #endif	
 	return (1);
 }
@@ -57,7 +200,7 @@
 	unsigned long *ptr;
 	dev >>= 3;
 #ifdef PCI_DEBUG	
-	_printk("PCI Read config dword[%d.%d.%x] = ", bus, dev, offset);
+	printk("PCI Read config dword[%d.%d.%x] = ", bus, dev, offset);
 #endif	
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
@@ -67,12 +210,12 @@
 	{
 		ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset);
 #ifdef PCI_DEBUG	
-		_printk("[%x] ", ptr);
+		printk("[%x] ", ptr);
 #endif		
 		_val = _LE_to_BE_long(*ptr);
 	}
 #ifdef PCI_DEBUG	
-	_printk("%x\n", _val);
+	printk("%x\n", _val);
 #endif	
 	*val = _val;
 	return PCIBIOS_SUCCESSFUL;
@@ -86,22 +229,22 @@
 	unsigned short *ptr;
 	dev >>= 3;
 #ifdef PCI_DEBUG	
-	_printk("PCI Read config word[%d.%d.%x] = ", bus, dev, offset);
+	printk("PCI Read config word[%d.%d.%x] = ", bus, dev, offset);
 #endif	
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
-		*val =(unsigned short) 0xFFFFFFFF;
+		*val = 0xFFFFFFFF;
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	} else
 	{
 		ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset);
 #ifdef PCI_DEBUG	
-		_printk("[%x] ", ptr);
+		printk("[%x] ", ptr);
 #endif		
 		_val = _LE_to_BE_short(*ptr);
 	}
 #ifdef PCI_DEBUG	
-	_printk("%x\n", _val);
+	printk("%x\n", _val);
 #endif		
 	*val = _val;
 	return PCIBIOS_SUCCESSFUL;
@@ -112,26 +255,41 @@
     unsigned char dev, unsigned char offset, unsigned char *val)
 {
 	unsigned char _val;
-	unsigned char *ptr;
+	volatile unsigned char *ptr;
 	dev >>= 3;
+	/* Note: the configuration registers don't always have this right! */
+	if (offset == PCI_INTERRUPT_LINE)
+	{
+		if (Motherboard_map[dev] <= 4)
+		{
+			*val = Motherboard_routes[Motherboard_map[dev]];
+		} else
+		{ /* Pseudo interrupts [for BeBox] */
+			*val = Motherboard_map[dev];
+		}
 #ifdef PCI_DEBUG	
-	_printk("PCI Read config byte[%d.%d.%x] = ", bus, dev, offset);
+		printk("PCI Read Interrupt Line[%d.%d] = %d\n", bus, dev, *val);
+#endif		
+		return PCIBIOS_SUCCESSFUL;
+	}
+#ifdef PCI_DEBUG	
+	printk("PCI Read config byte[%d.%d.%x] = ", bus, dev, offset);
 #endif		
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
-		*val = (unsigned char) 0xFFFFFFFF;
+		*val = 0xFFFFFFFF;
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	} else
 	{
 		ptr = (unsigned char *)(0x80800000 | (1<<dev) | offset ^ 1);
 #ifdef PCI_DEBUG	
-		_printk("[%x] ", ptr);
+		printk("[%x] ", ptr);
 #endif		
 		_val = *ptr;
 	}
 #ifdef PCI_DEBUG	
-	_printk("%x\n", _val);
-#endif		
+	printk("%x\n", _val);
+#endif
 	*val = _val;
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -145,7 +303,7 @@
 	dev >>= 3;
 	_val = _LE_to_BE_long(val);
 #ifdef PCI_DEBUG	
-	_printk("PCI Write config dword[%d.%d.%x] = %x\n", bus, dev, offset, _val);
+	printk("PCI Write config dword[%d.%d.%x] = %x\n", bus, dev, offset, _val);
 #endif		
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
@@ -167,7 +325,7 @@
 	dev >>= 3;
 	_val = _LE_to_BE_short(val);
 #ifdef PCI_DEBUG	
-	_printk("PCI Write config word[%d.%d.%x] = %x\n", bus, dev, offset, _val);
+	printk("PCI Write config word[%d.%d.%x] = %x\n", bus, dev, offset, _val);
 #endif		
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
@@ -189,7 +347,7 @@
 	dev >>= 3;
 	_val = val;
 #ifdef PCI_DEBUG	
-	_printk("PCI Write config byte[%d.%d.%x] = %x\n", bus, dev, offset, _val);
+	printk("PCI Write config byte[%d.%d.%x] = %x\n", bus, dev, offset, _val);
 #endif		
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
@@ -207,7 +365,7 @@
 		     unsigned short index, unsigned char *bus,
 		     unsigned char *dev)
 {
-	unsigned int w, desired = (device_id << 16) | vendor;
+	unsigned long w, desired = (device_id << 16) | vendor;
 	int devnr;
 
 	if (vendor == 0xffff) {
@@ -233,9 +391,98 @@
 pcibios_find_class (unsigned int class_code, unsigned short index, 
     unsigned char *bus, unsigned char *dev)
 {
-	printk("pcibios_find_class\n");
-	return PCIBIOS_FUNC_NOT_SUPPORTED;
+	int dev_nr, class, indx;
+	indx = 0;
+#ifdef PCI_DEBUG	
+	printk("pcibios_find_class - class: %x, index: %x", class_code, index);
+#endif	
+	for (dev_nr = 11;  dev_nr < 16;  dev_nr++)
+	{
+		pcibios_read_config_dword(0, dev_nr<<3, PCI_CLASS_REVISION, &class);
+		if ((class>>8) == class_code)
+		{
+			if (index == indx)
+			{
+				*bus = 0;
+				*dev = dev_nr<<3;
+#ifdef PCI_DEBUG
+	printk(" - device: %x\n", dev_nr);
+#endif	
+				return (0);
+			}
+			indx++;
+		}
+	}
+#ifdef PCI_DEBUG
+	printk(" - not found\n");
+#endif	
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }    
 
-const char *pcibios_strerror(int error) { _panic("pcibios_strerror"); } 
-/*int get_pci_list(char *buf) { _panic("get_pci_list"); } */
+const char *pcibios_strerror(int error)
+{
+	static char buf[32];
+	switch (error)
+	{	case PCIBIOS_SUCCESSFUL:
+			return ("PCI BIOS: no error");
+		case PCIBIOS_FUNC_NOT_SUPPORTED:
+			return ("PCI BIOS: function not supported");
+		case PCIBIOS_BAD_VENDOR_ID:
+			return ("PCI BIOS: bad vendor ID");
+		case PCIBIOS_DEVICE_NOT_FOUND:
+			return ("PCI BIOS: device not found");
+		case PCIBIOS_BAD_REGISTER_NUMBER:
+			return ("PCI BIOS: bad register number");
+		case PCIBIOS_SET_FAILED:
+			return ("PCI BIOS: set failed");
+		case PCIBIOS_BUFFER_TOO_SMALL:
+			return ("PCI BIOS: buffer too small");
+		default:
+			sprintf(buf, "PCI BIOS: invalid error #%d", error);
+			return(buf);
+	}
+}
+
+/*
+ * Note: This routine has to access the PCI configuration space
+ * for the PCI bridge chip (Intel 82378).
+ */
+ 
+void route_PCI_interrupts(void)
+{
+	unsigned char *ibc_pirq = (unsigned char *)0x80800860;
+	unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
+	extern unsigned long isBeBox[];
+	int i;
+	/* Decide which motherboard this is & how the PCI interrupts are routed */
+	if (isBeBox[0])
+	{
+		Motherboard_map = BeBox_pci_IRQ_map;
+		Motherboard_routes = BeBox_pci_IRQ_routes;
+	} else
+	{ /* Motorola hardware */
+		switch (inb(0x800) & 0xF0)
+		{
+			case 0x10: /* MVME16xx */
+				Motherboard_map = Genesis_pci_IRQ_map;
+				Motherboard_routes = Genesis_pci_IRQ_routes;
+				break;
+			case 0x20: /* Series E */
+				Motherboard_map = Comet_pci_IRQ_map;
+				Motherboard_routes = Comet_pci_IRQ_routes;
+				break;
+			case 0x40: /* PowerStack */
+			default: /* Can't hurt, can it? */
+				Motherboard_map = Blackhawk_pci_IRQ_map;
+				Motherboard_routes = Blackhawk_pci_IRQ_routes;
+				break;
+		}
+	}
+	/* Set up mapping from slots */
+	for (i = 1;  i <= 4;  i++)
+	{
+		ibc_pirq[i-1] = Motherboard_routes[i];
+	}
+	/* Enable PCI interrupts */
+	*ibc_pcicon |= 0x20;
+} 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this