import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / 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 <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
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 }