ibm.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include <linux/buffer_head.h>
  9. #include <linux/hdreg.h>
  10. #include <linux/slab.h>
  11. #include <asm/dasd.h>
  12. #include <asm/ebcdic.h>
  13. #include <asm/uaccess.h>
  14. #include <asm/vtoc.h>
  15. #include "check.h"
  16. #include "ibm.h"
  17. /*
  18. * compute the block number from a
  19. * cyl-cyl-head-head structure
  20. */
  21. static inline int
  22. cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
  23. return ptr->cc * geo->heads * geo->sectors +
  24. ptr->hh * geo->sectors;
  25. }
  26. /*
  27. * compute the block number from a
  28. * cyl-cyl-head-head-block structure
  29. */
  30. static inline int
  31. cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
  32. return ptr->cc * geo->heads * geo->sectors +
  33. ptr->hh * geo->sectors +
  34. ptr->b;
  35. }
  36. /*
  37. */
  38. int
  39. ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
  40. {
  41. int blocksize, offset, size,res;
  42. loff_t i_size;
  43. dasd_information2_t *info;
  44. struct hd_geometry *geo;
  45. char type[5] = {0,};
  46. char name[7] = {0,};
  47. union label_t {
  48. struct vtoc_volume_label vol;
  49. struct vtoc_cms_label cms;
  50. } *label;
  51. unsigned char *data;
  52. Sector sect;
  53. res = 0;
  54. blocksize = bdev_hardsect_size(bdev);
  55. if (blocksize <= 0)
  56. goto out_exit;
  57. i_size = i_size_read(bdev->bd_inode);
  58. if (i_size == 0)
  59. goto out_exit;
  60. info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
  61. if (info == NULL)
  62. goto out_exit;
  63. geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
  64. if (geo == NULL)
  65. goto out_nogeo;
  66. label = kmalloc(sizeof(union label_t), GFP_KERNEL);
  67. if (label == NULL)
  68. goto out_nolab;
  69. if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
  70. ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
  71. goto out_freeall;
  72. /*
  73. * Get volume label, extract name and type.
  74. */
  75. data = read_dev_sector(bdev, info->label_block*(blocksize/512), &sect);
  76. if (data == NULL)
  77. goto out_readerr;
  78. strncpy (type, data, 4);
  79. if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
  80. strncpy(name, data + 8, 6);
  81. else
  82. strncpy(name, data + 4, 6);
  83. memcpy(label, data, sizeof(union label_t));
  84. put_dev_sector(sect);
  85. EBCASC(type, 4);
  86. EBCASC(name, 6);
  87. res = 1;
  88. /*
  89. * Three different formats: LDL, CDL and unformated disk
  90. *
  91. * identified by info->format
  92. *
  93. * unformated disks we do not have to care about
  94. */
  95. if (info->format == DASD_FORMAT_LDL) {
  96. if (strncmp(type, "CMS1", 4) == 0) {
  97. /*
  98. * VM style CMS1 labeled disk
  99. */
  100. if (label->cms.disk_offset != 0) {
  101. printk("CMS1/%8s(MDSK):", name);
  102. /* disk is reserved minidisk */
  103. blocksize = label->cms.block_size;
  104. offset = label->cms.disk_offset;
  105. size = (label->cms.block_count - 1)
  106. * (blocksize >> 9);
  107. } else {
  108. printk("CMS1/%8s:", name);
  109. offset = (info->label_block + 1);
  110. size = i_size >> 9;
  111. }
  112. } else {
  113. /*
  114. * Old style LNX1 or unlabeled disk
  115. */
  116. if (strncmp(type, "LNX1", 4) == 0)
  117. printk ("LNX1/%8s:", name);
  118. else
  119. printk("(nonl)");
  120. offset = (info->label_block + 1);
  121. size = i_size >> 9;
  122. }
  123. put_partition(state, 1, offset*(blocksize >> 9),
  124. size-offset*(blocksize >> 9));
  125. } else if (info->format == DASD_FORMAT_CDL) {
  126. /*
  127. * New style CDL formatted disk
  128. */
  129. unsigned int blk;
  130. int counter;
  131. /*
  132. * check if VOL1 label is available
  133. * if not, something is wrong, skipping partition detection
  134. */
  135. if (strncmp(type, "VOL1", 4) == 0) {
  136. printk("VOL1/%8s:", name);
  137. /*
  138. * get block number and read then go through format1
  139. * labels
  140. */
  141. blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
  142. counter = 0;
  143. data = read_dev_sector(bdev, blk * (blocksize/512),
  144. &sect);
  145. while (data != NULL) {
  146. struct vtoc_format1_label f1;
  147. memcpy(&f1, data,
  148. sizeof(struct vtoc_format1_label));
  149. put_dev_sector(sect);
  150. /* skip FMT4 / FMT5 / FMT7 labels */
  151. if (f1.DS1FMTID == _ascebc['4']
  152. || f1.DS1FMTID == _ascebc['5']
  153. || f1.DS1FMTID == _ascebc['7']) {
  154. blk++;
  155. data = read_dev_sector(bdev, blk *
  156. (blocksize/512),
  157. &sect);
  158. continue;
  159. }
  160. /* only FMT1 valid at this point */
  161. if (f1.DS1FMTID != _ascebc['1'])
  162. break;
  163. /* OK, we got valid partition data */
  164. offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
  165. size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
  166. offset + geo->sectors;
  167. if (counter >= state->limit)
  168. break;
  169. put_partition(state, counter + 1,
  170. offset * (blocksize >> 9),
  171. size * (blocksize >> 9));
  172. counter++;
  173. blk++;
  174. data = read_dev_sector(bdev,
  175. blk * (blocksize/512),
  176. &sect);
  177. }
  178. if (!data)
  179. /* Are we not supposed to report this ? */
  180. goto out_readerr;
  181. } else
  182. printk(KERN_WARNING "Warning, expected Label VOL1 not "
  183. "found, treating as CDL formated Disk");
  184. }
  185. printk("\n");
  186. goto out_freeall;
  187. out_readerr:
  188. res = -1;
  189. out_freeall:
  190. kfree(label);
  191. out_nolab:
  192. kfree(geo);
  193. out_nogeo:
  194. kfree(info);
  195. out_exit:
  196. return res;
  197. }