diff options
Diffstat (limited to 'fs/partitions/ibm.c')
-rw-r--r-- | fs/partitions/ibm.c | 179 |
1 files changed, 114 insertions, 65 deletions
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 765bbc9f9..be3e7eae7 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -1,8 +1,12 @@ /* - * File...........: linux/fs/partitions/ibm.c + * File...........: linux/fs/partitions/ibm.c * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com> - * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + + * History of changes (starts July 2000) + * 07/10/00 Fixed detection of CMS formatted disks + */ #include <linux/fs.h> @@ -11,9 +15,21 @@ #include <linux/major.h> #include <linux/string.h> #include <linux/blk.h> - +#include <linux/malloc.h> +#include <linux/hdreg.h> +#include <linux/ioctl.h> +#include <linux/version.h> #include <asm/ebcdic.h> -#include "../../drivers/s390/block/dasd_types.h" +#include <asm/uaccess.h> +#include <asm/dasd.h> + +#include "ibm.h" +#include "check.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; +#endif /* LINUX_IS_24 */ typedef enum { ibm_partition_none = 0, @@ -25,98 +41,131 @@ typedef enum { 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; + 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; } -void -ibm_partition (struct gendisk *hd, kdev_t dev) +int +ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int +first_part_minor) { struct buffer_head *bh; ibm_partition_t partition_type; - int di = MINOR(dev) >> PARTN_BITS; char type[5] = {0,}; char name[7] = {0,}; - if ( bh = bread( dev, - dasd_info[di]->sizes.label_block, - get_ptable_blocksize(dev) ) ) { + struct hd_geometry geo; + mm_segment_t old_fs; + int blocksize; + struct file *filp = NULL; + struct inode *inode = NULL; + int offset, size; + + 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; + if ( ( bh = bread( dev, geo.start, blocksize) ) != NULL ) { strncpy ( type,bh -> b_data, 4); strncpy ( name,bh -> b_data + 4, 6); } else { - return; + return 0; } if ( (*(char *)bh -> b_data) & 0x80 ) { EBCASC(name,6); } switch ( partition_type = get_partition_type(type) ) { - case ibm_partition_lnx1: + case ibm_partition_lnx1: + offset = (geo.start + 1); printk ( "(LNX1)/%6s:",name); - add_gd_partition( hd, MINOR(dev) + 1, - (dasd_info [di]->sizes.label_block + 1) << - dasd_info [di]->sizes.s2b_shift, - (dasd_info [di]->sizes.blocks - - dasd_info [di]->sizes.label_block - 1) << - dasd_info [di]->sizes.s2b_shift ); break; case ibm_partition_vol1: + offset = 0; + size = 0; printk ( "(VOL1)/%6s:",name); break; case ibm_partition_cms1: printk ( "(CMS1)/%6s:",name); if (* (((long *)bh->b_data) + 13) == 0) { - /* disk holds a CMS filesystem */ - add_gd_partition( hd, MINOR(dev) + 1, - (dasd_info [di]->sizes.label_block + 1) << - dasd_info [di]->sizes.s2b_shift, - (dasd_info [di]->sizes.blocks - - dasd_info [di]->sizes.label_block) << - dasd_info [di]->sizes.s2b_shift ); - printk ("(CMS)"); + /* disk holds a CMS filesystem */ + offset = (geo.start + 1); + printk ("(CMS)"); } else { - /* disk is reserved minidisk */ - int offset = (*(((long *)bh->b_data) + 13)); - int size = (*(((long *)bh->b_data) + 7)) - 1 - - (*(((long *)bh->b_data) + 13)) * - ((*(((long *)bh->b_data) + 3)) >> 9); - add_gd_partition( hd, MINOR(dev) + 1, - offset << dasd_info [di]->sizes.s2b_shift, - size << dasd_info [di]->sizes.s2b_shift ); - printk ("(MDSK)"); + /* 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)"); } break; case ibm_partition_none: printk ( "(nonl)/ :"); -/* - printk ( "%d %d %d ", MINOR(dev) + 1, - (dasd_info [di]->sizes.label_block + 1) << - dasd_info [di]->sizes.s2b_shift, - (dasd_info [di]->sizes.blocks - - dasd_info [di]->sizes.label_block - 1) << - dasd_info [di]->sizes.s2b_shift ); -*/ - add_gd_partition( hd, MINOR(dev) + 1, - (dasd_info [di]->sizes.label_block + 1) << - dasd_info [di]->sizes.s2b_shift, - (dasd_info [di]->sizes.blocks - - dasd_info [di]->sizes.label_block - 1) << - dasd_info [di]->sizes.s2b_shift ); + offset = (geo.start+1); break; + default: + offset = 0; + size = 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; } |