patch-2.3.14 linux/fs/partitions/amiga.c

Next file: linux/fs/partitions/amiga.h
Previous file: linux/fs/partitions/acorn.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.13/linux/fs/partitions/amiga.c linux/fs/partitions/amiga.c
@@ -0,0 +1,120 @@
+/*
+ *  fs/partitions/amiga.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/byteorder.h>
+#include <linux/affs_hardblocks.h>
+
+#include "check.h"
+#include "amiga.h"
+
+static __inline__ u32
+checksum_block(u32 *m, int size)
+{
+	u32 sum = 0;
+
+	while (size--)
+		sum += be32_to_cpu(*m++);
+	return sum;
+}
+
+int
+amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+{
+	struct buffer_head	*bh;
+	struct RigidDiskBlock	*rdb;
+	struct PartitionBlock	*pb;
+	int			 start_sect;
+	int			 nr_sects;
+	int			 blk;
+	int			 part, res;
+	int			 old_blocksize;
+	int			 blocksize;
+
+	old_blocksize = get_ptable_blocksize(dev);
+	blocksize = get_hardsect_size(dev);
+
+	if (blocksize < 512)
+		blocksize = 512;
+
+	set_blocksize(dev,blocksize);
+	res = 0;
+
+	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if(!(bh = bread(dev,blk,blocksize))) {
+			printk("Dev %s: unable to read RDB block %d\n",
+			       kdevname(dev),blk);
+			goto rdb_done;
+		}
+		if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
+			rdb = (struct RigidDiskBlock *)bh->b_data;
+			if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
+				/* Try again with 0xdc..0xdf zeroed, Windows might have
+				 * trashed it.
+				 */
+				*(u32 *)(&bh->b_data[0xdc]) = 0;
+				if (checksum_block((u32 *)bh->b_data,
+						be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
+					brelse(bh);
+					printk("Dev %s: RDB in block %d has bad checksum\n",
+					       kdevname(dev),blk);
+					continue;
+				}
+				printk("Warning: Trashed word at 0xd0 in block %d "
+					"ignored in checksum calculation\n",blk);
+			}
+			printk(" RDSK");
+			blk = be32_to_cpu(rdb->rdb_PartitionList);
+			brelse(bh);
+			for (part = 1; blk > 0 && part <= 16; part++) {
+				if (!(bh = bread(dev,blk,blocksize))) {
+					printk("Dev %s: unable to read partition block %d\n",
+						       kdevname(dev),blk);
+					goto rdb_done;
+				}
+				pb  = (struct PartitionBlock *)bh->b_data;
+				blk = be32_to_cpu(pb->pb_Next);
+				if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
+				    (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+
+					/* Tell Kernel about it */
+
+					if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+							  be32_to_cpu(pb->pb_Environment[9])) *
+							 be32_to_cpu(pb->pb_Environment[3]) *
+							 be32_to_cpu(pb->pb_Environment[5]))) {
+						brelse(bh);
+						continue;
+ 					}
+					start_sect = be32_to_cpu(pb->pb_Environment[9]) *
+						     be32_to_cpu(pb->pb_Environment[3]) *
+						     be32_to_cpu(pb->pb_Environment[5]);
+					add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
+					first_part_minor++;
+					res = 1;
+				}
+				brelse(bh);
+			}
+			printk("\n");
+			break;
+		}
+		else
+			brelse(bh);
+	}
+
+rdb_done:
+	set_blocksize(dev,old_blocksize);
+	return res;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)