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

📄 iopprocessor.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ProcessIorReadWrite processes an IOR_READ or an IOR_WRITE request
// asynchronously.

void 
IopProcessor::ProcessIorReadWrite(PIOP pIop, PGPBoolean useAsync)
{
	DualErr		derr;
	PDCB		pDcb;
	PGPBoolean	doneWithRequest;
	PGPdisk		*pPGD;
	PGPUInt8	drive, *buf;
	PGPUInt16	blockSize, failSilentStatus;
	PIOR		pIor;

	pgpAssertAddrValid(pIop, IOP);

	pIor = &pIop->IOP_ior;
	pgpAssertAddrValid(pIor, IOR);
	
	pDcb = (PDCB) pIop->IOP_physical_dcb;
	pgpAssertAddrValid(pDcb, DCB);

	drive = pDcb->DCB_cmn.DCB_drive_lttr_equiv;
	pgpAssert(IsLegalDriveNumber(drive));
	
	pPGD = Driver->mPGPdisks.FindPGPdisk(drive);
	pgpAssertAddrValid(pPGD, PGPdisk);

	blockSize = ExtractBlockSize(pDcb);

	pgpAssert(IsDriveBusy(drive));

	// Reset the inactivity timer.
	Driver->mSecondsInactive = 0;

	// Verify that IO is enabled for this PGPdisk.
	if (!pPGD->IsIOEnabled())
	{
		derr = kPGDMinorError_FailSilently;
		failSilentStatus = IORS_NOT_READY;
	}

	// If this is a write, verify that the volume isn't write-protected.
	if (derr.IsntError())
	{
		if (pIor->IOR_func == IOR_WRITE)
		{
			if (pPGD->IsReadOnly())
			{
				derr = kPGDMinorError_FailSilently;
				failSilentStatus = IORS_WRITE_PROTECT;
			}
		}
	}

	// Prepare the request for execution.
	if (derr.IsntError())
	{
		PGPUInt32	i, nBytes;
		PGPUInt64	pos;

		mIopReqs[drive].useAsync	= useAsync;
		mIopReqs[drive].pIop		= pIop;
		mIopReqs[drive].pIor		= pIor;

		mIopReqs[drive].downInfo.callback	= IorReadWriteCallback;
		mIopReqs[drive].downInfo.refData[0]	= (PGPUInt32) this;
		mIopReqs[drive].downInfo.refData[1]	= drive;

		// Mark all the mini-request stuctures as unused.
		for (i=0; i<kIopProcMaxMinis; i++)
		{
			mIopReqs[drive].miniReqs[i].isInUse = FALSE;
		}

		// Calculate the byte offset on the volume where the request begins.
		pos = pIor->IOR_start_addr[0] * blockSize;

		// Initialize the list of miniReqs that describe the I/O transfers that
		// make up this request.

		if (!IsScatterGather(pIor))		// Just one 'piece'
		{
			nBytes = pIor->IOR_xfer_count;

			// Translate to bytes
			if (!IsInBytes(pIor))
			{
				nBytes *= blockSize;
			}
			
			buf = (PGPUInt8 *) pIor->IOR_buffer_ptr;
			pgpAssertAddrValid(buf, PGPUInt8);

			// Just one minireq at position 0 for this request.
			mIopReqs[drive].miniReqs[0].isInUse	= TRUE;
			mIopReqs[drive].miniReqs[0].buf		= buf;
			mIopReqs[drive].miniReqs[0].pos		= pos;
			mIopReqs[drive].miniReqs[0].nBytes	= nBytes;
		}
		else							// More than one 'piece'
		{
			PGPUInt32	curMiniReq;
			PSGD		pSgd;

			// We are dealing with scatter/gather requests. The pointer to
			// the first S/G structure will be in IOR_buffer_ptr. Each SGD
			// describes a number of bytes to transfer and provides a buffer.

			pSgd = (PSGD) pIor->IOR_buffer_ptr;
			pgpAssertAddrValid(pSgd, SGD);

			curMiniReq = 0;

			// Initialize a separate mini-request structure for each SGD.
			while (derr.IsntError() && (nBytes = pSgd->bd.SG_buff_size))
			{
				if (curMiniReq >= kIopProcMaxMinis)
				{
					derr = DualErr(kPGDMinorError_MiniRequestOverflow);
				}

				if (derr.IsntError())
				{
					// Translate to bytes.
					if (!IsInBytes(pIor))
					{
						nBytes *= blockSize;
					}

					buf = (PGPUInt8 *) pSgd->bd.SG_buff_ptr;
					pgpAssertAddrValid(buf, PGPUInt8);

					mIopReqs[drive].miniReqs[curMiniReq].isInUse	= TRUE;
					mIopReqs[drive].miniReqs[curMiniReq].buf		= buf;
					mIopReqs[drive].miniReqs[curMiniReq].pos		= pos;
					mIopReqs[drive].miniReqs[curMiniReq].nBytes		= nBytes;

					curMiniReq++;

					pos += nBytes;		// where the next read will begin
					pSgd++;				// move on to the next S/G structure
				}
			}
		}
	}

	// Now begin executing the request.
	if (derr.IsntError())
	{
		// ExecuteRequest won't fail on async.
		if (useAsync)
			ExecuteRequest(drive, &doneWithRequest);
		else
			derr = ExecuteRequest(drive, &doneWithRequest);
	}

	// If we are sync, then the request has been completed. If not, then
	// doneWithRequest shouldn't be TRUE assuming we were passed valid params.

	if (derr.IsntError())
	{
		if (doneWithRequest)
		{
			pgpAssert(!useAsync);
			ScheduleAsyncCallback(pIop, IORS_SUCCESS);
		}
	}

	// Call back errors now.
	if (derr.IsError())
	{
		switch (derr.mMinorError)
		{
		case kPGDMinorError_IopRequestOverflow:
		case kPGDMinorError_MiniRequestOverflow:
			ScheduleAsyncCallback(pIop, IORS_BUSY);
			break;

		case kPGDMinorError_FailSilently:
			ScheduleAsyncCallback(pIop, failSilentStatus);
			break;

		default:
			if (IsntNull(pPGD))
			{
				pPGD->EnableIO(FALSE);
				ScheduleAsyncCallback(pIop, IORS_MEDIA_ERROR);

				// For I/O errors, user will be asked for options.
				if (pIor->IOR_func == IOR_READ)
				{
					Driver->ReportError(kPGDMajorError_PGPdiskReadError, 
						derr, pPGD->GetDrive());
				}
				else
				{
					Driver->ReportError(kPGDMajorError_PGPdiskWriteError, 
						derr, pPGD->GetDrive());
				}
			}
			else
			{
				ScheduleAsyncCallback(pIop, IORS_NO_DEVICE);
			}
			break;
		}
	}
}

