⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iopprocessor.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////////
// IopProcessor.cpp
//
// Implementation of class IopProcessor.
//////////////////////////////////////////////////////////////////////////////

// $Id: IopProcessor.cpp,v 1.7 1999/02/13 04:24:35 nryan Exp $

// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.

#include <vtoolscp.h>

#include "Required.h"

#include "CPGPdiskDrv.h"
#include "Globals.h"
#include "IopProcessor.h"
#include "PGPdisk.h"


/////////////////////////////////////////////
// Class IopProcessor public member functions
/////////////////////////////////////////////

// The IopProcessor constructor.

IopProcessor::IopProcessor()
{
	mUseAsyncIO = kDefaultUseAsyncIO;

	for (PGPUInt32 i=0; i<kMaxDrives; i++)
	{
		mIopReqs[i].isBusy = FALSE;
	}
}

// IsDriveBusy returns TRUE if the PGPdisk represented by the given drive
// number is busy processing I/O.

PGPBoolean 
IopProcessor::IsDriveBusy(PGPUInt8 drive)
{
	pgpAssert(IsLegalDriveNumber(drive));

	return mIopReqs[drive].isBusy;
}

// SetDriveBusy marks the given drive as busy or not busy.

void 
IopProcessor::SetDriveBusy(PGPUInt8 drive, PGPBoolean isBusy)
{
	pgpAssert(IsLegalDriveNumber(drive));

	mIopReqs[drive].isBusy = isBusy;
}

// IsIOAsync returns TRUE if I/O is currently being processed asynchronously,
// FALSE otherwise.

PGPBoolean 
IopProcessor::IsIOAsync()
{
	return mUseAsyncIO;
}

// SetIOAsync specifies that I/O be processed either async or sync.

void 
IopProcessor::SetIOAsync(PGPBoolean isIOAsync)
{
	mUseAsyncIO = isIOAsync;
}

// ProcessIop schedules later processing, at a safe time, of the given IOP
// request. Validate the IOP and fail silently if validation fails.

void 
IopProcessor::ProcessIop(PIOP pIop)
{
	PDCB		pDcb;
	PGPBoolean	failThisRequest	= FALSE;
	PGPUInt8	drive;
	PGPUInt16	failStatus;
	PIOR		pIor;

	pgpAssertAddrValid(pIop, IOP);

	pIor = &pIop->IOP_ior;
	pgpAssertAddrValid(pIor, IOR);

	DebugOut("PGPdisk: Saw an %s\n", 
		Driver->GetIORFunctionName(pIor->IOR_func));

	// Store a pointer to this object in the IOP itself.
	pIor->IOR_private_port = (PGPUInt32) this;

	switch (pIor->IOR_func)
	{
	case IOR_GEN_IOCTL:
		// NEVER SCHEDULE IOCTL REQUESTS. ALWAYS PROCESS IN SAME CONTEXT IN
		// WHICH THEY ARE RECEIVED.

		IorGenIoctlDispatcher(pIop);
		break;

	case IOR_READ:
	case IOR_WRITE:
		// Queue the request.
		pDcb = (PDCB) pIop->IOP_physical_dcb;
		pgpAssertAddrValid(pDcb, DCB);

		// Validate the drive letter.
		drive = pDcb->DCB_cmn.DCB_drive_lttr_equiv;

		if (!IsLegalDriveNumber(drive) || 
			IsNull(Driver->mPGPdisks.FindPGPdisk(drive)))
		{
			failThisRequest = TRUE;
			failStatus = IORS_NO_DEVICE;
		}

		if (!failThisRequest)
		{
			IlbEnqueueIop(pIop, pDcb);

			// We must determine whether or not to schedule dispatching.
			// If I/O is in process, we don't schedule another callback - 
			// this will be done later on when that I/O is finished.
			// Otherwise we schedule a callback right now.

			if (!IsDriveBusy(drive))
			{
				SetDriveBusy(drive, TRUE);
				ScheduleIorReadWriteDispatch(drive);
			}
		}
		break;

	default:
		failThisRequest = TRUE;
		failStatus = IORS_INVALID_COMMAND;
		break;
	}

	if (failThisRequest)
	{
		pIor->IOR_status = failStatus;
		--pIop->IOP_callback_ptr;	
		pIop->IOP_callback_ptr->IOP_CB_address(pIop);
	}
}


//////////////////////////////////////////////
// Class IopProcessor private member functions
//////////////////////////////////////////////

// ScheduleIorReadWriteDispatch asks the system to schedule our IOR_READ and
// IOR_WRITE dispatching function for execution at a safer time.

void 
IopProcessor::ScheduleIorReadWriteDispatch(PGPUInt8 drive)
{
	static RestrictedEvent_THUNK iopThunk;

	pgpAssert(IsLegalDriveNumber(drive));

	Call_Restricted_Event(0, NULL, PEF_ALWAYS_SCHED, (PVOID) drive, 
		IorReadWriteDispatcher, 0, &iopThunk);
}

