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
24extern void md_autodetect_dev(kdev_t dev);
25#endif
26
27int 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		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