// ExecuteRequest executes the next 'piece' of the request being processed on
// the given drive. If there nothing left to execute, 'doneWithRequest' is
// set to TRUE, otherwise FALSE.

DualErr 
IopProcessor::ExecuteRequest(PGPUInt8 drive, PGPBoolean *doneWithRequest)
{
	DualErr		derr;
	PGPBoolean	foundMiniReq	= FALSE;
	PGPBoolean	useAsync		= FALSE;
	PGPUInt32	i;
	PDCB		pDcb;
	PGPdisk		*pPGD;
	PIOP		pIop;
	PIOR		pIor;

	pgpAssertAddrValid(doneWithRequest, PGPBoolean);
	(* doneWithRequest) = FALSE;

	pgpAssert(IsLegalDriveNumber(drive));
	pgpAssert(IsDriveBusy(drive));

	pIop = mIopReqs[drive].pIop;
	pgpAssertAddrValid(pIop, IOP);

	pIor = mIopReqs[drive].pIor;
	pgpAssertAddrValid(pIor, IOR);

	pDcb = (PDCB) pIop->IOP_physical_dcb;
	pgpAssertAddrValid(pDcb, DCB);

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

	useAsync = mIopReqs[drive].useAsync;

	// Look for the next piece we need to process, if any are left.
	for (i=0; i<kIopProcMaxMinis; i++)
	{
		if (mIopReqs[drive].miniReqs[i].isInUse)
		{
			PGPUInt8	*buf;
			PGPUInt32	nBytes;
			PGPUInt64	pos;

			foundMiniReq = TRUE;

			buf		= mIopReqs[drive].miniReqs[i].buf;
			pos		= mIopReqs[drive].miniReqs[i].pos;
			nBytes	= mIopReqs[drive].miniReqs[i].nBytes;
			
			pgpAssertAddrValid(buf, PGPUInt8);

			// Call it down. Don't ask for an error value on async calls since
			// async errors will be returned using the callback, not here.

			switch (pIor->IOR_func)
			{
			case IOR_READ:
				if (useAsync)
					pPGD->Read(buf, pos, nBytes, &mIopReqs[drive].downInfo);
				else
					derr = pPGD->Read(buf, pos, nBytes);
				break;

			case IOR_WRITE:
				if (useAsync)
					pPGD->Write(buf, pos, nBytes, &mIopReqs[drive].downInfo);
				else
					derr = pPGD->Write(buf, pos, nBytes);
				break;
			}

			// If we're async we only process one piece at a time.
			if (useAsync || derr.IsError())
				break;
		}
	}

	if (useAsync)
		(* doneWithRequest) = !foundMiniReq;
	else
		(* doneWithRequest) = TRUE;

	return derr;
}

// IorReadWriteCallback is called as a callback by the routines who executed
// our read and write requests. We extract the address of the PGPdisk object
// in question and pass the callback to it.