// IorGenIoctlDispatcher is called in order to dispatch IOR_GEN_IOCTL
// requests.

void 
IopProcessor::IorGenIoctlDispatcher(PIOP pIop)
{
	PIOR pIor;

	pgpAssertAddrValid(pIop, IOP);

	pIor = &pIop->IOP_ior;
	pgpAssertAddrValid(pIor, IOR);

	DebugOut("PGPdisk: %s initiated\n", 
		Driver->GetIORFunctionName(pIor->IOR_func));

	// Switch on the IOR function.
	switch (pIor->IOR_func)
	{
	case IOR_GEN_IOCTL:			// an ioctl request
		Driver->mIopProcessor.ProcessIorGenIoctl(pIop);
		break;

	default:					// otherwise fail
		pgpAssert(FALSE);
		break;
	}
}

// IorReadWriteDispatcher is the event callback that is scheduled by the
// I/O request routine in order to dispatch IOR_READ and IOR_WRITE requests.

VOID 
__stdcall 
IopProcessor::IorReadWriteDispatcher(
	VMHANDLE		hVM, 
	THREADHANDLE	hThread, 
	PVOID			Refdata, 
	PCLIENT_STRUCT	pRegs)
{
	PDCB		pDcb;
	PGPBoolean	foundIop	= FALSE;
	PGPdisk		*pPGD;
	PGPUInt8	drive;
	PIOP		pIop;

	drive = (PGPUInt8) Refdata;
	pgpAssert(IsLegalDriveNumber(drive));

	pPGD = Driver->mPGPdisks.FindPGPdisk(drive);
	pgpAssertAddrValid(pPGD, PGPdisk);

	pDcb = pPGD->GetDcb();
	pgpAssertAddrValid(pDcb, DCB);

	// Any outstanding I/O for this PGPdisk?
	if (pIop = IlbDequeueIop(pDcb))
	{
		PIOR pIor;

		pgpAssertAddrValid(pIop, IOP);

		pIor = &pIop->IOP_ior;
		pgpAssertAddrValid(pIor, IOR);

		DebugOut("PGPdisk: %s initiated\n", 
			Driver->GetIORFunctionName(pIor->IOR_func));

		// Switch on the IOR function.
		switch (pIor->IOR_func)
		{
		case IOR_READ:									// a read request
		case IOR_WRITE:									// a write request
			Driver->mIopProcessor.ProcessIorReadWrite(pIop, 
				Driver->mIopProcessor.mUseAsyncIO);
			break;

		default:										// otherwise fail
			pgpAssert(FALSE);
			break;
		}
	}
	else
	{
		// Allow I/O to the PGPdisk.
		Driver->mIopProcessor.SetDriveBusy(drive, FALSE);
	}
}

// ProcessIorGenIoctl processes an IOR_GEN_IOCTL request synchronously. We
// need to process these so formatting will work on PGPdisks.

