patch-2.4.4 linux/fs/partitions/ibm.c
Next file: linux/fs/proc/array.c
Previous file: linux/fs/partitions/Makefile
Back to the patch index
Back to the overall index
- Lines: 290
- Date:
Fri Apr 13 20:26:07 2001
- Orig file:
v2.4.3/linux/fs/partitions/ibm.c
- Orig date:
Fri Feb 16 16:02:37 2001
diff -u --recursive --new-file v2.4.3/linux/fs/partitions/ibm.c linux/fs/partitions/ibm.c
@@ -1,14 +1,17 @@
/*
* File...........: linux/fs/partitions/ibm.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Volker Sameske <sameske@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
* History of changes (starts July 2000)
- * 07/10/00 Fixed detection of CMS formatted disks
-
+ * 07/10/00 Fixed detection of CMS formatted disks
+ * 02/13/00 VTOC partition support added
*/
+#include <linux/config.h>
+#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
@@ -25,145 +28,177 @@
#include "ibm.h"
#include "check.h"
+#include <asm/vtoc.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
/* We hook in when DASD is a module... */
int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
+int (*genhd_dasd_fillgeo)(int,struct hd_geometry *) = NULL;
+EXPORT_SYMBOL(genhd_dasd_fillgeo);
+EXPORT_SYMBOL(genhd_dasd_name);
#endif /* LINUX_IS_24 */
typedef enum {
- ibm_partition_none = 0,
- ibm_partition_lnx1 = 1,
- ibm_partition_vol1 = 3,
- ibm_partition_cms1 = 4
+ ibm_partition_lnx1 = 0,
+ ibm_partition_vol1 = 1,
+ ibm_partition_cms1 = 2,
+ ibm_partition_none = 3
} ibm_partition_t;
+static char* part_names[] = { [ibm_partition_lnx1] = "LNX1",
+ [ibm_partition_vol1] = "VOL1",
+ [ibm_partition_cms1] = "CMS1",
+ [ibm_partition_none] = "(nonl)"
+};
+
static ibm_partition_t
get_partition_type ( char * type )
{
- static char lnx[5]="LNX1";
- static char vol[5]="VOL1";
- static char cms[5]="CMS1";
- if ( ! strncmp ( lnx, "LNX1",4 ) ) {
- ASCEBC(lnx,4);
- ASCEBC(vol,4);
- ASCEBC(cms,4);
- }
- if ( ! strncmp (type,lnx,4) ||
- ! strncmp (type,"LNX1",4) )
- return ibm_partition_lnx1;
- if ( ! strncmp (type,vol,4) )
- return ibm_partition_vol1;
- if ( ! strncmp (type,cms,4) )
- return ibm_partition_cms1;
- return ibm_partition_none;
+ int i;
+ for ( i = 0; i < 3; i ++) {
+ if ( ! strncmp (type,part_names[i],4) )
+ break;
+ }
+ return i;
+}
+
+/*
+ * add the two default partitions
+ * - whole dasd
+ * - whole dasd without "offset"
+ */
+static inline void
+two_partitions(struct gendisk *hd,
+ int minor,
+ int blocksize,
+ int offset,
+ int size) {
+
+ add_gd_partition( hd, minor, 0,size);
+ add_gd_partition( hd, minor + 1,
+ offset * (blocksize >> 9),
+ size-offset*(blocksize>>9));
+}
+
+
+/*
+ * compute the block number from a
+ * cyl-cyl-head-head structure
+ */
+static inline int
+cchh2blk (cchh_t *ptr, struct hd_geometry *geo) {
+ return ptr->cc * geo->heads * geo->sectors +
+ ptr->hh * geo->sectors;
+}
+
+
+/*
+ * compute the block number from a
+ * cyl-cyl-head-head-block structure
+ */
+static inline int
+cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
+ return ptr->cc * geo->heads * geo->sectors +
+ ptr->hh * geo->sectors +
+ ptr->b;
}
int
ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
first_part_minor)
{
- struct buffer_head *bh;
+ struct buffer_head *bh, *buf;
ibm_partition_t partition_type;
char type[5] = {0,};
char name[7] = {0,};
struct hd_geometry geo;
- mm_segment_t old_fs;
int blocksize;
- struct file *filp = NULL;
- struct inode *inode = NULL;
- int offset, size;
+ int offset=0, size=0, psize=0, counter=0;
+ unsigned int blk;
+ format1_label_t f1;
+ volume_label_t vlabel;
+ if ( first_sector != 0 ) {
+ BUG();
+ }
+ if ( !genhd_dasd_fillgeo ) {
+ return 0;
+ }
+ genhd_dasd_fillgeo(dev,&geo);
blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
if ( blocksize <= 0 ) {
return 0;
}
- set_blocksize(dev, blocksize); /* OUCH !! */
-
- /* find out offset of volume label (partn table) */
- inode = get_empty_inode();
- inode -> i_rdev = dev;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
- inode -> i_bdev = bdget(kdev_t_to_nr(dev));
-#endif /* KERNEL_VERSION */
- filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL);
- if (!filp)
- return 0;
- memset(filp,0,sizeof(struct file));
- filp ->f_mode = 1; /* read only */
- blkdev_open(inode,filp);
- old_fs=get_fs();
- set_fs(KERNEL_DS);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
- inode-> i_bdev -> bd_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
-#else
- filp->f_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
-#endif /* KERNEL_VERSION */
- set_fs(old_fs);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
- blkdev_put(inode->i_bdev,BDEV_FILE);
-#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
- blkdev_close(inode,filp);
-#else
- blkdev_release(inode);
-#endif /* LINUX_VERSION_CODE */
- size = hd -> sizes[MINOR(dev)]<<1;
+ set_blocksize(dev, blocksize); /* OUCH !! */
if ( ( bh = bread( dev, geo.start, blocksize) ) != NULL ) {
- strncpy ( type,bh -> b_data, 4);
+ strncpy ( type,bh -> b_data + 0, 4);
strncpy ( name,bh -> b_data + 4, 6);
+ memcpy (&vlabel, bh->b_data, sizeof(volume_label_t));
} else {
return 0;
}
- if ( (*(char *)bh -> b_data) & 0x80 ) {
- EBCASC(name,6);
- }
- switch ( partition_type = get_partition_type(type) ) {
- case ibm_partition_lnx1:
- offset = (geo.start + 1);
- printk ( "(LNX1)/%6s:",name);
- break;
- case ibm_partition_vol1:
- offset = 0;
- size = 0;
- printk ( "(VOL1)/%6s:",name);
- break;
+ EBCASC(type,4);
+ EBCASC(name,6);
+
+ partition_type = get_partition_type(type);
+ printk ( "%6s/%6s:",part_names[partition_type],name);
+ switch ( partition_type ) {
case ibm_partition_cms1:
- printk ( "(CMS1)/%6s:",name);
- if (* (((long *)bh->b_data) + 13) == 0) {
- /* disk holds a CMS filesystem */
- offset = (geo.start + 1);
- printk ("(CMS)");
- } else {
+ if (* (((long *)bh->b_data) + 13) != 0) {
/* disk is reserved minidisk */
- // mdisk_setup_data.size[i] =
- // (label[7] - 1 - label[13]) *
- // (label[3] >> 9) >> 1;
long *label=(long*)bh->b_data;
blocksize = label[3];
offset = label[13];
size = (label[7]-1)*(blocksize>>9);
printk ("(MDSK)");
+ } else {
+ offset = (geo.start + 1);
+ size = hd -> sizes[MINOR(dev)]<<1;
}
+ two_partitions( hd, MINOR(dev), blocksize,
+ offset, size);
break;
+ case ibm_partition_lnx1:
case ibm_partition_none:
- printk ( "(nonl)/ :");
- offset = (geo.start+1);
+ offset = (geo.start + 1);
+ size = hd -> sizes[MINOR(dev)]<<1;
+ two_partitions( hd, MINOR(dev), blocksize,
+ offset, size);
+ break;
+ case ibm_partition_vol1:
+ add_gd_partition(hd, MINOR(dev), 0, size);
+
+ /* get block number and read then first format1 label */
+ blk = cchhb2blk(&vlabel.vtoc, &geo) + 1;
+ if ((buf = bread( dev, blk, blocksize)) != NULL) {
+ memcpy (&f1, buf->b_data, sizeof(format1_label_t));
+ bforget(buf);
+ }
+
+ while (f1.DS1FMTID == _ascebc['1']) {
+ offset = cchh2blk(&f1.DS1EXT1.llimit, &geo);
+ psize = cchh2blk(&f1.DS1EXT1.ulimit, &geo) -
+ offset + 1;
+
+ counter++;
+ add_gd_partition(hd, MINOR(dev) + counter,
+ offset * (blocksize >> 9),
+ psize * (blocksize >> 9));
+
+ blk++;
+ if ((buf = bread( dev, blk, blocksize)) != NULL) {
+ memcpy (&f1, buf->b_data,
+ sizeof(format1_label_t));
+ bforget(buf);
+ }
+ }
break;
default:
- offset = 0;
- size = 0;
-
+ add_gd_partition( hd, MINOR(dev), 0, 0);
+ add_gd_partition( hd, MINOR(dev) + 1, 0, 0);
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
- add_gd_partition( hd, MINOR(dev), 0,size);
- add_gd_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
- size-offset*(blocksize>>9));
-#else
- add_partition( hd, MINOR(dev), 0,size,0);
- add_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
- size-offset*(blocksize>>9) ,0 );
-#endif /* LINUX_VERSION */
+
printk ( "\n" );
bforget(bh);
return 1;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)