patch-2.4.19 linux-2.4.19/arch/ppc/kernel/pmac_setup.c

Next file: linux-2.4.19/arch/ppc/kernel/pmac_smp.c
Previous file: linux-2.4.19/arch/ppc/kernel/pmac_pci.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/arch/ppc/kernel/pmac_setup.c linux-2.4.19/arch/ppc/kernel/pmac_setup.c
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pmac_setup.c 1.45 12/01/01 20:09:06 benh
+ * BK Id: SCCS/s.pmac_setup.c 1.54 04/16/02 20:08:22 paulus
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -50,6 +50,8 @@
 #include <linux/cuda.h>
 #include <linux/pmu.h>
 #include <linux/seq_file.h>
+#include <linux/blkdev.h>
+#include <linux/genhd.h>
 
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -67,14 +69,14 @@
 #include <asm/bootx.h>
 #include <asm/cputable.h>
 #include <asm/btext.h>
-
 #include <asm/pmac_feature.h>
 #include <asm/time.h>
+
 #include "local_irq.h"
 #include "pmac_pic.h"
-#include "../mm/mem_pieces.h"
-
-#undef SHOW_GATWICK_IRQS
+#include "mem_pieces.h"
+#include "scsi.h" /* sd_find_target */
+#include "sd.h"
 
 extern long pmac_time_init(void);
 extern unsigned long pmac_get_rtc_time(void);
@@ -140,26 +142,6 @@
 #ifdef CONFIG_SMP
 extern struct smp_ops_t psurge_smp_ops;
 extern struct smp_ops_t core99_smp_ops;
-
-volatile static long int core99_l2_cache;
-void __init
-core99_init_l2(void)
-{
-	int cpu = smp_processor_id();
-
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
-		return;
-
-	if (cpu == 0){
-		core99_l2_cache = _get_L2CR();
-		printk("CPU0: L2CR is %lx\n", core99_l2_cache);
-	} else {
-		printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
-		_set_L2CR(0);
-		_set_L2CR(core99_l2_cache);
-		printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
-	}
-}
 #endif /* CONFIG_SMP */
 
 /*
@@ -189,7 +171,15 @@
 	struct device_node *np;
 	char *pp;
 	int plen;
+	int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+		NULL, PMAC_MB_INFO_MODEL, 0);
+	unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+		NULL, PMAC_MB_INFO_FLAGS, 0);
+	char* mbname;
 
+	if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
+		mbname = "Unknown";
+		
 	/* find motherboard type */
 	seq_printf(m, "machine\t\t: ");
 	np = find_devices("device-tree");
@@ -213,6 +203,10 @@
 	} else
 		seq_printf(m, "PowerMac\n");
 
+	/* print parsed model */
+	seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
+	seq_printf(m, "pmac flags\t: %08x\n", mbflags);
+	
 	/* find l2 cache info */
 	np = find_devices("l2-cache");
 	if (np == 0)
@@ -275,16 +269,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_SCSI
-/* Find the device number for the disk (if any) at target tgt
-   on host adaptor host.  We just need to get the prototype from
-   sd.h */
-#include <linux/blkdev.h>
-#include "../../../drivers/scsi/scsi.h"
-#include "../../../drivers/scsi/sd.h"
-
-#endif
-
 #ifdef CONFIG_VT
 /*
  * Dummy mksound function that does nothing.
@@ -352,11 +336,6 @@
 		printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
 			ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
 				? "enabled" : "disabled");
-
-#ifdef CONFIG_SMP
-	/* somewhat of a hack */
-	core99_init_l2();
-#endif
 	
 #ifdef CONFIG_KGDB
 	zs_kgdb_hook(0);
@@ -444,6 +423,34 @@
 	pmac_feature_late_init();
 }
 
