📄 cpgpdiskimpdrv98.cpp
字号:
return error;
}
CComboError
CPGPdiskImpDrv98::PerformPremountTasks()
{
CComboError error;
// Save contents of boot block.
error = mFile.Read(mBootBlock, mFirstDataBlock*kPGPdiskBlockSize,
kPGPdiskBlockSize);
if (error.IsntError())
error = mCipherContext.DecryptCFB(0, 1, mBootBlock, mBootBlock);
// Massage FileSystem IO requests on 98 to prevent hangs.
if (error.IsntError())
{
mBufferToWatchFor = mBuffer;
error = CDriverSubsystemsDrv98::FilesystemWatcher().WatchForBuffer(
mBuffer);
}
return error;
}
PGPUInt16
CPGPdiskImpDrv98::ProcessIorGenIoctl(CIop& iop)
{
pgpAssert(IsMounted());
CComboError error;
PGPUInt32 ioctlStatus = 0;
PGPUInt32 iopStatus = 0;
UDebug::DebugOut("PGPdisk: Ioctl - function=%x minor %x\n",
iop.IoctlFunction(), iop.IoctlControlParam() & 0xff);
// We only process some 440D functions and the 4411 function.
switch (iop.IoctlFunction())
{
case 0x440D:
switch (UMath::GetLowByte(UMath::GetLowWord(
iop.IoctlControlParam())))
{
case 0x40: // Set Device Parameters
{
// We don't actually have to 'do' anything here. The system
// will set these parameters when it writes the boot block,
// which is where we get them from anyways.
ioctlStatus = ERROR_SUCCESS;
iopStatus = IORS_SUCCESS;
break;
}
case 0x41: // Write Track on Logical Drive
{
FileSys::RwBlock *pRWB = static_cast<FileSys::RwBlock *>(
iop.IoctlBuffer());
pgpAssertAddrValid(pRWB, RwBlock);
// Calculate the starting sector.
PGPUInt64 pos = pRWB->rwCylinder * FileSys::kSizeCyl;
pos += pRWB->rwHead * FileSys::kSizeHead;
pos += pRWB->rwFirstSector;
// Calculate the number of blocks to write.
PGPUInt32 nBlocks = pRWB->rwSectors;
// Calculate the buffer address.
void *buf = Map16BitAddrToLinear(
UMath::GetHighWord(pRWB->rwBuffer),
UMath::GetLowWord(pRWB->rwBuffer));
// Perform the write.
error = Write(buf, pos, nBlocks);
ioctlStatus = (error.IsntError() ? ERROR_SUCCESS :
ERROR_INVALID_FUNCTION);
iopStatus = IORS_SUCCESS;
break;
}
case 0x42: // Format Track on Logical Drive
{
// Don't actually do anything, since PGPdisks aren't physical
// drives that need any special treatment of sectors before
// being written to.
FileSys::FvBlock *pFVB = static_cast<FileSys::FvBlock *>(
iop.IoctlBuffer());
pgpAssertAddrValid(pFVB, FvBlock);
if (pFVB->fvSpecFunc == 1)
pFVB->fvSpecFunc = 0;
ioctlStatus = ERROR_SUCCESS;
iopStatus = IORS_SUCCESS;
break;
}
case 0x60: // Get Device Parameters
{
switch (UMath::GetHighByte(UMath::GetLowWord(
iop.IoctlControlParam())))
{
case 0x08:
{
FileSys::DevParamsFat16 *pDp16 = static_cast<
FileSys::DevParamsFat16 *>(iop.IoctlBuffer());
pgpAssertAddrValid(pDp16, DevParamsFat16);
error = GetDevParamsFat16(*pDp16);
}
break;
case 0x48:
{
FileSys::DevParamsFat32 *pDp32 = static_cast<
FileSys::DevParamsFat32 *>(iop.IoctlBuffer());
pgpAssertAddrValid(pDp32, DevParamsFat32);
error = GetDevParamsFat32(*pDp32);
}
}
ioctlStatus = (error.IsntError() ? ERROR_SUCCESS :
ERROR_INVALID_FUNCTION);
iopStatus = IORS_SUCCESS;
break;
}
case 0x61: // Read Track on Logical Drive
{
FileSys::RwBlock *pRWB = static_cast<FileSys::RwBlock *>(
iop.IoctlBuffer());
pgpAssertAddrValid(pRWB, RwBlock);
// Calculate the starting sector.
PGPUInt64 pos = pRWB->rwCylinder * FileSys::kSizeCyl;
pos += pRWB->rwHead * FileSys::kSizeHead;
pos += pRWB->rwFirstSector;
// Calculate the number of blocks to read.
PGPUInt32 nBlocks = pRWB->rwSectors;
// Calculate the buffer address.
void *buf = Map16BitAddrToLinear(
UMath::GetHighWord(pRWB->rwBuffer),
UMath::GetLowWord(pRWB->rwBuffer));
// Perform the read.
error = Read(buf, pos, nBlocks);
ioctlStatus = (error.IsntError() ? ERROR_SUCCESS :
ERROR_INVALID_FUNCTION);
iopStatus = IORS_SUCCESS;
break;
}
case 0x66: // Get Media ID
{
FileSys::MID *pMid = static_cast<FileSys::MID *>(
iop.IoctlBuffer());
error = GetMID(*pMid);
ioctlStatus = (error.IsntError() ? ERROR_SUCCESS :
ERROR_INVALID_FUNCTION);
iopStatus = IORS_SUCCESS;
break;
}
default:
ioctlStatus = ERROR_INVALID_FUNCTION;
iopStatus = IORS_INVALID_COMMAND;
break;
}
break;
case 0x4411: // Query if we handle specified 440D code
switch (UMath::GetLowByte(UMath::GetLowWord(
iop.IoctlControlParam())))
{
case 0x40:
case 0x41:
case 0x42:
case 0x60:
case 0x61:
case 0x66:
ioctlStatus = ERROR_SUCCESS;
iopStatus = IORS_SUCCESS;
break;
default:
ioctlStatus = ERROR_INVALID_FUNCTION;
iopStatus = IORS_SUCCESS;
break;
}
break;
default:
ioctlStatus = ERROR_INVALID_FUNCTION;
iopStatus = IORS_INVALID_COMMAND;
break;
}
iop.IoctlReturn() = ioctlStatus;
return static_cast<PGPUInt16>(iopStatus);
}
PGPUInt16
CPGPdiskImpDrv98::ProcessIorReadWrite(CIop& iop)
{
pgpAssert(IsMounted());
CComboError error;
PGPBoolean isAWrite = (iop.Func() == IOR_WRITE);
if (isAWrite && IsReadOnly())
return IORS_WRITE_PROTECT;
if (!error.HaveNonPGPError())
{
PGPUInt32 pos = static_cast<PGPUInt32>(iop.StartAddress());
// Requests can either be in pieces (scatter/gather) or not.
if (iop.IsScatterGather())
{
PBDSGD pBDSGD;
pBDSGD = static_cast<PBDSGD>(iop.Buffer());
pgpAssertAddrValid(pBDSGD, BDSGD);
while (TRUE)
{
PGPUInt32 nBlocks = pBDSGD->SG_buff_size;
if (nBlocks == 0)
break;
if (iop.IsInBytes())
{
pgpAssert(nBlocks % kPGPdiskBlockSize == 0);
nBlocks /= kPGPdiskBlockSize;
}
void *buf = reinterpret_cast<void *>(
pBDSGD->SG_buff_ptr);
pgpAssertAddrValid(buf, VoidAlign);
if (isAWrite)
error = Write(buf, pos, nBlocks);
else
error = Read(buf, pos, nBlocks);
pos += nBlocks;
pBDSGD++;
if (error.IsError())
break;
}
}
else
{
PGPUInt32 nBlocks = iop.TransferCount();
if (iop.IsInBytes())
{
pgpAssert(nBlocks % kPGPdiskBlockSize == 0);
nBlocks /= kPGPdiskBlockSize;
}
void *buf = iop.Buffer();
pgpAssertAddrValid(buf, VoidAlign);
if (isAWrite)
error = Write(buf, pos, nBlocks);
else
error = Read(buf, pos, nBlocks);
}
}
if (error.IsntError())
return IORS_SUCCESS;
else
return IORS_MEDIA_ERROR;
}
void
CPGPdiskImpDrv98::ProcessIopCallbackAux(CIop& iop)
{
pgpAssert(IsMounted());
CComboError error;
PGPUInt16 iorFunc = iop.Func();
PGPUInt32 iopAddress = reinterpret_cast<PGPUInt32>(
static_cast<PIOP>(iop));
UDebug::DebugOut("PGPdisk: Processing an %s address %X.",
UConstantNamesDrv98::NameIorFunction(iorFunc), iopAddress);
// Process the IOP according to function.
switch (iorFunc)
{
case IOR_READ:
case IOR_WRITE:
error.err = ProcessIorReadWrite(iop);
break;
default:
pgpAssert(FALSE);
error.err = IORS_INVALID_COMMAND;
break;
}
iop.Callback(static_cast<PGPUInt16>(error.err));
UDebug::DebugOut("PGPdisk: Done processing an %s address %X status %X.",
UConstantNamesDrv98::NameIorFunction(iorFunc), iopAddress, error.err);
}
void
CPGPdiskImpDrv98::ProcessIopCallback(void *refPtr)
{
CIop iop(static_cast<PIOP>(refPtr));
CPGPdiskImpDrv98 *pImp = reinterpret_cast<CPGPdiskImpDrv98 *>(
iop.PrivatePort());
pgpAssertAddrValid(pImp, CPGPdiskImpDrv98);
pImp->ProcessIopCallbackAux(iop);
}
CComboError
CPGPdiskImpDrv98::QueueIopToIoThread(CIop& iop)
{
CComboError error;
iop.PrivatePort() = reinterpret_cast<unsigned long>(this);
mIoThread->PerformAsyncCallback(ProcessIopCallback, iop.Get());
return error;
}
PGPUInt32
CPGPdiskImpDrv98::ProcessExternalIo(void *ioPacket, PGPBoolean& wasCompleted)
{
pgpAssert(IsMounted());
// This is going to be an IOP.
CComboError error;
CIop iop(static_cast<PIOP>(ioPacket));
PGPBoolean completeNow = TRUE;
PGPUInt16 iorFunc = iop.Func();
PGPUInt32 iopAddress = reinterpret_cast<PGPUInt32>(ioPacket);
UDebug::DebugOut("PGPdisk: Seeing an %s address %X.",
UConstantNamesDrv98::NameIorFunction(iorFunc), iopAddress);
switch (iorFunc)
{
case IOR_GEN_IOCTL:
// NEVER SCHEDULE IOCTL REQUESTS. ALWAYS PROCESS IN SAME CONTEXT IN
// WHICH THEY ARE RECEIVED.
error.err = ProcessIorGenIoctl(iop);
break;
case IOR_READ:
case IOR_WRITE:
// Queue the IOP to the thread.
error = QueueIopToIoThread(iop);
if (error.IsError())
error.err = IORS_MEMORY_ERROR;
else
completeNow = FALSE;
break;
default:
error.err = IORS_INVALID_COMMAND;
break;
}
// Complete if not scheduled.
if (completeNow)
{
iop.Callback(static_cast<PGPUInt16>(error.err));
wasCompleted = TRUE;
UDebug::DebugOut("PGPdisk: Completed an %s address %X status %X.",
UConstantNamesDrv98::NameIorFunction(iorFunc),
iopAddress, static_cast<PGPUInt32>(error.err));
}
else
{
UDebug::DebugOut("PGPdisk: Scheduled an %s IOP address %X.",
UConstantNamesDrv98::NameIorFunction(iorFunc), iopAddress);
}
return error.err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -