mirror of https://github.com/tongzx/nt5src
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
430 lines
9.4 KiB
#include "enduser.h"
|
|
|
|
|
|
ULONG XmsEntry;
|
|
unsigned XmsHandle;
|
|
unsigned XmsMaxSectors;
|
|
|
|
#pragma pack(1)
|
|
struct {
|
|
ULONG Count;
|
|
USHORT SourceHandle;
|
|
ULONG SourceOffset;
|
|
USHORT DestinationHandle;
|
|
ULONG DestinationOffset;
|
|
} XmsParams;
|
|
#pragma pack()
|
|
|
|
|
|
VOID
|
|
XmsInit(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initiialize the XMS i/o package by checking to see
|
|
if XMS memory is available and if so, grabbing the largest block
|
|
we can.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
unsigned e_s=0,e_o=0;
|
|
ULONG Entry;
|
|
unsigned LargestBlock;
|
|
unsigned Handle;
|
|
BOOL b;
|
|
|
|
//
|
|
// Check XMS installed
|
|
//
|
|
_asm {
|
|
mov ax,4300h
|
|
int 2fh
|
|
cmp al,80h
|
|
jne xmschecked
|
|
mov ax,4310h
|
|
int 2fh
|
|
mov e_o,bx
|
|
mov bx,es
|
|
mov e_s,bx
|
|
xmschecked:
|
|
}
|
|
|
|
if(!e_s && !e_o) {
|
|
FatalError(textNoXmsManager);
|
|
}
|
|
|
|
Entry = ((ULONG)e_s << 16) | e_o;
|
|
|
|
//
|
|
// Get size of largest block and make sure it's
|
|
// large enough to make use of XMS worthwhile.
|
|
// IoBuffer is 63*512 sectors, which is just under 32K.
|
|
// So we want at least 32K. Also trim the block size
|
|
// so the sector count will fit in a ushort.
|
|
//
|
|
_asm {
|
|
mov ah,8
|
|
call far ptr [Entry]
|
|
mov LargestBlock,ax
|
|
}
|
|
|
|
if(LargestBlock < 32) {
|
|
FatalError(textNoXmsManager);
|
|
}
|
|
if(LargestBlock > 32767) {
|
|
LargestBlock = 32767;
|
|
}
|
|
|
|
//
|
|
// Allocate the block.
|
|
//
|
|
_asm {
|
|
mov ah,9
|
|
mov dx,LargestBlock
|
|
call far ptr [Entry]
|
|
mov Handle,dx
|
|
mov b,ax
|
|
}
|
|
|
|
if(!b) {
|
|
FatalError(textNoXmsManager);
|
|
}
|
|
|
|
XmsEntry = Entry;
|
|
XmsHandle = Handle;
|
|
XmsMaxSectors = LargestBlock * 2 - 128; // actually it's * 1024/512
|
|
// make it 64K smaller just in case.
|
|
}
|
|
|
|
|
|
VOID
|
|
XmsTerminate(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Terminate XMS i/o by releasing any allocated block.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Entry;
|
|
int Handle;
|
|
|
|
if(XmsEntry && XmsMaxSectors) {
|
|
|
|
Entry = XmsEntry;
|
|
Handle = XmsHandle;
|
|
|
|
_asm {
|
|
mov ah,0ah
|
|
mov dx,Handle
|
|
call far ptr [Entry]
|
|
}
|
|
|
|
XmsEntry = 0;
|
|
XmsHandle = 0;
|
|
XmsMaxSectors = 0;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
XmsIoDiskRead(
|
|
IN HDISK DiskHandle,
|
|
IN ULONG StartSector,
|
|
IN ULONG SectorCount,
|
|
OUT ULONG *SectorsRead,
|
|
OUT BOOL *Xms
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read sectors from a disk.
|
|
|
|
If the sector count is less then 64 or XMS is not available,
|
|
then a maximum of 63 sectors will be read into the buffer
|
|
pointed to by the IoBuffer global variable.
|
|
|
|
If the sector count is greater than 63 and XMS is available,
|
|
then as many sectors as will fit into our XMS buffer are
|
|
read and buffered in XMS memory, using IoBuffer as the
|
|
intermediary transfer buffer.
|
|
|
|
Every read deltas the gas gauge by the number of sectors
|
|
transferred.
|
|
|
|
Arguments:
|
|
|
|
DiskHandle - supplies disk handle of disk to be read from.
|
|
|
|
StartSector - supplies first sector of read run.
|
|
|
|
SectorCount - supplies the number of sectors the caller
|
|
wants to read.
|
|
|
|
SectorsRead - receives the number of sectors read, which is
|
|
the minimum of the number of sectors the caller actually
|
|
wants, and either 63 (non-xms case) or XmsSectors (xms case).
|
|
|
|
Xms - recieves a value indicating whether the sectors were read
|
|
and buffered in Xms memory. The caller may need to know this
|
|
when he goes to write the data later.
|
|
|
|
Return Value:
|
|
|
|
None. Does not return if error.
|
|
|
|
--*/
|
|
|
|
{
|
|
BYTE c;
|
|
BOOL b;
|
|
BYTE code;
|
|
ULONG Entry;
|
|
unsigned x_s,x_o;
|
|
|
|
if((SectorCount <= 63) || !XmsMaxSectors) {
|
|
//
|
|
// Conventional memory only. I/O to IoBuffer.
|
|
//
|
|
*Xms = FALSE;
|
|
if(SectorCount > 63) {
|
|
SectorCount = 63;
|
|
}
|
|
|
|
if(!ReadDisk(DiskHandle,StartSector,(BYTE)SectorCount,IoBuffer)) {
|
|
FatalError(textReadFailedAtSector,(UINT)SectorCount,StartSector);
|
|
}
|
|
|
|
*SectorsRead = SectorCount;
|
|
GaugeDelta(SectorCount);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// XMS read.
|
|
//
|
|
*Xms = TRUE;
|
|
if(SectorCount > XmsMaxSectors) {
|
|
SectorCount = XmsMaxSectors;
|
|
}
|
|
*SectorsRead = SectorCount;
|
|
|
|
XmsParams.SourceHandle = 0;
|
|
XmsParams.SourceOffset = (ULONG)IoBuffer;
|
|
XmsParams.DestinationHandle = XmsHandle;
|
|
XmsParams.DestinationOffset = 0;
|
|
|
|
Entry = XmsEntry;
|
|
x_s = (unsigned)((ULONG)(void _far *)&XmsParams >> 16);
|
|
x_o = (unsigned)(ULONG)&XmsParams;
|
|
|
|
while(SectorCount) {
|
|
|
|
c = (BYTE)((SectorCount > 63L) ? 63L : SectorCount);
|
|
|
|
if(!ReadDisk(DiskHandle,StartSector,c,IoBuffer)) {
|
|
FatalError(textReadFailedAtSector,c,StartSector);
|
|
}
|
|
|
|
XmsParams.Count = c * 512L;
|
|
|
|
_asm {
|
|
push ds
|
|
push si
|
|
push x_s
|
|
pop ds
|
|
mov si,x_o
|
|
mov ah,0bh
|
|
call far ptr [Entry]
|
|
mov b,ax
|
|
mov code,bl
|
|
pop si
|
|
pop ds
|
|
}
|
|
|
|
if(!b) {
|
|
FatalError(textXmsMemoryError,code);
|
|
}
|
|
|
|
XmsParams.DestinationOffset += XmsParams.Count;
|
|
StartSector += c;
|
|
SectorCount -= c;
|
|
GaugeDelta(c);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
XmsIoDiskWrite(
|
|
IN HDISK DiskHandle,
|
|
IN ULONG StartSector,
|
|
IN ULONG SectorOffset,
|
|
IN ULONG SectorCount,
|
|
IN BOOL Xms
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write sectors to a disk.
|
|
|
|
Sectors are written either from IoBuffer or from XMS memory
|
|
(using IoBuffer as the intermediary transfer buffer) as the caller
|
|
specifies.
|
|
|
|
Every write deltas the gas gauge by the number of sectors
|
|
transferred.
|
|
|
|
Arguments:
|
|
|
|
DiskHandle - supplies disk handle of disk to write to.
|
|
|
|
StartSector - supplies first sector of write run.
|
|
|
|
SectorOffset - supplies the number of sectors to skip/ignore at
|
|
the start of the i/o buffer (either IoBuffer or XMS memory).
|
|
This allows the caller to write out a previously read run
|
|
in chunks.
|
|
|
|
SectorCount - supplies the number of sectors to write.
|
|
|
|
Xms - supplies a value indicating whether the data to be written
|
|
is in Xms memory. If not, it's in IoBuffer.
|
|
|
|
Return Value:
|
|
|
|
None. Does not return if error.
|
|
|
|
--*/
|
|
|
|
{
|
|
BYTE c;
|
|
BYTE i;
|
|
BOOL b;
|
|
BYTE code;
|
|
ULONG Entry;
|
|
unsigned x_s,x_o;
|
|
|
|
if(!Xms) {
|
|
//
|
|
// Conventional memory only. I/O from IoBuffer.
|
|
// SectorCount had better be <= 63!
|
|
//
|
|
if(!CmdLineArgs.Test) {
|
|
i=0;
|
|
while(i<3) {
|
|
//
|
|
// Retry a couple times. (My machine seems to randomly fail a write once in a while.)
|
|
//
|
|
if(WriteDisk(DiskHandle,
|
|
StartSector,
|
|
(BYTE)SectorCount,
|
|
(FPBYTE)IoBuffer+((unsigned)SectorOffset*512))
|
|
) {
|
|
if(i>0) {
|
|
_Log(" *** Write succeeded retried %d times.\n", i );
|
|
}
|
|
break;
|
|
}
|
|
_Log(" *** Write error at sector %ld length %d attempt %d\n", StartSector,SectorCount, i );
|
|
i++;
|
|
}
|
|
if(i==3) {
|
|
FatalError(textWriteFailedAtSector,(UINT)SectorCount,StartSector);
|
|
}
|
|
}
|
|
GaugeDelta(SectorCount);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// XMS write. SectorCount had better be <= XmsMaxSectors!
|
|
//
|
|
XmsParams.SourceHandle = XmsHandle;
|
|
XmsParams.SourceOffset = 512 * SectorOffset;
|
|
XmsParams.DestinationHandle = 0;
|
|
XmsParams.DestinationOffset = (ULONG)IoBuffer;
|
|
|
|
Entry = XmsEntry;
|
|
x_s = (unsigned)((ULONG)(void _far *)&XmsParams >> 16);
|
|
x_o = (unsigned)(ULONG)&XmsParams;
|
|
|
|
while(SectorCount) {
|
|
|
|
c = (BYTE)((SectorCount > 63L) ? 63L : SectorCount);
|
|
|
|
XmsParams.Count = c * 512L;
|
|
|
|
_asm {
|
|
push ds
|
|
push si
|
|
push x_s
|
|
pop ds
|
|
mov si,x_o
|
|
mov ah,0bh
|
|
call far ptr [Entry]
|
|
mov b,ax
|
|
mov code,bl
|
|
pop si
|
|
pop ds
|
|
}
|
|
|
|
if(!b) {
|
|
FatalError(textXmsMemoryError,code);
|
|
}
|
|
|
|
if(!CmdLineArgs.Test) {
|
|
i=0;
|
|
while(i<3) {
|
|
//
|
|
// Retry a couple times. (My machine seems to randomly fail a write once in a while.)
|
|
//
|
|
if(WriteDisk(DiskHandle,StartSector,c,IoBuffer)) {
|
|
if(i>0) {
|
|
_Log(" *** Write succeeded retried %d times.\n", i );
|
|
}
|
|
break;
|
|
}
|
|
_Log(" *** Write error at sector %ld length %d attempt %d\n", StartSector, c, i );
|
|
i++;
|
|
}
|
|
if(i==3) {
|
|
FatalError(textWriteFailedAtSector,c,StartSector);
|
|
}
|
|
}
|
|
|
|
XmsParams.SourceOffset += XmsParams.Count;
|
|
StartSector += c;
|
|
SectorCount -= c;
|
|
GaugeDelta(c);
|
|
}
|
|
}
|