void 
IopProcessor::IorReadWriteCallback(GenericCallbackInfo *downInfo)
{
	IopProcessor	*pIP;
	PGPUInt8		drive;

	pgpAssertAddrValid(downInfo, GenericCallbackInfo);

	pIP = (IopProcessor *) downInfo->refData[0];
	pgpAssertAddrValid(pIP, IopProcessor);

	drive = (PGPUInt8) downInfo->refData[1];
	pgpAssert(IsLegalDriveNumber(drive));

	pIP->IorReadWriteCallbackAux(drive);
}

// IorReadWriteCallbackAux is called by the static callback function
// 'IorReadWriteCallback' so we don't have to type 'pIP' before every
// reference to an object member or method.

void 
IopProcessor::IorReadWriteCallbackAux(PGPUInt8 drive)
{
	DualErr		derr;
	PGPBoolean	doneWithRequest;
	PGPUInt32	i;

	pgpAssert(IsLegalDriveNumber(drive));
	pgpAssert(IsDriveBusy(drive));

	derr = mIopReqs[drive].downInfo.derr;

	if (derr.IsntError())
	{
		// Mark the mini-request structure we just completed as unused.
		for (i=0; i<kIopProcMaxMinis; i++)
		{
			if (mIopReqs[drive].miniReqs[i].isInUse)
			{
				mIopReqs[drive].miniReqs[i].isInUse = FALSE;
				break;
			}
		}
	}

	// Perform further processing on this request, if needed.
	if (derr.IsntError())
	{
		derr = ExecuteRequest(drive, &doneWithRequest);
	}

	// Callback if we're done or on error.
	if (doneWithRequest || derr.IsError())
	{	
		PIOP	pIop;
		PIOR	pIor;

		pIop = mIopReqs[drive].pIop;
		pgpAssertAddrValid(pIop, IOP);

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

		if (derr.IsntError())
		{
			ScheduleAsyncCallback(pIop, IORS_SUCCESS);
		}
		else
		{
			PGPdisk *pPGD;

			switch (derr.mMinorError)
			{
			case kPGDMinorError_IopRequestOverflow:
			case kPGDMinorError_MiniRequestOverflow:
				ScheduleAsyncCallback(pIop, IORS_BUSY);
				break;

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

				// Disable I/O to the PGPdisk.
				pPGD->EnableIO(FALSE);
				ScheduleAsyncCallback(pIop, IORS_MEDIA_ERROR);

				// For I/O errors, user will be asked for options.
				if (pIor->IOR_func == IOR_READ)
				{
					Driver->ReportError(kPGDMajorError_PGPdiskReadError, 
						DualErr::NoError, pPGD->GetDrive());
				}
				else
				{
					Driver->ReportError(kPGDMajorError_PGPdiskWriteError, 
						DualErr::NoError, pPGD->GetDrive());
				}
				break;
			}
		}
	}
}

// ScheduleAsyncCallback schedules a windows event that calls our function
// that will call the asynchronous request up.

void 
IopProcessor::ScheduleAsyncCallback(PIOP pIop, PGPUInt16 status)
{
	PIOR							pIor;
	static RestrictedEvent_THUNK	callbackThunk;

	pgpAssertAddrValid(pIop, IOP);

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

	pIor->IOR_status = status;

	Call_Restricted_Event(0, NULL, PEF_ALWAYS_SCHED, (PVOID) pIop, 
		AsyncExecuteCallback, 0, &callbackThunk);
}

// AsyncExecuteCallback was scheduled by 'ScheduleAsyncCallback' for the
// purpose of calling back up the asynchronous request we received.

VOID 
__stdcall 
IopProcessor::AsyncExecuteCallback(
	VMHANDLE		hVM, 
	THREADHANDLE	hThread, 
	PVOID			Refdata, 
	PCLIENT_STRUCT	pRegs)
{
	IopProcessor	*pIP;
	PGPUInt8		drive;
	PIOP			pIop;
	PIOR			pIor;

	pIop = (PIOP) Refdata;
	pgpAssertAddrValid(pIop, IOP);

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

	pIP = (IopProcessor *) pIor->IOR_private_port;
	pgpAssertAddrValid(pIP, IopProcessor);

	// If the IOR was a read or write request, we must check if there is more
	// I/O from that PGPdisk to process. We do this by scheduling the IOP
	// dispatch function as a callback.

	PDCB pDcb;

	switch (pIor->IOR_func)
	{
	case IOR_READ:
	case IOR_WRITE:
		pDcb = (PDCB) pIop->IOP_physical_dcb;
		pgpAssertAddrValid(pDcb, DCB);

		drive = pDcb->DCB_cmn.DCB_drive_lttr_equiv;
		pgpAssert(IsLegalDriveNumber(drive));

		--pIop->IOP_callback_ptr;	
		pIop->IOP_callback_ptr->IOP_CB_address(pIop);

		pIP->ScheduleIorReadWriteDispatch(drive);
		break;

	default:
		--pIop->IOP_callback_ptr;	
		pIop->IOP_callback_ptr->IOP_CB_address(pIop);
		break;
	}
}

⌨️ 快捷键说明

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