ibm.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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