Leaked source code of windows server 2003
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.

316 lines
8.2 KiB

  1. #include "arccodes.h"
  2. #include "bootx86.h"
  3. #include "flop.h"
  4. #ifdef FLOPPY_CACHE
  5. //#define FLOPPY_CACHE_DEBUG
  6. #ifdef FLOPPY_CACHE_DEBUG
  7. #define DBGOUT(x) BlPrint x
  8. #else
  9. #define DBGOUT(x)
  10. #endif
  11. #define MAX_FLOPPY_LEN 1474560
  12. UCHAR CachedDiskImage[MAX_FLOPPY_LEN];
  13. UCHAR CachedDiskBadSectorMap[(MAX_FLOPPY_LEN/512)];
  14. UCHAR CachedDiskCylinderMap[80];
  15. USHORT CachedDiskBytesPerSector;
  16. USHORT CachedDiskSectorsPerTrack;
  17. USHORT CachedDiskSectorsPerCylinder;
  18. USHORT CachedDiskBytesPerTrack;
  19. ULONG CachedDiskLastSector;
  20. BOOLEAN DiskInCache = FALSE;
  21. VOID
  22. FcpCacheOneCylinder(
  23. IN USHORT Cylinder
  24. )
  25. {
  26. PUCHAR pCache;
  27. unsigned track,sector;
  28. ULONG AbsoluteSector;
  29. ARC_STATUS Status;
  30. unsigned retry;
  31. //
  32. // Calculate the location in the cache image where this cylinder should go.
  33. //
  34. AbsoluteSector = Cylinder * CachedDiskSectorsPerCylinder;
  35. pCache = CachedDiskImage + (AbsoluteSector * CachedDiskBytesPerSector);
  36. //
  37. // Read track 0 and 1 of this cylinder.
  38. //
  39. for(track=0; track<2; track++) {
  40. DBGOUT(("FcCacheFloppyDisk: Cylinder %u head %u: ",Cylinder,track));
  41. retry = 0;
  42. do {
  43. Status = GET_SECTOR(
  44. 2, // int13 request = read
  45. 0, // disk number (a:)
  46. (USHORT)track, // head (0 or 1)
  47. Cylinder, // track (usually 0-79)
  48. 1, // sector number (1-based)
  49. CachedDiskSectorsPerTrack, // number of sectors to read
  50. LocalBuffer // buffer
  51. );
  52. if(Status) {
  53. retry++;
  54. RESET_DISK(0,0,0,0,0,0,0);
  55. }
  56. } while(Status && (retry <= 3));
  57. if(Status) {
  58. DBGOUT(("Error!\n"));
  59. //
  60. // One or more sectors in the track were bad -- read individually.
  61. //
  62. for(sector=1; sector<=CachedDiskSectorsPerTrack; sector++) {
  63. DBGOUT((" Sector %u: ",sector));
  64. retry = 0;
  65. do {
  66. Status = GET_SECTOR(
  67. 2, // int13 request = read
  68. 0, // disk number (a:)
  69. (USHORT)track, // head (0 or 1)
  70. Cylinder, // cylinder (usually 0-79)
  71. (USHORT)sector, // sector number (1-based)
  72. 1, // number of sectors to read
  73. LocalBuffer // buffer
  74. );
  75. if(Status) {
  76. retry++;
  77. RESET_DISK(0,0,0,0,0,0,0);
  78. }
  79. } while(Status && (retry <= 2));
  80. if(Status) {
  81. //
  82. // Sector is bad.
  83. //
  84. CachedDiskBadSectorMap[AbsoluteSector] = TRUE;
  85. DBGOUT(("bad\n"));
  86. } else {
  87. //
  88. // Sector is good. Transfer the data into the cache buffer.
  89. //
  90. RtlMoveMemory(pCache,LocalBuffer,CachedDiskBytesPerSector);
  91. DBGOUT(("OK\n"));
  92. }
  93. //
  94. // Advance to the next sector in the cache buffer.
  95. //
  96. pCache += CachedDiskBytesPerSector;
  97. AbsoluteSector++;
  98. }
  99. } else {
  100. //
  101. // Transfer the whole track we just successfully read
  102. // into the cached disk buffer.
  103. //
  104. RtlMoveMemory(pCache,LocalBuffer,CachedDiskBytesPerTrack);
  105. pCache += CachedDiskBytesPerTrack;
  106. AbsoluteSector += CachedDiskSectorsPerTrack;
  107. DBGOUT(("OK\n"));
  108. }
  109. }
  110. CachedDiskCylinderMap[Cylinder] = TRUE;
  111. }
  112. BOOLEAN
  113. FcIsThisFloppyCached(
  114. IN PUCHAR Buffer
  115. )
  116. {
  117. if(!DiskInCache) {
  118. return(FALSE);
  119. }
  120. //
  121. // Compare the first 512 bytes of the cached disk
  122. // to the buffer passed in. If they are equal,
  123. // then the disk is already cached.
  124. //
  125. if(RtlCompareMemory(CachedDiskImage,Buffer,512) == 512) {
  126. return(TRUE);
  127. }
  128. //
  129. // Disk is not cached.
  130. //
  131. return(FALSE);
  132. }
  133. VOID
  134. FcUncacheFloppyDisk(
  135. VOID
  136. )
  137. {
  138. DiskInCache = FALSE;
  139. }
  140. VOID
  141. FcCacheFloppyDisk(
  142. PBIOS_PARAMETER_BLOCK Bpb
  143. )
  144. {
  145. //
  146. // Indicate that the cache is invalid.
  147. //
  148. DiskInCache = FALSE;
  149. //
  150. // Sanity check the bpb.
  151. // Ensure it's a standard 1.2 meg or 1.44 meg disk.
  152. //
  153. if((Bpb->Heads != 2) || (Bpb->BytesPerSector != 512)
  154. || ((Bpb->SectorsPerTrack != 15) && (Bpb->SectorsPerTrack != 18))
  155. || ((Bpb->Sectors != 2880) && (Bpb->Sectors != 2400)))
  156. {
  157. DBGOUT(("FcCacheFloppyDisk: floppy not standard 1.2 or 1.44 meg disk\n"));
  158. return;
  159. }
  160. //
  161. // Grab a buffer under the 1 meg line.
  162. // The buffer must be big enough to hold one whole track of
  163. // a 1.44 meg floppy.
  164. //
  165. if(LocalBuffer == NULL) {
  166. LocalBuffer = FwAllocateHeap(18 * 512);
  167. if(LocalBuffer == NULL) {
  168. DBGOUT(("FcCacheFloppyDisk: Couldn't allocate local buffer\n"));
  169. return;
  170. }
  171. }
  172. DBGOUT(("FcCacheFloppyDisk: LocalBuffer @ %lx\n",LocalBuffer));
  173. //
  174. // The disk is one we can cache. Indicate that a disk is cached
  175. // and mark all sectors good and all tracks not present.
  176. //
  177. DiskInCache = TRUE;
  178. RtlZeroMemory(CachedDiskBadSectorMap,sizeof(CachedDiskBadSectorMap));
  179. RtlZeroMemory(CachedDiskCylinderMap,sizeof(CachedDiskCylinderMap));
  180. CachedDiskSectorsPerTrack = Bpb->SectorsPerTrack;
  181. CachedDiskSectorsPerCylinder = Bpb->Heads * Bpb->SectorsPerTrack;
  182. CachedDiskBytesPerSector = Bpb->BytesPerSector;
  183. //
  184. // Calculate the number of bytes in a Track on the floppy.
  185. //
  186. CachedDiskBytesPerTrack = CachedDiskSectorsPerTrack * Bpb->BytesPerSector;
  187. //
  188. // Calculate the number of tracks.
  189. //
  190. CachedDiskLastSector = Bpb->Sectors-1;
  191. DBGOUT(("FcCacheFloppyDisk: Caching disk, %u sectors per track\n",CachedDiskSectorsPerTrack));
  192. FcpCacheOneCylinder(0);
  193. }
  194. ARC_STATUS
  195. FcReadFromCache(
  196. IN ULONG Offset,
  197. IN ULONG Length,
  198. OUT PUCHAR Buffer
  199. )
  200. {
  201. ULONG FirstSector,LastSector,Sector;
  202. ULONG FirstCyl,LastCyl,cyl;
  203. if(!Length) {
  204. return(ESUCCESS);
  205. }
  206. if(!DiskInCache) {
  207. return(EINVAL);
  208. }
  209. //
  210. // Determine the first sector in the transfer.
  211. //
  212. FirstSector = Offset / 512;
  213. //
  214. // Determine and validate the last sector in the transfer.
  215. //
  216. LastSector = FirstSector + ((Length-1)/512);
  217. if(LastSector > CachedDiskLastSector) {
  218. return(E2BIG);
  219. }
  220. //
  221. // Determine the first and last cylinders involved in the transfer.
  222. //
  223. FirstCyl = FirstSector / CachedDiskSectorsPerCylinder;
  224. LastCyl = LastSector / CachedDiskSectorsPerCylinder;
  225. //
  226. // Make sure all these cylinders are cached.
  227. //
  228. for(cyl=FirstCyl; cyl<=LastCyl; cyl++) {
  229. if(!CachedDiskCylinderMap[cyl]) {
  230. FcpCacheOneCylinder((USHORT)cyl);
  231. }
  232. }
  233. //
  234. // Determine if any of the sectors in the transfer range
  235. // are marked bad in the sector map.
  236. //
  237. // If so, return an i/o error.
  238. //
  239. for(Sector=FirstSector; Sector<=LastSector; Sector++) {
  240. if(CachedDiskBadSectorMap[Sector]) {
  241. return(EIO);
  242. }
  243. }
  244. //
  245. // Transfer the data into the caller's buffer.
  246. //
  247. RtlMoveMemory(Buffer,CachedDiskImage+Offset,Length);
  248. return(ESUCCESS);
  249. }
  250. #endif // def FLOPPY_CACHE