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

📄 ramios.c

📁 ramdisk,著名的内存虚拟磁盘的源代码
💻 C
字号:
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060  USA
//
// Copyright (c) 1998 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================

// RFSDIOS.C - I/O Subsystem interface for Registry File System
// Copyright (c) 1996, Compuware Corporation

// This module contains functions that are called by the IOS.
#include  "ramdisk.h"
#include PAGEABLE_CODE_SEGMENT
#include PAGEABLE_DATA_SEGMENT

//BYTE Drive;

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// DoCallDown passes a request to the next lower layer. Note that the
// documentation about how to do this is totally wrong: you don't just
// add sizeof(DCB_cd_entry) to the calldown pointer, you follow a
// linked list from one calldown entry to the next.

void __declspec(naked) DoCallDown(IOP* iop)
	{							// DoCallDown
	_asm
		{						// call down to next layer
		mov	ecx, [esp+4]
		mov	eax, [ecx]IOP.IOP_calldown_ptr
		mov eax, [eax]DCB_cd_entry.DCB_cd_next
		mov [ecx]IOP.IOP_calldown_ptr, eax
		jmp [eax]DCB_cd_entry.DCB_cd_io_address
		}						// call down to next layer
	}							// DoCallDown

// DoCallBack handles completion of an I/O request by calling the
// previous level's callback routine.

void __declspec(naked) DoCallBack(IOP* iop)
	{							// DoCallBack
	_asm
		{						// call back to previous layer
		mov ecx, [esp+4]
		sub [ecx]IOP.IOP_callback_ptr, size IOP_callback_entry
		mov eax, [ecx]IOP.IOP_callback_ptr
		jmp [eax]IOP_callback_entry.IOP_CB_address
		}						// call back to previous layer
	}							// DoCallBack

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Function
//	RAMDISK_Aer
//
// Purpose
//	Async Event Routine for RFSD	
//
// Parameters
//	pAep	pointer to the AEP structure
//
// Return Value
//	Depends on AEP subfunction.
//
// Remarks
//	The function name is required by usage of the macro 
//	Define_Port_Driver (see regfsd.c).
//
//	We handle the following AEPs:
//
//	  AEP_INITIALIZE:	create a DDB for our virtual drive
//	  AEP_INQUIRY:		set up a fake DCB
//	  AEP_CONFIG_DCB:	associate drive letter and insert into
//				calldown list
//	  AEP_BOOT_COMPLETE:	signal OK
//
VOID OnRequest(IOP* iop);
int ndevices = 0;				// # devices we've found

VOID __cdecl RAMDISK_Aer(AEP* pAep)
{
	DCB* pDcb;
	IOSDDB* pNewDDB;	
	ISP_ddb_create CreateDDBPacket;
	ISP_calldown_insert InsertISP;
	
	switch (pAep->AEP_func)
	{
	case AEP_INITIALIZE:
		// Create a DDB for our "controller". This will cause IOS to send
		// AEP_INQUIRY packets for each unit on the controller.
		CreateDDBPacket.ISP_ddb_hdr.ISP_func = ISP_CREATE_DDB;
		CreateDDBPacket.ISP_ddb_hdr.ISP_result = 0;		
		CreateDDBPacket.ISP_ddb_size = sizeof(IOSDDB);
		CreateDDBPacket.ISP_ddb_ptr = 0;
		CreateDDBPacket.ISP_ddb_flags = 0;
		
		RAMDISK_Ilb.ILB_service_rtn((PISP)&CreateDDBPacket);
		pNewDDB = (IOSDDB*)CreateDDBPacket.ISP_ddb_ptr;

		pAep->AEP_result = AEP_SUCCESS;
		break;

   	case AEP_UNINITIALIZE:
        	pAep->AEP_result = AEP_SUCCESS;
        	break;

	case AEP_DEVICE_INQUIRY:
		// The IOS sends this in response to the creation of the DDB. On the
		// first call (DCB_unit_on_ctl == 0) we set up the supplied fake DCB
		// with the parametes for our virtual drive. On subsequent calls, we
		// anwer "no more devices". This terminates the inquiry.

		pDcb = (DCB*)(((AEP_inquiry_device*)pAep)->AEP_i_d_dcb);
		ASSERT(pDcb);

		if (pDcb->DCB_unit_on_ctl == 0)
		{
			strcpy(pDcb->DCB_vendor_id, "ZXYZLL");
			strcpy(pDcb->DCB_product_id, "VRAMDISK");
			strcpy(pDcb->DCB_port_name, "VRAMDISK");			
			pAep->AEP_result = AEP_SUCCESS;
		}
		else
			pAep->AEP_result = AEP_NO_MORE_DEVICES;	
		break;

	case AEP_CONFIG_DCB:

		// The IOS sends this AEP after each successful inquiry call. We
		// associate the DCB with a drive letter and insert the request
		// handler into the calldown chain.
		pDcb = (DCB*)(((AEP_dcb_config*)pAep)->AEP_d_c_dcb);
		ASSERT(pDcb);
		if (!(pDcb->DCB_cmn.DCB_device_flags & DCB_DEV_PHYSICAL))
		{
			pAep->AEP_result = AEP_SUCCESS;
			break;
		}
		ASSERT(memcmp(pDcb->DCB_vendor_id, "ZXYZLL", 6) == 0);

		SetupDCB(pDcb);		
		
		//Drive = AssociateDriveLetter((DCB_COMMON*)pDcb);
			
		memset(&InsertISP, 0, sizeof(InsertISP));
		InsertISP.ISP_i_cd_hdr.ISP_func = ISP_INSERT_CALLDOWN;	
		InsertISP.ISP_i_cd_hdr.ISP_result = 0;			
		InsertISP.ISP_i_cd_dcb = (DCB_COMMON *)pDcb;					
                InsertISP.ISP_i_cd_req = OnRequest;	
		InsertISP.ISP_i_cd_ddb = (PDDB) (((AEP_dcb_config*)pAep)->AEP_d_c_hdr.AEP_ddb);               		
		InsertISP.ISP_i_cd_expan_len = 0;				
		InsertISP.ISP_i_cd_flags = pDcb->DCB_cmn.DCB_dmd_flags | DCB_dmd_serialize; 
                InsertISP.ISP_i_cd_lgn = ((AEP_dcb_config*)pAep)->AEP_d_c_hdr.AEP_lgn;
		RAMDISK_Ilb.ILB_service_rtn((PISP)&InsertISP);
		
		++ndevices;					// this will cause us to stay loader after next AEP_BOOT_COMPLETE

		pAep->AEP_result = AEP_SUCCESS;
		break;

	case AEP_UNCONFIG_DCB:
		pDcb = (DCB*)(((PAEP_dcb_unconfig)pAep)->AEP_d_u_dcb);
		ASSERT(pDcb);
		if (!(pDcb->DCB_cmn.DCB_device_flags & DCB_DEV_PHYSICAL)
			|| memcmp(pDcb->DCB_vendor_id, "ZXYZLL", 6) != 0)
		{
			pAep->AEP_result = AEP_SUCCESS;
			break;
		}
		--ndevices;					// this will cause to unload after next AEP_BOOT_COMPLETE
		ASSERT(ndevices >= 0);
		pAep->AEP_result = AEP_SUCCESS;
        	break;

	case AEP_BOOT_COMPLETE:
		pAep->AEP_result = ndevices ? AEP_SUCCESS : AEP_FAILURE; // unload if no devices
	
		break;

	default:
		pAep->AEP_result = AEP_FAILURE;
		break;
	}		
}


