[parisc-linux-cvs] primary sti selection

Thomas Bogendoerfer tsbogend@alpha.franken.de
Sun, 6 Jan 2002 19:53:56 +0100


Hi,

I've implemented a way for selecting the primary sti for console, which
is consistent between sticon and stifb and works (at least for me:-)).
Before I'll commit it, I want to get a little feedback whether it's ok.
Below are two patchsets, the first one is for linux the second one for palo.
The sti selections now uses the kernel parameter sti= for passing the io path
of the wanted sti device. My palo changes will read the console path
and convert that to the right sti= parameter. The linux changes will
take that parameter and decide on the basis, what should be the
primary sti for sticon and stifb.

I've tested the patches on B132 (one VIS-EG), C100 (two HCRX8),
C160 (one VIS-EG and one HCRX24) and C200 (FX6), and everything worked as
expected.

Thomas.


Index: arch/parisc/kernel/drivers.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/drivers.c,v
retrieving revision 1.35
diff -u -p -r1.35 drivers.c
--- arch/parisc/kernel/drivers.c	2001/12/21 23:50:07	1.35
+++ arch/parisc/kernel/drivers.c	2002/01/06 02:50:32
@@ -204,7 +204,7 @@ get_node_path(struct parisc_device *dev,
 	}
 }
 
-static void print_hwpath(struct parisc_device *dev, char *output)
+void print_hwpath(struct parisc_device *dev, char *output)
 {
 	int i;
 	struct hardware_path path;
Index: drivers/gsc/dino.c
===================================================================
RCS file: /home/cvs/parisc/linux/drivers/gsc/dino.c,v
retrieving revision 1.49
diff -u -p -r1.49 dino.c
--- drivers/gsc/dino.c	2001/12/26 22:00:32	1.49
+++ drivers/gsc/dino.c	2002/01/06 17:18:42
@@ -559,7 +559,7 @@ dino_fixup_bus(struct pci_bus *bus)
 				bus, bus->secondary, bus->sysdata);
 
 	/* Firmware doesn't set up card-mode dino, so we have to */
-	if (is_card_dino(dino_dev->hba.iodc_info))
+	if (is_card_dino(&dino_dev->hba.dev->id))
 		dino_card_setup(bus, dino_dev->hba.base_addr);
 
 	/* If this is a PCI-PCI Bridge, read the window registers etc */
@@ -570,7 +570,7 @@ dino_fixup_bus(struct pci_bus *bus)
 		int i;
 
 		dev = pci_dev_b(ln);
-		if (is_card_dino(dino_dev->hba.iodc_info))
+		if (is_card_dino(&dino_dev->hba.dev->id))
 			dino_card_fixup(dev);
 
 		/*
@@ -907,7 +907,7 @@ dino_driver_callback(struct parisc_devic
 
 	memset(dino_dev, 0, sizeof(struct dino_device));
 
-	dino_dev->hba.iodc_info = &dev->id;
+	dino_dev->hba.dev = dev;
 	dino_dev->hba.base_addr = dev->hpa;  /* faster access */
 	dino_dev->hba.lmmio_space_offset = 0;	/* CPU addrs == bus addrs */
 	dino_dev->dinosaur_pen = SPIN_LOCK_UNLOCKED;
Index: drivers/video/sti/sticore.c
===================================================================
RCS file: /home/cvs/parisc/linux/drivers/video/sti/sticore.c,v
retrieving revision 1.30
diff -u -p -r1.30 sticore.c
--- drivers/video/sti/sticore.c	2001/12/04 02:12:40	1.30
+++ drivers/video/sti/sticore.c	2002/01/06 18:06:15
@@ -30,7 +30,7 @@
 
 #include "sticore.h"
 
-struct sti_struct *default_sti;
+struct sti_struct *default_sti = NULL;
 
 static int num_sti_roms;			  /* # of STI ROMS found */
 static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */
@@ -242,16 +242,14 @@ sti_rom_copy(unsigned long base, unsigne
 
 
 
-static unsigned int __initdata sti_initial_index;
+static char default_sti_path[21] = { '\0' };
 
 static int __init 
 sti_setup(char *str)
 {
-	char *end;
+	if (str)
+		strncpy (default_sti_path, str, sizeof (default_sti_path));
 	
-	if (str && *str)
-		sti_initial_index = simple_strtoul(str, &end, 10);
-	
 	return 0;
 }
 
@@ -865,6 +863,11 @@ out_err:
 	return NULL;
 }
 