+/* That include would have to be in include/linux/ ideally */
+#include "../../../fs/partitions/mac.h"
+
+/* Borrowed from fs/partition/check.c */
+static unsigned char* __init
+read_one_block(struct block_device *bdev, unsigned long n, struct page **v)
+{
+	struct address_space *mapping = bdev->bd_inode->i_mapping;
+	int sect = PAGE_CACHE_SIZE / 512;
+	struct page *page;
+
+	page = read_cache_page(mapping, n/sect,
+			(filler_t *)mapping->a_ops->readpage, NULL);
+	if (!IS_ERR(page)) {
+		wait_on_page(page);
+		if (!Page_Uptodate(page))
+			goto fail;
+		if (PageError(page))
+			goto fail;
+		*v = page;
+		return (unsigned char *)page_address(page) + 512 * (n % sect);
+fail:
+		page_cache_release(page);
+	}
+	*v = NULL;
+	return NULL;
+}
+
 #ifdef CONFIG_SCSI
 void __init
 note_scsi_host(struct device_node *node, void *host)
@@ -473,7 +480,7 @@
 		}
 	}
 }
-#endif
+#endif /* CONFIG_SCSI */
 
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
 kdev_t __init
@@ -509,32 +516,132 @@
 #endif
 }
 
-/* can't be __init - can be called whenever a disk is first accessed */
-void __pmac
-note_bootable_part(kdev_t dev, int part, int goodness)
+static void __init
+check_bootable_part(kdev_t dev, int blk, struct mac_partition *part)
 {
-	static int found_boot = 0;
-	char *p;
+	int goodness = 0;
+
+	macpart_fix_string(part->processor, 16);
+	macpart_fix_string(part->name, 32);
+	macpart_fix_string(part->type, 32);					
+    
+	if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
+	    && strcasecmp(part->processor, "powerpc") == 0)
+		goodness++;
+
+	if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
+	    || (strnicmp(part->type, "Linux", 5) == 0
+	    && strcasecmp(part->type, "Linux_swap") != 0)) {
+		int i, l;
+
+		goodness++;
+		l = strlen(part->name);
+		if (strcmp(part->name, "/") == 0)
+			goodness++;
+		for (i = 0; i <= l - 4; ++i) {
+			if (strnicmp(part->name + i, "root",
+				     4) == 0) {
+				goodness += 2;
+				break;
+			}
+		}
+		if (strnicmp(part->name, "swap", 4) == 0)
+			goodness--;
+	}
+
+	if (goodness > current_root_goodness) {
+		ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + blk);
+		current_root_goodness = goodness;
+	}
+}
 
-	/* Do nothing if the root has been mounted already. */
-	if (init_task.fs->rootmnt != NULL)
+static void __init
+check_bootable_disk(kdev_t dev, struct block_device *bdev)
+{
+	struct mac_partition *part;
+	struct mac_driver_desc *md;
+	struct page* pg;
+	unsigned secsize, blocks_in_map, blk;
+	unsigned char* data;
+	
+	/* Check driver descriptor */
+	md = (struct mac_driver_desc *) read_one_block(bdev, 0, &pg);
+	if (!md)
 		return;
-	if ((goodness <= current_root_goodness) &&
-	    (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE)))
+	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC)
+		goto fail;
+	secsize = be16_to_cpu(md->block_size);
+	page_cache_release(pg);
+	
+	/* Check if it looks like a mac partition map */
+	data = read_one_block(bdev, secsize/512, &pg);
+	if (!data)
+		goto fail;
+	part = (struct mac_partition *) (data + secsize%512);
+	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+		goto fail;
+
+	/* Iterate the partition map */
+	blocks_in_map = be32_to_cpu(part->map_count);
+	for (blk = 1; blk <= blocks_in_map; ++blk) {
+		int pos = blk * secsize;
+		page_cache_release(pg);
+		data = read_one_block(bdev, pos/512, &pg);
+		if (!data)
+			break;
+		part = (struct mac_partition *) (data + pos%512);
+		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+			break;
+		check_bootable_part(dev, blk, part);
+	}
+fail:
+	if (pg)	
+		page_cache_release(pg);
+}
+
+static int __init
+walk_bootable(struct gendisk *hd, void *data)
+{
+	int drive;
+	
+	for (drive=0; drive<hd->nr_real; drive++) {
+		kdev_t dev;
+		struct block_device *bdev;
+		int rc;
+
+		dev = MKDEV(hd->major, drive << hd->minor_shift);
+		if (boot_dev && boot_dev != dev)
+			continue;
+		bdev = bdget(kdev_t_to_nr(dev));
+		if (bdev == NULL)
+			continue;
+		rc = blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW);
+		if (rc == 0) {
+			check_bootable_disk(dev, bdev);
+			blkdev_put(bdev, BDEV_RAW);
+		}
+	}
+
+	return 0;
+}
+
+void __init
+pmac_discover_root(void)
+{
+	char* p;
+
+	/* Check if root devices already got selected by other ways */
+	if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
 		return;
 	p = strstr(saved_command_line, "root=");
 	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
 		return;
 
-	if (!found_boot) {
-		find_boot_device();
-		found_boot = 1;
-	}
-	if (boot_dev == 0 || dev == boot_dev) {
-		ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part);
-		boot_dev = NODEV;
-		current_root_goodness = goodness;
-	}
+	/* Find the device used for booting if we can */
+	find_boot_device();
+
+	/* Try to locate a partition */
+	walk_gendisk(walk_bootable, NULL);
 }
 
 void __pmac