VOID OnRequest(IOP* iop)
{							// OnRequest	
	#define ior iop->IOP_ior
	DWORD funcode = ior.IOR_func;
	PDCB dcb = (PDCB) iop->IOP_physical_dcb;

	ior.IOR_status = IORS_SUCCESS; // assume it'll succeed
	dcb->DCB_cmn.DCB_device_flags |= DCB_DEV_IO_ACTIVE;

	switch (funcode)
	{					// dispatch function processor

	///////////////////////////////////////////////////////////////////////
	
	case IOR_READ:			// IOR_func == 0
		{					// IOR_READ
		DWORD sector = ior.IOR_start_addr[0];
		PBYTE diskdata = (PBYTE) (base + sector * dcb->DCB_actual_blk_size);

		ASSERT(sector < dcb->DCB_actual_sector_cnt[0]);
		ASSERT(ior.IOR_start_addr[1] == 0);

		if (ior.IOR_flags & IORF_SCATTER_GATHER)
			{				// have scatter/gather structures
			_BlockDev_Scatter_Gather* sgd = (_BlockDev_Scatter_Gather*) ior.IOR_buffer_ptr;
			PBYTE memdata;
			DWORD nbytes;
			while ((nbytes = sgd->BD_SG_Count))
				{			// for each s/g structure
				memdata = (PBYTE) sgd->BD_SG_Buffer_Ptr; // linear address!
				if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
					nbytes *= dcb->DCB_actual_blk_size;
				memcpy(memdata, diskdata, nbytes);
				diskdata += nbytes;
				++sgd;
				}			// for each s/g structure
			}				// have scatter/gather structures
		else
			{				// have simple buffer address
			PBYTE memdata = (PBYTE) ior.IOR_buffer_ptr;
			DWORD nbytes = ior.IOR_xfer_count;
			if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
				nbytes *= dcb->DCB_actual_blk_size;
			memcpy(memdata, diskdata, nbytes);
			}				// have simple buffer address
		
		break;
		}					// IOR_READ

	///////////////////////////////////////////////////////////////////////
	
	case IOR_WRITE:			// IOR_func == 1
		{					// IOR_WRITE
		DWORD sector = ior.IOR_start_addr[0];
		PBYTE diskdata = (PBYTE) (base + sector * dcb->DCB_actual_blk_size);

		ASSERT(sector);		// why is anyone rewriting the boot sector??
		ASSERT(sector < dcb->DCB_actual_sector_cnt[0]);
		ASSERT(ior.IOR_start_addr[1] == 0);

		if (ior.IOR_flags & IORF_SCATTER_GATHER)
			{				// have scatter/gather structures
			_BlockDev_Scatter_Gather* sgd = (_BlockDev_Scatter_Gather*) ior.IOR_buffer_ptr;
			PBYTE memdata;
			DWORD nbytes;
			while ((nbytes = sgd->BD_SG_Count))
				{			// for each s/g structure
				memdata = (PBYTE) sgd->BD_SG_Buffer_Ptr; // linear address!
				if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
					nbytes *= dcb->DCB_actual_blk_size;
				memcpy(diskdata, memdata, nbytes);
				diskdata += nbytes;
				++sgd;
				}			// for each s/g structure
			}				// have scatter/gather structures
		else
			{				// have simple buffer address
			PBYTE memdata = (PBYTE) ior.IOR_buffer_ptr;
			DWORD nbytes = ior.IOR_xfer_count;
			if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
				nbytes *= dcb->DCB_actual_blk_size;
			memcpy(diskdata, memdata, nbytes);
			}				// have simple buffer address
		
		break;
		}					// IOR_WRITE

	///////////////////////////////////////////////////////////////////////

	default:
		dcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_IO_ACTIVE;
		DoCallDown(iop);
		return;
	}					// dispatch function processor

	dcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_IO_ACTIVE;
	DoCallBack(iop);		// we're done with this request

	#undef ior
}							// OnRequest

⌨️ 快捷键说明

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