Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
[linux-2.6] / fs / partitions / sun.c
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 "check.h"
11 #include "sun.h"
12
13 int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
14 {
15         int i;
16         __be16 csum;
17         int slot = 1;
18         __be16 *ush;
19         Sector sect;
20         struct sun_disklabel {
21                 unsigned char info[128];   /* Informative text string */
22                 unsigned char spare0[14];
23                 struct sun_info {
24                         unsigned char spare1;
25                         unsigned char id;
26                         unsigned char spare2;
27                         unsigned char flags;
28                 } infos[8];
29                 unsigned char spare[246];  /* Boot information etc. */
30                 __be16 rspeed;     /* Disk rotational speed */
31                 __be16 pcylcount;  /* Physical cylinder count */
32                 __be16 sparecyl;   /* extra sects per cylinder */
33                 unsigned char spare2[4];   /* More magic... */
34                 __be16 ilfact;     /* Interleave factor */
35                 __be16 ncyl;       /* Data cylinder count */
36                 __be16 nacyl;      /* Alt. cylinder count */
37                 __be16 ntrks;      /* Tracks per cylinder */
38                 __be16 nsect;      /* Sectors per track */
39                 unsigned char spare3[4];   /* Even more magic... */
40                 struct sun_partition {
41                         __be32 start_cylinder;
42                         __be32 num_sectors;
43                 } partitions[8];
44                 __be16 magic;      /* Magic number */
45                 __be16 csum;       /* Label xor'd checksum */
46         } * label;              
47         struct sun_partition *p;
48         unsigned long spc;
49         char b[BDEVNAME_SIZE];
50
51         label = (struct sun_disklabel *)read_dev_sector(bdev, 0, &sect);
52         if (!label)
53                 return -1;
54
55         p = label->partitions;
56         if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
57 /*              printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n",
58                        bdevname(bdev, b), be16_to_cpu(label->magic)); */
59                 put_dev_sector(sect);
60                 return 0;
61         }
62         /* Look at the checksum */
63         ush = ((__be16 *) (label+1)) - 1;
64         for (csum = 0; ush >= ((__be16 *) label);)
65                 csum ^= *ush--;
66         if (csum) {
67                 printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
68                        bdevname(bdev, b));
69                 put_dev_sector(sect);
70                 return 0;
71         }
72
73         /* All Sun disks have 8 partition entries */
74         spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
75         for (i = 0; i < 8; i++, p++) {
76                 unsigned long st_sector;
77                 int num_sectors;
78
79                 st_sector = be32_to_cpu(p->start_cylinder) * spc;
80                 num_sectors = be32_to_cpu(p->num_sectors);
81                 if (num_sectors) {
82                         put_partition(state, slot, st_sector, num_sectors);
83                         if (label->infos[i].id == LINUX_RAID_PARTITION)
84                                 state->parts[slot].flags = 1;
85                 }
86                 slot++;
87         }
88         printk("\n");
89         put_dev_sector(sect);
90         return 1;
91 }