File: /usr/src/linux/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     }
121