The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/partitions/ibm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * File...........: linux/fs/partitions/ibm.c      
    3  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
    4  *                  Volker Sameske <sameske@de.ibm.com>
    5  * Bugreports.to..: <Linux390@de.ibm.com>
    6  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
    7 
    8  * History of changes (starts July 2000)
    9  * 07/10/00 Fixed detection of CMS formatted disks     
   10  * 02/13/00 VTOC partition support added
   11  * 12/27/01 fixed PL030593 (CMS reserved minidisk not detected on 64 bit)
   12  */
   13 
   14 #include <linux/config.h>
   15 #include <linux/fs.h>
   16 #include <linux/genhd.h>
   17 #include <linux/kernel.h>
   18 #include <linux/major.h>
   19 #include <linux/string.h>
   20 #include <linux/blk.h>
   21 #include <linux/slab.h>
   22 #include <linux/hdreg.h>
   23 #include <linux/ioctl.h>
   24 #include <linux/version.h>
   25 #include <asm/ebcdic.h>
   26 #include <asm/uaccess.h>
   27 #include <asm/dasd.h>
   28 
   29 #include "ibm.h"
   30 #include "check.h"
   31 #include <asm/vtoc.h>
   32 
   33 /*
   34  * compute the block number from a 
   35  * cyl-cyl-head-head structure
   36  */
   37 static inline int
   38 cchh2blk (cchh_t *ptr, struct hd_geometry *geo) {
   39         return ptr->cc * geo->heads * geo->sectors +
   40                ptr->hh * geo->sectors;
   41 }
   42 
   43 
   44 /*
   45  * compute the block number from a 
   46  * cyl-cyl-head-head-block structure
   47  */
   48 static inline int
   49 cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
   50         return ptr->cc * geo->heads * geo->sectors +
   51                 ptr->hh * geo->sectors +
   52                 ptr->b;
   53 }
   54 
   55 /*
   56  * We used to use ioctl_by_bdev in early 2.4, but it broke
   57  * between 2.4.9 and 2.4.18 somewhere.
   58  */
   59 extern int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
   60                             unsigned int no, unsigned long data);
   61 
   62 static int
   63 ibm_ioctl_unopened(struct block_device *bdev, unsigned cmd, unsigned long arg)
   64 {
   65         int res;
   66         mm_segment_t old_fs = get_fs();
   67 
   68         if (genhd_dasd_ioctl == NULL)
   69                 return -ENODEV;
   70 #if 0
   71         lock_kernel();
   72         if (bd_ops->owner)
   73                 __MOD_INC_USE_COUNT(bdev->bd_op->owner);
   74         unlock_kernel();
   75 #endif
   76         set_fs(KERNEL_DS);
   77         res = (*genhd_dasd_ioctl)(bdev->bd_inode, NULL, cmd, arg);
   78         set_fs(old_fs);
   79 #if 0
   80         lock_kernel();
   81         if (bd_ops->owner)
   82                 __MOD_DEV_USE_COUNT(bd_ops->owner);
   83         unlock_kernel();
   84 #endif
   85         return res;
   86 }
   87 
   88 /*
   89  */
   90 int 
   91 ibm_partition(struct gendisk *hd, struct block_device *bdev,
   92               unsigned long first_sector, int first_part_minor)
   93 {
   94         int blocksize, offset, size;
   95         dasd_information_t *info;
   96         struct hd_geometry *geo;
   97         char type[5] = {0,};
   98         char name[7] = {0,};
   99         volume_label_t *vlabel;
  100         unsigned char *data;
  101         Sector sect;
  102 
  103         if ( first_sector != 0 )
  104                 BUG();
  105 
  106         if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
  107                 goto out_noinfo;
  108         if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
  109                 goto out_nogeo;
  110         if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL)
  111                 goto out_novlab;
  112 
  113         if (ibm_ioctl_unopened(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
  114             ibm_ioctl_unopened(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
  115                 goto out_noioctl;
  116 
  117         if ((blocksize = get_hardsect_size(to_kdev_t(bdev->bd_dev))) <= 0)
  118                 goto out_badsect;
  119 
  120         /*
  121          * Get volume label, extract name and type.
  122          */
  123         data = read_dev_sector(bdev, info->label_block*(blocksize/512), &sect);
  124         if (data == NULL)
  125                 goto out_readerr;
  126         strncpy (type, data, 4);
  127         if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
  128                 strncpy(name, data + 8, 6);
  129         else
  130                 strncpy(name, data + 4, 6);
  131         memcpy (vlabel, data, sizeof(volume_label_t));
  132         put_dev_sector(sect);
  133 
  134         EBCASC(type, 4);
  135         EBCASC(name, 6);
  136 
  137         /*
  138          * Three different types: CMS1, VOL1 and LNX1/unlabeled
  139          */
  140         if (strncmp(type, "CMS1", 4) == 0) {
  141                 /*
  142                  * VM style CMS1 labeled disk
  143                  */
  144                 int *label = (int *) data;
  145 
  146                 if (label[13] != 0) {
  147                         printk("CMS1/%8s(MDSK):", name);
  148                         /* disk is reserved minidisk */
  149                         blocksize = label[3];
  150                         offset = label[13];
  151                         size = (label[7] - 1)*(blocksize >> 9);
  152                 } else {
  153                         printk("CMS1/%8s:", name);
  154                         offset = (info->label_block + 1);
  155                         size = bdev->bd_inode->i_size >> 9;
  156                 }
  157                 // add_gd_partition(hd, first_part_minor - 1, 0, size);
  158                 add_gd_partition(hd, first_part_minor,
  159                                  offset*(blocksize >> 9),
  160                                  size-offset*(blocksize >> 9));
  161         } else if (strncmp(type, "VOL1", 4) == 0) {
  162                 /*
  163                  * New style VOL1 labeled disk
  164                  */
  165                 unsigned int blk;
  166                 int counter;
  167 
  168                 printk("VOL1/%8s:", name);
  169 
  170                 /* get block number and read then go through format1 labels */
  171                 blk = cchhb2blk(&vlabel->vtoc, geo) + 1;
  172                 counter = 0;
  173                 while ((data = read_dev_sector(bdev, blk*(blocksize/512),
  174                                                &sect)) != NULL) {
  175                         format1_label_t f1;
  176 
  177                         memcpy(&f1, data, sizeof(format1_label_t));
  178                         put_dev_sector(sect);
  179 
  180                         /* skip FMT4 / FMT5 / FMT7 labels */
  181                         if (f1.DS1FMTID == _ascebc['4']
  182                             || f1.DS1FMTID == _ascebc['5']
  183                             || f1.DS1FMTID == _ascebc['7']) {
  184                                 blk++;
  185                                 continue;
  186                         }
  187 
  188                         /* only FMT1 valid at this point */
  189                         if (f1.DS1FMTID != _ascebc['1'])
  190                                 break;
  191 
  192                         /* OK, we got valid partition data */
  193                         offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
  194                         size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) - 
  195                                 offset + geo->sectors;
  196                         if (counter >= hd->max_p)
  197                                 break;
  198                         add_gd_partition(hd, first_part_minor + counter, 
  199                                          offset * (blocksize >> 9),
  200                                          size * (blocksize >> 9));
  201                         counter++;
  202                         blk++;
  203                 }
  204         } else {
  205                 /*
  206                  * Old style LNX1 or unlabeled disk
  207                  */
  208                 if (strncmp(type, "LNX1", 4) == 0)
  209                         printk ("LNX1/%8s:", name);
  210                 else
  211                         printk("(nonl)/%8s:", name);
  212                 offset = (info->label_block + 1);
  213                 size = (bdev->bd_inode->i_size >> 9);
  214                 // add_gd_partition(hd, first_part_minor - 1, 0, size);
  215                 add_gd_partition(hd, first_part_minor,
  216                                  offset*(blocksize >> 9),
  217                                   size-offset*(blocksize >> 9));
  218         }
  219 
  220         printk("\n");
  221         kfree(vlabel);
  222         kfree(geo);
  223         kfree(info);
  224         return 1;
  225 
  226 out_readerr:
  227 out_badsect:
  228 out_noioctl:
  229         kfree(vlabel);
  230 out_novlab:
  231         kfree(geo);
  232 out_nogeo:
  233         kfree(info);
  234 out_noinfo:
  235         return 0;
  236 }

Cache object: b91fa2bf888157ef2c2190bc7049590d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.