void 
IopProcessor::ProcessIorGenIoctl(PIOP pIop)
{
	DualErr		derr;
	PGPUInt8	drive;
	PGPUInt16	iorsResult;
	PGPUInt32	ioctlResult;
	PIOR		pIor;
	PGPdisk		*pPGD;

	pgpAssertAddrValid(pIop, IOP);

	pIor = &pIop->IOP_ior;
	pgpAssertAddrValid(pIor, IOR);
	
	drive = pIor->IOR_ioctl_drive - 1;

	// Check for invalid drive.
	if ((drive == 0) || !IsLegalDriveNumber(drive) || 
		IsNull(Driver->mPGPdisks.FindPGPdisk(drive)))
	{
		ioctlResult = ERROR_INVALID_DRIVE;
		iorsResult = IORS_INVALID_COMMAND;
	}
	else
	{
		pPGD = Driver->mPGPdisks.FindPGPdisk(drive);
		pgpAssertAddrValid(pPGD, PGPdisk);

		DebugOut("PGPdisk: Ioctl - drive=%c function=%x minor %x\n", 
			DriveNumToLet(drive), pIor->IOR_ioctl_function, 
			pIor->IOR_ioctl_control_param & 0xff);

		// Now process the IOCTL request. We only process some 440D functions
		// and the 4411 function.

		switch (pIor->IOR_ioctl_function)
		{

		case 0x440D:
			switch (GetLowByte((PGPUInt16) pIor->IOR_ioctl_control_param))
			{

			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.

				ioctlResult = ERROR_SUCCESS;
				iorsResult = IORS_SUCCESS;
				break;
			}

			case 0x41:			// Write Track on Logical Drive
			{
				PGPUInt8	*buf;
				PGPUInt16	offset, segment;
				PGPUInt32	nBlocks;
				PGPUInt64	pos;
				RwBlock		*pRWB;
		
				pRWB = (RwBlock *) pIor->IOR_ioctl_buffer_ptr;

				// Calculate the starting sector.
				pos	= pRWB->rwCylinder * kSizeCyl;
				pos	+= pRWB->rwHead * kSizeHead;
				pos	+= pRWB->rwFirstSector;

				// Calculate the number of blocks to read.
				nBlocks	= pRWB->rwSectors;

				// Calculate the buffer address.
				segment = GetHighWord(pRWB->rwBuffer);
				offset = GetLowWord(pRWB->rwBuffer);

				buf = (PGPUInt8 *) Get_Cur_VM_Handle()->CB_High_Linear +
					(segment << 4) + offset;

				// Perform the write.
				derr = pPGD->Read(buf, pos*kDefaultBlockSize, 
					nBlocks*kDefaultBlockSize);

				ioctlResult = (derr.IsntError() ? ERROR_SUCCESS :
					ERROR_INVALID_FUNCTION);
				iorsResult = IORS_SUCCESS;
				break;
			}

			case 0x42:			// Format Track on Logical Drive
			{
				FvBlock *pFVB;
			
				// Don't actually do anything, since PGPdisks aren't physical
				// drives that need any special treatment of sectors before
				// being written to.

				pFVB = (FvBlock *) pIor->IOR_ioctl_buffer_ptr;

				if (pFVB->fvSpecFunc == 1)
				{
					pFVB->fvSpecFunc = 0;
				}

				ioctlResult = ERROR_SUCCESS;
				iorsResult = IORS_SUCCESS;
				break;
			}

			case 0x60:			// Get Device Parameters
			{
				switch (
					GetHighByte((PGPUInt16) pIor->IOR_ioctl_control_param))
				{
				case 0x08:
					derr = pPGD->GetDevParams16(
						(DevParams16 *) pIor->IOR_ioctl_buffer_ptr);
					break;

				case 0x48:
					derr = pPGD->GetDevParams32(
						(DevParams32 *) pIor->IOR_ioctl_buffer_ptr);
					break;
				}

				ioctlResult = (derr.IsntError() ? ERROR_SUCCESS :
					ERROR_INVALID_FUNCTION);
				iorsResult = IORS_SUCCESS;
				break;
			}

			case 0x61:			// Read Track on Logical Drive
			{
				PGPUInt8	*buf;
				PGPUInt16	offset, segment;
				PGPUInt32	nBlocks;
				PGPUInt64	pos;
				RwBlock		*pRWB;
		
				pRWB = (RwBlock *) pIor->IOR_ioctl_buffer_ptr;

				// Calculate the starting sector.
				pos	= pRWB->rwCylinder * kSizeCyl;
				pos	+= pRWB->rwHead * kSizeHead;
				pos	+= pRWB->rwFirstSector;

				// Calculate the number of blocks to read.
				nBlocks	= pRWB->rwSectors;

				// Calculate the buffer address.
				segment = GetHighWord(pRWB->rwBuffer);
				offset = GetLowWord(pRWB->rwBuffer);

				buf = (PGPUInt8 *) Get_Cur_VM_Handle()->CB_High_Linear +
					(segment << 4) + offset;

				// Perform the read.
				derr = pPGD->Read(buf, pos*kDefaultBlockSize, 
					nBlocks*kDefaultBlockSize);

				ioctlResult = (derr.IsntError() ? ERROR_SUCCESS :
					ERROR_INVALID_FUNCTION);
				iorsResult = IORS_SUCCESS;
				break;
			}

			case 0x66:			// Get Media ID
			{	
				derr = pPGD->GetMediaId((MID *) pIor->IOR_ioctl_buffer_ptr);

				ioctlResult = (derr.IsntError() ? ERROR_SUCCESS :
					ERROR_INVALID_FUNCTION);
				iorsResult = IORS_SUCCESS;
				break;
			}

			default:
				ioctlResult = ERROR_INVALID_FUNCTION;
				iorsResult = IORS_INVALID_COMMAND;
				break;
			}
			break;

		case 0x4411:		// Query if we handle specified 440D code
			switch (GetLowByte((PGPUInt16) pIor->IOR_ioctl_control_param))
			{
			case 0x40:
			case 0x41:
			case 0x42:
			case 0x60:
			case 0x61:
			case 0x66:
				ioctlResult = ERROR_SUCCESS;
				iorsResult = IORS_SUCCESS;
				break;

			default:
				ioctlResult = ERROR_INVALID_FUNCTION;
				iorsResult = IORS_SUCCESS;
				break;
			}
			break;

		default:
			ioctlResult = ERROR_INVALID_FUNCTION;
			iorsResult = IORS_INVALID_COMMAND;
			break;
		}
	}

	pIor->IOR_ioctl_return = ioctlResult;
	ScheduleAsyncCallback(pIop, iorsResult);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -