Import changeset
[linux-flexiantxendom0-3.2.10.git] / fs / partitions / amiga.c
1 /*
2  *  fs/partitions/amiga.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/fs.h>
11 #include <linux/genhd.h>
12 #include <linux/kernel.h>
13 #include <linux/major.h>
14 #include <linux/string.h>
15 #include <linux/blk.h>
16
17 #include <asm/byteorder.h>
18 #include <linux/affs_hardblocks.h>
19
20 #include "check.h"
21 #include "amiga.h"
22
23 static __inline__ u32
24 checksum_block(u32 *m, int size)
25 {
26         u32 sum = 0;
27
28         while (size--)
29                 sum += be32_to_cpu(*m++);
30         return sum;
31 }
32
33 int
34 amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
35 {
36         struct buffer_head      *bh;
37         struct RigidDiskBlock   *rdb;
38         struct PartitionBlock   *pb;
39         int                      start_sect;
40         int                      nr_sects;
41         int                      blk;
42         int                      part, res;
43         int                      old_blocksize;
44         int                      blocksize;
45
46         old_blocksize = get_ptable_blocksize(dev);
47         blocksize = get_hardsect_size(dev);
48
49         if (blocksize < 512)
50                 blocksize = 512;
51
52         set_blocksize(dev,blocksize);
53         res = 0;
54
55         for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
56                 if(!(bh = bread(dev,blk,blocksize))) {
57                         if (warn_no_part) printk("Dev %s: unable to read RDB block %d\n",
58                                kdevname(dev),blk);
59                         goto rdb_done;
60                 }
61                 if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
62                         rdb = (struct RigidDiskBlock *)bh->b_data;
63                         if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
64                                 /* Try again with 0xdc..0xdf zeroed, Windows might have
65                                  * trashed it.
66                                  */
67                                 *(u32 *)(&bh->b_data[0xdc]) = 0;
68                                 if (checksum_block((u32 *)bh->b_data,
69                                                 be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
70                                         brelse(bh);
71                                         printk("Dev %s: RDB in block %d has bad checksum\n",
72                                                kdevname(dev),blk);
73                                         continue;
74                                 }
75                                 printk("Warning: Trashed word at 0xd0 in block %d "
76                                         "ignored in checksum calculation\n",blk);
77                         }
78                         printk(" RDSK");
79                         blk = be32_to_cpu(rdb->rdb_PartitionList);
80                         brelse(bh);
81                         for (part = 1; blk > 0 && part <= 16; part++) {
82                                 if (!(bh = bread(dev,blk,blocksize))) {
83                                         if (warn_no_part) printk("Dev %s: unable to read partition block %d\n",
84                                                        kdevname(dev),blk);
85                                         goto rdb_done;
86                                 }
87                                 pb  = (struct PartitionBlock *)bh->b_data;
88                                 blk = be32_to_cpu(pb->pb_Next);
89                                 if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
90                                     (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
91
92                                         /* Tell Kernel about it */
93
94                                         if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
95                                                           be32_to_cpu(pb->pb_Environment[9])) *
96                                                          be32_to_cpu(pb->pb_Environment[3]) *
97                                                          be32_to_cpu(pb->pb_Environment[5]))) {
98                                                 brelse(bh);
99                                                 continue;
100                                         }
101                                         start_sect = be32_to_cpu(pb->pb_Environment[9]) *
102                                                      be32_to_cpu(pb->pb_Environment[3]) *
103                                                      be32_to_cpu(pb->pb_Environment[5]);
104                                         add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
105                                         first_part_minor++;
106                                         res = 1;
107                                 }
108                                 brelse(bh);
109                         }
110                         printk("\n");
111                         break;
112                 }
113                 else
114                         brelse(bh);
115         }
116
117 rdb_done:
118         set_blocksize(dev,old_blocksize);
119         return res;
120 }