+static void __init sticore_check_for_default_sti (struct sti_struct *sti, char *path)
+{
+	if (strcmp (path, default_sti_path) == 0)
+		default_sti = sti;
+}
 
 /*
  * on newer systems PDC gives the address of the ROM 
@@ -874,21 +877,28 @@ out_err:
 static int __init sticore_pa_init(struct parisc_device *dev)
 {
 	unsigned long rom = 0;
-
+	char pa_path[21];
+	struct sti_struct *sti = NULL;
+	
 	if(dev->num_addrs) {
 		rom = dev->addr[0];
 	}
 	if (!rom) {
 		rom = dev->hpa;
 		DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
-		if (sti_try_rom_generic(rom, dev->hpa, NULL))
-			return 0;
+		sti = sti_try_rom_generic(rom, dev->hpa, NULL);
 		rom = PAGE0->proc_sti;
 	}
-	DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
-	if (sti_try_rom_generic(rom, dev->hpa, NULL))
-		return 0;
-	return 1;
+	if (!sti) {
+		DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
+		sti = sti_try_rom_generic(rom, dev->hpa, NULL);
+	}
+	if (!sti)
+		return 1;
+	
+	print_hwpath (dev, pa_path);
+	sticore_check_for_default_sti (sti, pa_path);
+	return 0;
 }
 
 
@@ -939,6 +949,25 @@ static int __devinit sticore_pci_init(st
 		/* fall through */
 	default:
 		sti = sti_try_rom_generic(rom_base, fb_base, pd);
+		if (sti) {
+			unsigned char pci_path[4];
+			char pa_path[21];
+			struct pci_bus *root;
+			int i = 0;
+			char *p;
+			
+			pci_path[i++] = PCI_FUNC(pd->devfn);
+			pci_path[i++] = PCI_SLOT(pd->devfn);
+			for (root = pd->bus; root->parent && i < 4; root = root->parent)
+				pci_path[i++] = root->number;
+			if (i >= 4)
+				break; /* too many bridges, shouldn't happen */
+			print_hwpath (HBA_DATA(root->sysdata)->dev, pa_path);
+			p = &pa_path[strlen(pa_path)];
+			while (i > 0)
+				p += sprintf (p, "/%d", pci_path[--i]);
+			sticore_check_for_default_sti(sti, pa_path);
+		}
 		break;
 	}
 
@@ -997,12 +1026,10 @@ struct sti_struct * __init sti_init_roms
 	/* Register drivers for native & PCI cards */
 	register_parisc_driver(&pa_sti_driver);
 	pci_module_init (&pci_sti_driver);
-
-	/* check boot-value from "sti=<index>" */
-	if (sti_initial_index >= num_sti_roms)
-		sti_initial_index = 0;
 
-	default_sti = sti_roms[sti_initial_index];
+	/* if we didn't find the given default sti, take the first one */
+	if (!default_sti)
+		default_sti = sti_roms[0];
 
 out:
 	/* return default STI if available */
@@ -1013,11 +1040,26 @@ out:
 	return NULL;
 }
 
+/*
+ * index = 0 gives default sti
+ * index > 0 gives other stis in detection order
+ */
 struct sti_struct * __init sti_get_rom(int index)
 {
-	if (index >=0 && index < num_sti_roms)
-		return sti_roms[index];
+	int i;
 	
-	return NULL;
+	if (index == 0)
+		return default_sti;
+
+	i = -1;
+	while (index > 0) {
+		i++;
+		if (i > num_sti_roms)
+			return NULL;
+		if (sti_roms[i] == default_sti)
+			continue;
+		index--;
+	}
+	return sti_roms[i];
 }
    
