Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
8.2 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1998
  3. Module Name:
  4. physlogi.c
  5. Abstract:
  6. This module contains functions used specifically by tape drivers.
  7. It contains functions that do physical to pseudo-logical and pseudo-
  8. logical to physical tape block address/position translation.
  9. Environment:
  10. kernel mode only
  11. Revision History:
  12. --*/
  13. #include "ntddk.h"
  14. #include "physlogi.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, TapeClassPhysicalBlockToLogicalBlock)
  17. #pragma alloc_text(PAGE, TapeClassLogicalBlockToPhysicalBlock)
  18. #endif
  19. //
  20. // defines for various QIC physical tape format constants
  21. //
  22. #define QIC_150_BOT_OFFSET 2
  23. #define QIC_525_PSEUDO_PHYSICAL_BLOCK_SIZE 512
  24. #define QIC_525_PHYSICAL_BLOCK_SIZE 1024
  25. #define QIC_525_DATA_BLKS_PER_FRAME 14
  26. #define QIC_525_ECC_BLKS_PER_FRAME 2
  27. #define QIC_525_BLKS_PER_FRAME 16
  28. #define QIC_525_BOT_OFFSET 16
  29. #define QIC_1350_PHYSICAL_BLOCK_SIZE 512
  30. #define QIC_1350_DATA_BLKS_PER_FRAME 52
  31. #define QIC_1350_ECC_BLKS_PER_FRAME 12
  32. #define QIC_1350_BLKS_PER_FRAME 64
  33. #define QIC_1350_BOT_OFFSET 64
  34. ULONG
  35. TapeClassPhysicalBlockToLogicalBlock(
  36. IN UCHAR DensityCode,
  37. IN ULONG PhysicalBlockAddress,
  38. IN ULONG BlockLength,
  39. IN BOOLEAN FromBOT
  40. )
  41. /*++
  42. Routine Description:
  43. This routine will translate from a QIC physical tape format
  44. specific physical/absolute block address to a pseudo-logical
  45. block address.
  46. Arguments:
  47. DensityCode // tape media density code
  48. PhysicalBlockAddress // tape format specific tape block address
  49. BlockLength // mode select/sense block length setting
  50. FromBOT // true/false - translate from BOT
  51. Return Value:
  52. ULONG
  53. --*/
  54. {
  55. ULONG logicalBlockAddress;
  56. ULONG frames;
  57. PAGED_CODE();
  58. logicalBlockAddress = PhysicalBlockAddress;
  59. switch ( DensityCode ) {
  60. case 0:
  61. logicalBlockAddress = 0xFFFFFFFF;
  62. break;
  63. case QIC_24:
  64. logicalBlockAddress--;
  65. break;
  66. case QIC_120:
  67. logicalBlockAddress--;
  68. break;
  69. case QIC_150:
  70. if (FromBOT) {
  71. if (logicalBlockAddress > QIC_150_BOT_OFFSET) {
  72. logicalBlockAddress -= QIC_150_BOT_OFFSET;
  73. } else {
  74. logicalBlockAddress = 0;
  75. }
  76. } else {
  77. logicalBlockAddress--;
  78. }
  79. break;
  80. case QIC_525:
  81. case QIC_1000:
  82. case QIC_2GB:
  83. if (FromBOT && (logicalBlockAddress >= QIC_525_BOT_OFFSET)) {
  84. logicalBlockAddress -= QIC_525_BOT_OFFSET;
  85. }
  86. if (logicalBlockAddress != 0) {
  87. frames = logicalBlockAddress/QIC_525_BLKS_PER_FRAME;
  88. logicalBlockAddress -= QIC_525_ECC_BLKS_PER_FRAME*frames;
  89. switch (BlockLength) {
  90. case QIC_525_PHYSICAL_BLOCK_SIZE:
  91. break;
  92. case QIC_525_PSEUDO_PHYSICAL_BLOCK_SIZE:
  93. logicalBlockAddress *= 2;
  94. break;
  95. default:
  96. if (BlockLength > QIC_525_PHYSICAL_BLOCK_SIZE) {
  97. if ((BlockLength%QIC_525_PHYSICAL_BLOCK_SIZE) == 0) {
  98. logicalBlockAddress /=
  99. BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE;
  100. } else {
  101. logicalBlockAddress /=
  102. 1+(BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE);
  103. }
  104. }
  105. break;
  106. }
  107. }
  108. break;
  109. case QIC_1350:
  110. case QIC_2100:
  111. if (FromBOT && (logicalBlockAddress >= QIC_1350_BOT_OFFSET)) {
  112. logicalBlockAddress -= QIC_1350_BOT_OFFSET;
  113. }
  114. if (logicalBlockAddress != 0) {
  115. frames = logicalBlockAddress/QIC_1350_BLKS_PER_FRAME;
  116. logicalBlockAddress -= QIC_1350_ECC_BLKS_PER_FRAME*frames;
  117. if (BlockLength > QIC_1350_PHYSICAL_BLOCK_SIZE) {
  118. if ((BlockLength%QIC_1350_PHYSICAL_BLOCK_SIZE) == 0) {
  119. logicalBlockAddress /=
  120. BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE;
  121. } else {
  122. logicalBlockAddress /=
  123. 1+(BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE);
  124. }
  125. }
  126. }
  127. break;
  128. }
  129. return logicalBlockAddress;
  130. } // end TapeClassPhysicalBlockToLogicalBlock()
  131. TAPE_PHYS_POSITION
  132. TapeClassLogicalBlockToPhysicalBlock(
  133. IN UCHAR DensityCode,
  134. IN ULONG LogicalBlockAddress,
  135. IN ULONG BlockLength,
  136. IN BOOLEAN FromBOT
  137. )
  138. /*++
  139. Routine Description:
  140. This routine will translate from a pseudo-logical block address
  141. to a QIC physical tape format specific physical/absolute block
  142. address and (space) block delta.
  143. Arguments:
  144. DensityCode // tape media density code
  145. LogicalBlockAddress // pseudo-logical tape block address
  146. BlockLength // mode select/sense block length setting
  147. FromBOT // true/false - translate from BOT
  148. Return Value:
  149. TAPE_PHYS_POSITION info/structure
  150. --*/
  151. {
  152. TAPE_PHYS_POSITION physPosition;
  153. ULONG physicalBlockAddress;
  154. ULONG remainder = 0;
  155. ULONG frames;
  156. PAGED_CODE();
  157. physicalBlockAddress = LogicalBlockAddress;
  158. switch ( DensityCode ) {
  159. case 0:
  160. physicalBlockAddress = 0xFFFFFFFF;
  161. break;
  162. case QIC_24:
  163. physicalBlockAddress++;
  164. break;
  165. case QIC_120:
  166. physicalBlockAddress++;
  167. break;
  168. case QIC_150:
  169. if (FromBOT) {
  170. physicalBlockAddress += QIC_150_BOT_OFFSET;
  171. } else {
  172. physicalBlockAddress++;
  173. }
  174. break;
  175. case QIC_525:
  176. case QIC_1000:
  177. case QIC_2GB:
  178. if (physicalBlockAddress != 0) {
  179. switch (BlockLength) {
  180. case QIC_525_PHYSICAL_BLOCK_SIZE:
  181. break;
  182. case QIC_525_PSEUDO_PHYSICAL_BLOCK_SIZE:
  183. remainder = physicalBlockAddress & 0x00000001;
  184. physicalBlockAddress >>= 1;
  185. break;
  186. default:
  187. if (BlockLength > QIC_525_PHYSICAL_BLOCK_SIZE) {
  188. if ((BlockLength%QIC_525_PHYSICAL_BLOCK_SIZE) == 0) {
  189. physicalBlockAddress *=
  190. BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE;
  191. } else {
  192. physicalBlockAddress *=
  193. 1+(BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE);
  194. }
  195. }
  196. break;
  197. }
  198. frames = physicalBlockAddress/QIC_525_DATA_BLKS_PER_FRAME;
  199. physicalBlockAddress += QIC_525_ECC_BLKS_PER_FRAME*frames;
  200. }
  201. if (FromBOT) {
  202. physicalBlockAddress += QIC_525_BOT_OFFSET;
  203. }
  204. break;
  205. case QIC_1350:
  206. case QIC_2100:
  207. if (physicalBlockAddress != 0) {
  208. if (BlockLength > QIC_1350_PHYSICAL_BLOCK_SIZE) {
  209. if ((BlockLength%QIC_1350_PHYSICAL_BLOCK_SIZE) == 0) {
  210. physicalBlockAddress *=
  211. BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE;
  212. } else {
  213. physicalBlockAddress *=
  214. 1+(BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE);
  215. }
  216. }
  217. frames = physicalBlockAddress/QIC_1350_DATA_BLKS_PER_FRAME;
  218. physicalBlockAddress += QIC_1350_ECC_BLKS_PER_FRAME*frames;
  219. }
  220. if (FromBOT) {
  221. physicalBlockAddress += QIC_1350_BOT_OFFSET;
  222. }
  223. break;
  224. }
  225. physPosition.SeekBlockAddress = physicalBlockAddress;
  226. physPosition.SpaceBlockCount = remainder;
  227. return physPosition;
  228. } // end TapeClassLogicalBlockToPhysicalBlock()