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.

302 lines
6.3 KiB

  1. /*++
  2. Copyright (c) 1991-1998 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. Author:
  7. Neil Sandlin (neilsa) 26-Apr-99
  8. Environment:
  9. Kernel mode only.
  10. --*/
  11. #include "pch.h"
  12. //
  13. // Internal References
  14. //
  15. ULONG
  16. MemCardGetCapacityFromCIS(
  17. IN PMEMCARD_EXTENSION memcardExtension
  18. );
  19. ULONG
  20. MemCardGetCapacityFromBootSector(
  21. IN PMEMCARD_EXTENSION memcardExtension
  22. );
  23. ULONG
  24. MemCardProbeForCapacity(
  25. IN PMEMCARD_EXTENSION memcardExtension
  26. );
  27. #ifdef ALLOC_PRAGMA
  28. #pragma alloc_text(PAGE,MemCardGetCapacityFromCIS)
  29. #pragma alloc_text(PAGE,MemCardGetCapacityFromBootSector)
  30. #pragma alloc_text(PAGE,MemCardProbeForCapacity)
  31. #endif
  32. ULONG
  33. MemCardGetCapacity(
  34. IN PMEMCARD_EXTENSION memcardExtension
  35. )
  36. /*++
  37. Routine Description:
  38. Arguments:
  39. device extension for the card
  40. Return Value:
  41. --*/
  42. {
  43. ULONG capacity;
  44. capacity = MemCardGetCapacityFromCIS(memcardExtension);
  45. if (capacity) {
  46. return capacity;
  47. }
  48. capacity = MemCardGetCapacityFromBootSector(memcardExtension);
  49. if (capacity) {
  50. return capacity;
  51. }
  52. return MemCardProbeForCapacity(memcardExtension);
  53. }
  54. ULONG
  55. MemCardGetCapacityFromBootSector(
  56. IN PMEMCARD_EXTENSION memcardExtension
  57. )
  58. /*++
  59. Routine Description:
  60. Arguments:
  61. device extension for the card
  62. Return Value:
  63. --*/
  64. {
  65. NTSTATUS status;
  66. BOOT_SECTOR_INFO BootSector;
  67. ULONG capacity = 0;
  68. status = MEMCARD_READ(memcardExtension, 0, &BootSector, sizeof(BootSector));
  69. if (NT_SUCCESS(status)) {
  70. #define BYTES_PER_SECTOR 512
  71. //
  72. // see if this really looks like a boot sector
  73. // These are the same tests done in the win9x sram support
  74. //
  75. if ((BootSector.JumpByte == 0xE9 || BootSector.JumpByte == 0xEB) &&
  76. BootSector.BytesPerSector == BYTES_PER_SECTOR &&
  77. BootSector.SectorsPerCluster != 0 &&
  78. BootSector.ReservedSectors == 1 &&
  79. (BootSector.NumberOfFATs == 1 || BootSector.NumberOfFATs == 2) &&
  80. BootSector.RootEntries != 0 && (BootSector.RootEntries & 15) == 0 &&
  81. (BootSector.TotalSectors != 0 || BootSector.BigTotalSectors != 0) &&
  82. BootSector.SectorsPerFAT != 0 &&
  83. BootSector.SectorsPerTrack != 0 &&
  84. BootSector.Heads != 0 &&
  85. BootSector.MediaDescriptor >= 0xF0) {
  86. //
  87. // Finally it appears valid, return total size of region.
  88. //
  89. capacity = BootSector.TotalSectors * BYTES_PER_SECTOR;
  90. }
  91. }
  92. return capacity;
  93. }
  94. ULONG
  95. MemCardGetCapacityFromCIS(
  96. IN PMEMCARD_EXTENSION memcardExtension
  97. )
  98. /*++
  99. Routine Description:
  100. This is a quick and dirty routine to read the tuples of the card, if they
  101. exist, to get the capacity.
  102. Arguments:
  103. device extension for the card
  104. Return Value:
  105. The # of bytes of memory on the device
  106. --*/
  107. {
  108. UCHAR tupleData[16];
  109. ULONG bytesRead;
  110. ULONG dataCount;
  111. ULONG unitSize;
  112. ULONG unitCount;
  113. ULONG i;
  114. //
  115. // get device capacity
  116. // all this stuff should really be in the bus driver
  117. //
  118. bytesRead = (memcardExtension->PcmciaBusInterface.ReadConfig)(memcardExtension->UnderlyingPDO,
  119. PCCARD_ATTRIBUTE_MEMORY,
  120. tupleData,
  121. 0,
  122. 16);
  123. if ((bytesRead != 16) || (tupleData[0] != 1)){
  124. return 0;
  125. }
  126. dataCount = (ULONG)tupleData[1];
  127. if ((dataCount < 2) || (dataCount>14)){
  128. return 0;
  129. }
  130. i = 3;
  131. if ((tupleData[2] & 7) == 7) {
  132. while(tupleData[i] & 0x80) {
  133. if ((i-2) > dataCount) {
  134. return 0;
  135. }
  136. i++;
  137. }
  138. }
  139. if ((tupleData[i]&7) == 7) {
  140. return 0;
  141. }
  142. unitSize = 512 << ((tupleData[i]&7)*2);
  143. unitCount = (tupleData[i]>>3)+1;
  144. return(unitCount * unitSize);
  145. }
  146. ULONG
  147. MemCardProbeForCapacity(
  148. IN PMEMCARD_EXTENSION memcardExtension
  149. )
  150. /*++
  151. Routine Description:
  152. Since we were unable to determine the card capacity through other means,
  153. here we actually write stuff out on the card to check how big it is.
  154. This algorithm for testing the card capacity was ported from win9x.
  155. Arguments:
  156. device extension for the card
  157. Return Value:
  158. byte capacity of device
  159. --*/
  160. {
  161. NTSTATUS status;
  162. ULONG capacity = 0;
  163. USHORT origValue, ChkValue, StartValue;
  164. USHORT mcSig = 'Mc';
  165. USHORT zeroes = 0;
  166. #define SRAM_BLK_SIZE (16*1024)
  167. ULONG CardOff = SRAM_BLK_SIZE;
  168. USHORT CurValue;
  169. if ((memcardExtension->PcmciaInterface.IsWriteProtected)(memcardExtension->UnderlyingPDO)) {
  170. return 0;
  171. }
  172. //
  173. //
  174. if (!NT_SUCCESS(MEMCARD_READ (memcardExtension, 0, &origValue, sizeof(origValue))) ||
  175. !NT_SUCCESS(MEMCARD_WRITE(memcardExtension, 0, &mcSig, sizeof(mcSig))) ||
  176. !NT_SUCCESS(MEMCARD_READ (memcardExtension, 0, &ChkValue, sizeof(ChkValue)))) {
  177. return 0;
  178. }
  179. if (ChkValue != mcSig) {
  180. //
  181. // not sram
  182. //
  183. return 0;
  184. }
  185. for (;;) {
  186. if (!NT_SUCCESS(MEMCARD_READ (memcardExtension, CardOff, &CurValue, sizeof(CurValue))) ||
  187. !NT_SUCCESS(MEMCARD_WRITE(memcardExtension, CardOff, &zeroes, sizeof(zeroes))) ||
  188. !NT_SUCCESS(MEMCARD_READ (memcardExtension, CardOff, &ChkValue, sizeof(ChkValue))) ||
  189. !NT_SUCCESS(MEMCARD_READ (memcardExtension, 0, &StartValue, sizeof(StartValue)))) {
  190. break;
  191. }
  192. // We stop when either we can't write 0 anymore or the 0
  193. // has wrapped over the 0x9090 at card offset 0
  194. if (ChkValue != zeroes || StartValue == zeroes) {
  195. capacity = CardOff;
  196. break;
  197. }
  198. // Restore the saved value from the start of the block.
  199. if (!NT_SUCCESS(MEMCARD_WRITE(memcardExtension, CardOff, &CurValue, sizeof(CurValue)))) {
  200. break;
  201. }
  202. CardOff += SRAM_BLK_SIZE; // increment to the next block
  203. }
  204. //
  205. // try to restore original value
  206. //
  207. MEMCARD_WRITE(memcardExtension, 0, &origValue, sizeof(origValue));
  208. return capacity;
  209. }