@@ -664,7 +771,7 @@
  * Read in a property describing some pieces of memory.
  */
 
-static void __init
+static int __init
 get_mem_prop(char *name, struct mem_pieces *mp)
 {
 	struct reg_property *rp;
@@ -677,7 +784,7 @@
 	if (ip == NULL) {
 		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
 		       name);
-		abort();
+		return 0;
 	}
 	s /= (nsc + nac) * 4;
 	rp = mp->regions;
@@ -696,6 +803,7 @@
 	/* Make sure the pieces are sorted. */
 	mem_pieces_sort(mp);
 	mem_pieces_coalesce(mp);
+	return 1;
 }
 
 /*
@@ -711,12 +819,6 @@
 	unsigned long a, total;
 	struct mem_pieces phys_mem;
 
-	memory_node = find_devices("memory");
-	if (memory_node == NULL) {
-		printk(KERN_ERR "can't find memory node\n");
-		abort();
-	}
-
 	/*
 	 * Find out where physical memory is, and check that it
 	 * starts at 0 and is contiguous.  It seems that RAM is
@@ -727,8 +829,9 @@
 	 * more complicated (or else you end up wasting space
 	 * in mem_map).
 	 */
-	get_mem_prop("reg", &phys_mem);
-	if (phys_mem.n_regions == 0)
+	memory_node = find_devices("memory");
+	if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
+	    || phys_mem.n_regions == 0)
 		panic("No RAM??");
 	a = phys_mem.regions[0].address;
 	if (a != 0)
@@ -805,6 +908,8 @@
 	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
 	ppc_md.pcibios_after_init = pmac_pcibios_after_init;
 
+	ppc_md.discover_root  = pmac_discover_root;
+
 	ppc_md.restart        = pmac_restart;
 	ppc_md.power_off      = pmac_power_off;
 	ppc_md.halt           = pmac_halt;
@@ -841,15 +946,12 @@
 }
 
 #ifdef CONFIG_BOOTX_TEXT
-extern void drawchar(char c);
-extern void drawstring(const char *c);
-extern boot_infos_t *disp_bi;
 void __init
 pmac_progress(char *s, unsigned short hex)
 {
-	if (disp_bi == 0)
-		return;
-	btext_drawstring(s);
-	btext_drawchar('\n');
+	if (boot_text_mapped) {
+		btext_drawstring(s);
+		btext_drawchar('\n');
+	}
 }
 #endif /* CONFIG_BOOTX_TEXT */

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