Index: include/asm-parisc/pci.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/pci.h,v
retrieving revision 1.38
diff -u -p -r1.38 pci.h
--- include/asm-parisc/pci.h	2001/11/10 01:47:37	1.38
+++ include/asm-parisc/pci.h	2002/01/06 17:12:02
@@ -47,7 +47,7 @@
 */
 struct pci_hba_data {
 	unsigned long	base_addr;	/* aka Host Physical Address */
-	const struct parisc_device_id *iodc_info; /* Info from PA bus walk */
+	const struct parisc_device *dev; /* device from PA bus walk */
 	struct pci_bus *hba_bus;	/* primary PCI bus below HBA */
 	int		hba_num;	/* I/O port space access "key" */
 	struct resource bus_num;	/* PCI bus numbers */
@@ -249,6 +249,7 @@ extern inline void pcibios_register_hba(
 struct parisc_device;
 void * ccio_get_iommu(struct parisc_device *dev);
 struct pci_dev * ccio_get_fake(struct parisc_device *dev);
+int ccio_request_resource(struct parisc_device *dev, struct resource *r);
 #else /* !CONFIG_IOMMU_CCIO */
 #define ccio_get_iommu(dev) (NULL)
 #define ccio_get_fake(dev) (NULL)

----------------------------------------------------------------------------

Index: ipl/bootloader.h
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/bootloader.h,v
retrieving revision 1.10
diff -u -p -r1.10 bootloader.h
--- ipl/bootloader.h	2001/12/31 19:36:32	1.10
+++ ipl/bootloader.h	2002/01/06 18:21:12
@@ -35,6 +35,7 @@ int pdc_os_bits();
 #define OS_32 0x2
 #define OS_64 0x1
 int pdc_iodc_bootin(unsigned devaddr, char *memaddr, unsigned size);
+int pdc_read_conspath(unsigned char *memaddr);
 
 typedef void (*describe_t)(int fd, int *bufalign, int *blocksize);
 typedef int (*read_t)(int fd, char *buf, unsigned nbytes, unsigned devaddr);
Index: ipl/ipl.c
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/ipl.c,v
retrieving revision 1.27
diff -u -p -r1.27 ipl.c
--- ipl/ipl.c	2001/12/31 19:36:32	1.27
+++ ipl/ipl.c	2002/01/06 18:29:29
@@ -333,7 +333,33 @@ iplmain(int is_interactive, char *initia
 	    printf("(graphics).\n");
 	    strcat(f.cmdline, "tty0");
 	    if (strstr(f.cmdline, " sti=") == 0)
-	        strcat(f.cmdline, " sti=0");
+	    {
+		struct {
+		    unsigned char flags;
+		    unsigned char bc[6];
+		    unsigned char mod;
+		} cons;
+		int i;
+		
+		strcat (f.cmdline, " sti=");
+		if (pdc_read_conspath ((unsigned char *)&cons) > 0)
+		{
+		    char pathcomp[4];
+		    
+		    for (i = 0; i < 6; i++)
+		    {
+			if (cons.bc[i] < 64)
+			{
+			    sprintf (pathcomp, "%d/", cons.bc[i]);
+			    strcat (f.cmdline, pathcomp);
+			}
+		    }
+		    sprintf (pathcomp, "%d", cons.mod);
+		    strcat (f.cmdline, pathcomp);
+		}
+		else
+		    strcat (f.cmdline, "0");
+	    }
 	    if (strstr(f.cmdline, " sti_font=") == 0)
 	        strcat(f.cmdline, " sti_font=VGA8x16");
 	    if (strstr(f.cmdline, " TERM=") == 0)
Index: ipl/pdc_misc.c
===================================================================
RCS file: /home/cvs/parisc/palo/ipl/pdc_misc.c,v
retrieving revision 1.13
diff -u -p -r1.13 pdc_misc.c
--- ipl/pdc_misc.c	2001/11/19 03:54:42	1.13
+++ ipl/pdc_misc.c	2002/01/06 02:20:43
@@ -19,6 +19,7 @@
 #define PDC_RETURN_MASK 0
 #define PDC_RETURN_DEFAULTS 1
 #define PDC_SET_DEFAULTS 2
+#define PDC_STABLE 10
 
 void die(const char *s)
 {
@@ -283,6 +284,21 @@ pdc_iodc_bootin(unsigned devaddr, char *
 	return 0;			/* count = 0 at EOF */
     }
     else if (r >= 0)
+    {
+	convert_from_wide(pdc_result);
+	return pdc_result[0];		/* count */
+    }
+    return r;				/* r < 0; error */
+}
+
+int
+pdc_read_conspath(unsigned char *memaddr)
+{
+    int r;
+    
+    r = firmware_call(mem_pdc, PDC_STABLE, 0, 96, memaddr, 8);
+
+    if (r >= 0)
     {
 	convert_from_wide(pdc_result);
 	return pdc_result[0];		/* count */





-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea.                                 [ Alexander Viro on linux-kernel ]