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.

430 lines
9.4 KiB

  1. #include "enduser.h"
  2. ULONG XmsEntry;
  3. unsigned XmsHandle;
  4. unsigned XmsMaxSectors;
  5. #pragma pack(1)
  6. struct {
  7. ULONG Count;
  8. USHORT SourceHandle;
  9. ULONG SourceOffset;
  10. USHORT DestinationHandle;
  11. ULONG DestinationOffset;
  12. } XmsParams;
  13. #pragma pack()
  14. VOID
  15. XmsInit(
  16. VOID
  17. )
  18. /*++
  19. Routine Description:
  20. Initiialize the XMS i/o package by checking to see
  21. if XMS memory is available and if so, grabbing the largest block
  22. we can.
  23. Arguments:
  24. None.
  25. Return Value:
  26. None.
  27. --*/
  28. {
  29. unsigned e_s=0,e_o=0;
  30. ULONG Entry;
  31. unsigned LargestBlock;
  32. unsigned Handle;
  33. BOOL b;
  34. //
  35. // Check XMS installed
  36. //
  37. _asm {
  38. mov ax,4300h
  39. int 2fh
  40. cmp al,80h
  41. jne xmschecked
  42. mov ax,4310h
  43. int 2fh
  44. mov e_o,bx
  45. mov bx,es
  46. mov e_s,bx
  47. xmschecked:
  48. }
  49. if(!e_s && !e_o) {
  50. FatalError(textNoXmsManager);
  51. }
  52. Entry = ((ULONG)e_s << 16) | e_o;
  53. //
  54. // Get size of largest block and make sure it's
  55. // large enough to make use of XMS worthwhile.
  56. // IoBuffer is 63*512 sectors, which is just under 32K.
  57. // So we want at least 32K. Also trim the block size
  58. // so the sector count will fit in a ushort.
  59. //
  60. _asm {
  61. mov ah,8
  62. call far ptr [Entry]
  63. mov LargestBlock,ax
  64. }
  65. if(LargestBlock < 32) {
  66. FatalError(textNoXmsManager);
  67. }
  68. if(LargestBlock > 32767) {
  69. LargestBlock = 32767;
  70. }
  71. //
  72. // Allocate the block.
  73. //
  74. _asm {
  75. mov ah,9
  76. mov dx,LargestBlock
  77. call far ptr [Entry]
  78. mov Handle,dx
  79. mov b,ax
  80. }
  81. if(!b) {
  82. FatalError(textNoXmsManager);
  83. }
  84. XmsEntry = Entry;
  85. XmsHandle = Handle;
  86. XmsMaxSectors = LargestBlock * 2 - 128; // actually it's * 1024/512
  87. // make it 64K smaller just in case.
  88. }
  89. VOID
  90. XmsTerminate(
  91. VOID
  92. )
  93. /*++
  94. Routine Description:
  95. Terminate XMS i/o by releasing any allocated block.
  96. Arguments:
  97. None.
  98. Return Value:
  99. None.
  100. --*/
  101. {
  102. ULONG Entry;
  103. int Handle;
  104. if(XmsEntry && XmsMaxSectors) {
  105. Entry = XmsEntry;
  106. Handle = XmsHandle;
  107. _asm {
  108. mov ah,0ah
  109. mov dx,Handle
  110. call far ptr [Entry]
  111. }
  112. XmsEntry = 0;
  113. XmsHandle = 0;
  114. XmsMaxSectors = 0;
  115. }
  116. }
  117. VOID
  118. XmsIoDiskRead(
  119. IN HDISK DiskHandle,
  120. IN ULONG StartSector,
  121. IN ULONG SectorCount,
  122. OUT ULONG *SectorsRead,
  123. OUT BOOL *Xms
  124. )
  125. /*++
  126. Routine Description:
  127. Read sectors from a disk.
  128. If the sector count is less then 64 or XMS is not available,
  129. then a maximum of 63 sectors will be read into the buffer
  130. pointed to by the IoBuffer global variable.
  131. If the sector count is greater than 63 and XMS is available,
  132. then as many sectors as will fit into our XMS buffer are
  133. read and buffered in XMS memory, using IoBuffer as the
  134. intermediary transfer buffer.
  135. Every read deltas the gas gauge by the number of sectors
  136. transferred.
  137. Arguments:
  138. DiskHandle - supplies disk handle of disk to be read from.
  139. StartSector - supplies first sector of read run.
  140. SectorCount - supplies the number of sectors the caller
  141. wants to read.
  142. SectorsRead - receives the number of sectors read, which is
  143. the minimum of the number of sectors the caller actually
  144. wants, and either 63 (non-xms case) or XmsSectors (xms case).
  145. Xms - recieves a value indicating whether the sectors were read
  146. and buffered in Xms memory. The caller may need to know this
  147. when he goes to write the data later.
  148. Return Value:
  149. None. Does not return if error.
  150. --*/
  151. {
  152. BYTE c;
  153. BOOL b;
  154. BYTE code;
  155. ULONG Entry;
  156. unsigned x_s,x_o;
  157. if((SectorCount <= 63) || !XmsMaxSectors) {
  158. //
  159. // Conventional memory only. I/O to IoBuffer.
  160. //
  161. *Xms = FALSE;
  162. if(SectorCount > 63) {
  163. SectorCount = 63;
  164. }
  165. if(!ReadDisk(DiskHandle,StartSector,(BYTE)SectorCount,IoBuffer)) {
  166. FatalError(textReadFailedAtSector,(UINT)SectorCount,StartSector);
  167. }
  168. *SectorsRead = SectorCount;
  169. GaugeDelta(SectorCount);
  170. return;
  171. }
  172. //
  173. // XMS read.
  174. //
  175. *Xms = TRUE;
  176. if(SectorCount > XmsMaxSectors) {
  177. SectorCount = XmsMaxSectors;
  178. }
  179. *SectorsRead = SectorCount;
  180. XmsParams.SourceHandle = 0;
  181. XmsParams.SourceOffset = (ULONG)IoBuffer;
  182. XmsParams.DestinationHandle = XmsHandle;
  183. XmsParams.DestinationOffset = 0;
  184. Entry = XmsEntry;
  185. x_s = (unsigned)((ULONG)(void _far *)&XmsParams >> 16);
  186. x_o = (unsigned)(ULONG)&XmsParams;
  187. while(SectorCount) {
  188. c = (BYTE)((SectorCount > 63L) ? 63L : SectorCount);
  189. if(!ReadDisk(DiskHandle,StartSector,c,IoBuffer)) {
  190. FatalError(textReadFailedAtSector,c,StartSector);
  191. }
  192. XmsParams.Count = c * 512L;
  193. _asm {
  194. push ds
  195. push si
  196. push x_s
  197. pop ds
  198. mov si,x_o
  199. mov ah,0bh
  200. call far ptr [Entry]
  201. mov b,ax
  202. mov code,bl
  203. pop si
  204. pop ds
  205. }
  206. if(!b) {
  207. FatalError(textXmsMemoryError,code);
  208. }
  209. XmsParams.DestinationOffset += XmsParams.Count;
  210. StartSector += c;
  211. SectorCount -= c;
  212. GaugeDelta(c);
  213. }
  214. }
  215. VOID
  216. XmsIoDiskWrite(
  217. IN HDISK DiskHandle,
  218. IN ULONG StartSector,
  219. IN ULONG SectorOffset,
  220. IN ULONG SectorCount,
  221. IN BOOL Xms
  222. )
  223. /*++
  224. Routine Description:
  225. Write sectors to a disk.
  226. Sectors are written either from IoBuffer or from XMS memory
  227. (using IoBuffer as the intermediary transfer buffer) as the caller
  228. specifies.
  229. Every write deltas the gas gauge by the number of sectors
  230. transferred.
  231. Arguments:
  232. DiskHandle - supplies disk handle of disk to write to.
  233. StartSector - supplies first sector of write run.
  234. SectorOffset - supplies the number of sectors to skip/ignore at
  235. the start of the i/o buffer (either IoBuffer or XMS memory).
  236. This allows the caller to write out a previously read run
  237. in chunks.
  238. SectorCount - supplies the number of sectors to write.
  239. Xms - supplies a value indicating whether the data to be written
  240. is in Xms memory. If not, it's in IoBuffer.
  241. Return Value:
  242. None. Does not return if error.
  243. --*/
  244. {
  245. BYTE c;
  246. BYTE i;
  247. BOOL b;
  248. BYTE code;
  249. ULONG Entry;
  250. unsigned x_s,x_o;
  251. if(!Xms) {
  252. //
  253. // Conventional memory only. I/O from IoBuffer.
  254. // SectorCount had better be <= 63!
  255. //
  256. if(!CmdLineArgs.Test) {
  257. i=0;
  258. while(i<3) {
  259. //
  260. // Retry a couple times. (My machine seems to randomly fail a write once in a while.)
  261. //
  262. if(WriteDisk(DiskHandle,
  263. StartSector,
  264. (BYTE)SectorCount,
  265. (FPBYTE)IoBuffer+((unsigned)SectorOffset*512))
  266. ) {
  267. if(i>0) {
  268. _Log(" *** Write succeeded retried %d times.\n", i );
  269. }
  270. break;
  271. }
  272. _Log(" *** Write error at sector %ld length %d attempt %d\n", StartSector,SectorCount, i );
  273. i++;
  274. }
  275. if(i==3) {
  276. FatalError(textWriteFailedAtSector,(UINT)SectorCount,StartSector);
  277. }
  278. }
  279. GaugeDelta(SectorCount);
  280. return;
  281. }
  282. //
  283. // XMS write. SectorCount had better be <= XmsMaxSectors!
  284. //
  285. XmsParams.SourceHandle = XmsHandle;
  286. XmsParams.SourceOffset = 512 * SectorOffset;
  287. XmsParams.DestinationHandle = 0;
  288. XmsParams.DestinationOffset = (ULONG)IoBuffer;
  289. Entry = XmsEntry;
  290. x_s = (unsigned)((ULONG)(void _far *)&XmsParams >> 16);
  291. x_o = (unsigned)(ULONG)&XmsParams;
  292. while(SectorCount) {
  293. c = (BYTE)((SectorCount > 63L) ? 63L : SectorCount);
  294. XmsParams.Count = c * 512L;
  295. _asm {
  296. push ds
  297. push si
  298. push x_s
  299. pop ds
  300. mov si,x_o
  301. mov ah,0bh
  302. call far ptr [Entry]
  303. mov b,ax
  304. mov code,bl
  305. pop si
  306. pop ds
  307. }
  308. if(!b) {
  309. FatalError(textXmsMemoryError,code);
  310. }
  311. if(!CmdLineArgs.Test) {
  312. i=0;
  313. while(i<3) {
  314. //
  315. // Retry a couple times. (My machine seems to randomly fail a write once in a while.)
  316. //
  317. if(WriteDisk(DiskHandle,StartSector,c,IoBuffer)) {
  318. if(i>0) {
  319. _Log(" *** Write succeeded retried %d times.\n", i );
  320. }
  321. break;
  322. }
  323. _Log(" *** Write error at sector %ld length %d attempt %d\n", StartSector, c, i );
  324. i++;
  325. }
  326. if(i==3) {
  327. FatalError(textWriteFailedAtSector,c,StartSector);
  328. }
  329. }
  330. XmsParams.SourceOffset += XmsParams.Count;
  331. StartSector += c;
  332. SectorCount -= c;
  333. GaugeDelta(c);
  334. }
  335. }