1 /*
2  *  fs/partitions/sun.c
3  *
4  *  Code extracted from drivers/block/genhd.c
5  *
6  *  Copyright (C) 1991-1998  Linus Torvalds
7  *  Re-organised Feb 1998 Russell King
8  */
9 
10 #include <linux/config.h>
11 #include <linux/fs.h>
12 #include <linux/genhd.h>
13 #include <linux/kernel.h>
14 #include <linux/major.h>
15 #include <linux/string.h>
16 #include <linux/blk.h>
17 
18 #include <asm/system.h>
19 
20 #include "check.h"
21 #include "sun.h"
22 
23 #ifdef CONFIG_BLK_DEV_MD
24 extern void md_autodetect_dev(kdev_t dev);
25 #endif
26 
sun_partition(struct gendisk * hd,struct block_device * bdev,unsigned long first_sector,int first_part_minor)27 int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor)
28 {
29 	int i, csum;
30 	unsigned short *ush;
31 	Sector sect;
32 	kdev_t dev = to_kdev_t(bdev->bd_dev);
33 	struct sun_disklabel {
34 		unsigned char info[128];   /* Informative text string */
35 		unsigned char spare0[14];
36 		struct sun_info {
37 			unsigned char spare1;
38 			unsigned char id;
39 			unsigned char spare2;
40 			unsigned char flags;
41 		} infos[8];
42 		unsigned char spare[246];  /* Boot information etc. */
43 		unsigned short rspeed;     /* Disk rotational speed */
44 		unsigned short pcylcount;  /* Physical cylinder count */
45 		unsigned short sparecyl;   /* extra sects per cylinder */
46 		unsigned char spare2[4];   /* More magic... */
47 		unsigned short ilfact;     /* Interleave factor */
48 		unsigned short ncyl;       /* Data cylinder count */
49 		unsigned short nacyl;      /* Alt. cylinder count */
50 		unsigned short ntrks;      /* Tracks per cylinder */
51 		unsigned short nsect;      /* Sectors per track */
52 		unsigned char spare3[4];   /* Even more magic... */
53 		struct sun_partition {
54 			__u32 start_cylinder;
55 			__u32 num_sectors;
56 		} partitions[8];
57 		unsigned short magic;      /* Magic number */
58 		unsigned short csum;       /* Label xor'd checksum */
59 	} * label;
60 	struct sun_partition *p;
61 	unsigned long spc;
62 
63 	label = (struct sun_disklabel *)read_dev_sector(bdev, 0, &sect);
64 	if (!label)
65 		return -1;
66 
67 	p = label->partitions;
68 	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
69 /*		printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n",
70 		       bdevname(dev), be16_to_cpu(label->magic)); */
71 		put_dev_sector(sect);
72 		return 0;
73 	}
74 	/* Look at the checksum */
75 	ush = ((unsigned short *) (label+1)) - 1;
76 	for (csum = 0; ush >= ((unsigned short *) label);)
77 		csum ^= *ush--;
78 	if (csum) {
79 		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
80 		       bdevname(dev));
81 		put_dev_sector(sect);
82 		return 0;
83 	}
84 
85 	/* All Sun disks have 8 partition entries */
86 	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
87 	for (i = 0; i < 8; i++, p++) {
88 		unsigned long st_sector;
89 		unsigned int num_sectors;
90 
91 		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
92 		num_sectors = be32_to_cpu(p->num_sectors);
93 		if (num_sectors) {
94 			add_gd_partition(hd, first_part_minor,
95 					 st_sector, num_sectors);
96 #ifdef CONFIG_BLK_DEV_MD
97 			if (label->infos[i].id == LINUX_RAID_PARTITION)
98 				md_autodetect_dev(MKDEV(hd->major,
99 							first_part_minor));
100 #endif
101 		}
102 		first_part_minor++;
103 	}
104 	printk("\n");
105 	put_dev_sector(sect);
106 	return 1;
107 }
108