前段时间,只需用一台新电脑,由于资金有限没有匹配了心仪已久的SSD。我没感觉到飞翔的感觉,总不甘心,仔细想想。我死了相当大的存储,我们可以假设部分内存作为硬盘驱动器把它弄出来。不会比固态硬盘的速度快,我们開始吧。

首先。我们要做的就是写一个硬盘控制器的驱动,我们知道。存储类型的驱动一般都遵守 class/port/miniport driver 这种结构。微软已经完毕了磁盘类的驱动,以及 SCSI 总线的 Port 驱动,我们仅仅须要完毕 SCSI 总线上硬盘控制器的 Miniport 驱动就能够了。

拿出 DDK 的源代码分析一遍,微软果然不负众望地提供了一个驱动的源代码,我用的是DDK 7600.16385.1,里面有一个 ramdisk 的源代码,但读起来就发现。它是用 wdf
框架来实现的。我对 wdf 框架不熟悉。决定自己用 wdm 框架来又一次实现一遍。

接着便是各种资料的查询。最后最终摸清了SCSI miniport 驱动的大体框架。为了给一个极致简单的框架。我省去了很多冗余的代码,代码例如以下:

#define DBG 1

#include <ntddk.h>
#include <srb.h>
#include <scsi.h> #define MODULE_NAME_PREFIX "RamDisk: "
#define KdPrintThisFunction() KdPrint((MODULE_NAME_PREFIX"%s\n", __FUNCTION__)) #define RAMDISK_SECTOR_SIZE 512
#define RAMDISK_CAPACITY 16 * 1024 *1024 //typedef struct _DEVICE_EXTENSION { //} DEVICE_EXTENSION, *PDEVICE_EXTENSION; // Miniport 的一些回调函数
BOOLEAN Initialize(__in PVOID DeviceExtension);
BOOLEAN ResetBus(__in PVOID DeviceExtension, __in ULONG PathId);
BOOLEAN StartIo(__in PVOID DeviceExtension, __in PSCSI_REQUEST_BLOCK Srb);
BOOLEAN Interrupt(__in PVOID DeviceExtension);
ULONG FindAdapter(
__in PVOID DeviceExtension,
__in PVOID HwContext,
__in PVOID BusInformation,
__in PCHAR ArgumentString,
__inout PPORT_CONFIGURATION_INFORMATION ConfigInfo,
__out PBOOLEAN Again
);
BOOLEAN AdapterState(__in PVOID DeviceExtension, __in PVOID Context, __in BOOLEAN SaveState);
SCSI_ADAPTER_CONTROL_STATUS AdapterControl(PVOID DeviceExtension,SCSI_ADAPTER_CONTROL_TYPE ctlType,PVOID pParameters); VOID DriverUnload(__in struct _DRIVER_OBJECT *DriverObject); PVOID RamDiskMemroy; NTSTATUS
DriverEntry(
__in struct _DRIVER_OBJECT *DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
HW_INITIALIZATION_DATA HwInitData; KdPrintThisFunction(); RtlZeroMemory(&HwInitData, sizeof(HW_INITIALIZATION_DATA));
HwInitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); HwInitData.HwInitialize = Initialize;
HwInitData.HwResetBus = ResetBus;
HwInitData.HwStartIo = StartIo;
HwInitData.HwInterrupt = NULL; // 不须要中断服务
HwInitData.HwFindAdapter = FindAdapter;
HwInitData.HwAdapterState = AdapterState;
HwInitData.HwAdapterControl = AdapterControl; HwInitData.AdapterInterfaceType = Isa;
HwInitData.DeviceExtensionSize = 0;
HwInitData.SrbExtensionSize = 0;
HwInitData.NumberOfAccessRanges = 0; HwInitData.MapBuffers = TRUE;
HwInitData.NeedPhysicalAddresses = FALSE;
HwInitData.TaggedQueuing = FALSE;
HwInitData.AutoRequestSense = TRUE;
HwInitData.MultipleRequestPerLu = FALSE;
HwInitData.ReceiveEvent = FALSE; // 初始化
ScsiPortInitialize(DriverObject, RegistryPath, &HwInitData, NULL); DriverObject->DriverUnload = DriverUnload; RamDiskMemroy = ExAllocatePool(NonPagedPool, RAMDISK_CAPACITY);
if (RamDiskMemroy == NULL) {
KdPrint(("RamDisk: Allocate memory failed!\n"));
return STATUS_FAILED_DRIVER_ENTRY;
} KdPrint(("MyRamDisk: RamDiskMemroy - 0x%p\n", RamDiskMemroy)); return STATUS_SUCCESS;
} VOID
DriverUnload(
__in struct _DRIVER_OBJECT *DriverObject
)
{
KdPrintThisFunction();
ExFreePool(RamDiskMemroy);
} BOOLEAN
Initialize(
__in PVOID DeviceExtension
)
{
KdPrintThisFunction();
return TRUE;
} BOOLEAN
ResetBus(
__in PVOID DeviceExtension,
__in ULONG PathId
)
{
KdPrintThisFunction();
return TRUE;
} BOOLEAN
ReadCapacityData(
PSCSI_REQUEST_BLOCK Srb
)
{
PREAD_CAPACITY_DATA CapacityData = (PREAD_CAPACITY_DATA)Srb->DataBuffer;
ULONG Value = 0; KdPrintThisFunction(); // this two value should in Big Endian
Value = RAMDISK_CAPACITY / RAMDISK_SECTOR_SIZE - 1;
REVERSE_LONG(&Value);
CapacityData->LogicalBlockAddress = Value;
Value = RAMDISK_SECTOR_SIZE;
REVERSE_LONG(&Value);
CapacityData->BytesPerBlock = Value; return TRUE;
} BOOLEAN
Inquiry(
PSCSI_REQUEST_BLOCK Srb
)
{
PINQUIRYDATA InquiryData = (PINQUIRYDATA)Srb->DataBuffer;
PCDB Cdb = &Srb->Cdb; KdPrintThisFunction(); InquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
InquiryData->DeviceTypeQualifier = DEVICE_CONNECTED;
InquiryData->DeviceTypeModifier = 0;
InquiryData->RemovableMedia = 0;
InquiryData->ResponseDataFormat = 2;
InquiryData->Versions = 0;
InquiryData->AdditionalLength = sizeof(INQUIRYDATA) - 5; // 这些数据关系到系统中设备管理器的显示
RtlMoveMemory(InquiryData->VendorId,"HENZOX",6);
RtlMoveMemory(InquiryData->ProductId,"RamDisk - Henzox",16);
RtlMoveMemory(InquiryData->ProductRevisionLevel,"1010",4); KdPrint(("Inquiry: succeeded(target-lun)=(%d,%d)\n", Srb->TargetId, Srb->Lun)); return TRUE;
} BOOLEAN
ReadDisk(
PSCSI_REQUEST_BLOCK Srb
)
{
ULONG Start = 0; // 開始扇区
USHORT Count = 0; // 读取大小,以扇区为单位 PCDB Cdb = &Srb->Cdb[0];
Start = *(PULONG)&Cdb->CDB10.LogicalBlockByte0;
REVERSE_LONG(&Start);
Count = *(PUSHORT)&Cdb->CDB10.TransferBlocksMsb;
REVERSE_SHORT(&Count); if ((Start + Count) * RAMDISK_SECTOR_SIZE > RAMDISK_CAPACITY) {
KdPrint(("ReadDisk: overflow!\n"));
return FALSE;
}
// Count * RAMDISK_SECTOR_SIZE equals to Srb->DataTransferLength
KdPrint(("ReadDisk: Start - %d, Size - %d\n", Start * RAMDISK_SECTOR_SIZE, Srb->DataTransferLength));
RtlMoveMemory(Srb->DataBuffer, (PUCHAR)RamDiskMemroy + Start * RAMDISK_SECTOR_SIZE, Srb->DataTransferLength);
return TRUE;
} BOOLEAN
WriteDisk(
PSCSI_REQUEST_BLOCK Srb
)
{
ULONG Start = 0; // 開始地址
USHORT Count = 0; // 读取大小,以扇区为单位 PCDB Cdb = &Srb->Cdb[0];
Start = *(PULONG)&Cdb->CDB10.LogicalBlockByte0;
REVERSE_LONG(&Start);
Count = *(PUSHORT)&Cdb->CDB10.TransferBlocksMsb;
REVERSE_SHORT(&Count); if (Start + Count * RAMDISK_SECTOR_SIZE > RAMDISK_CAPACITY) {
KdPrint(("WriteDisk: overflow!\n"));
return FALSE;
} KdPrint(("WriteDisk: Start - %d, Size - %d\n", Start * RAMDISK_SECTOR_SIZE, Srb->DataTransferLength));
RtlMoveMemory((PUCHAR)RamDiskMemroy + Start * RAMDISK_SECTOR_SIZE, Srb->DataBuffer, Srb->DataTransferLength);
return TRUE; } BOOLEAN
ExecuteScsi(
PSCSI_REQUEST_BLOCK Srb
)
{
BOOLEAN ReturnValue = FALSE;
PCDB Cdb = (PCDB)&Srb->Cdb[0]; KdPrintThisFunction(); switch (Cdb->CDB10.OperationCode) {
case 0x28:
// Read disk
ReturnValue = ReadDisk(Srb);
break;
case 0x2A:
// Write disk
ReturnValue = WriteDisk(Srb);
break;
case 0x25:
// Read the capacity of the disk
ReturnValue = ReadCapacityData(Srb);
break;
case 0x12:
// Disk inquiry
ReturnValue = Inquiry(Srb);
break;
default:
KdPrint(("ExecuteScsi: Unknown operation code(0x%p)\n", Cdb->CDB10.OperationCode));
ReturnValue = TRUE;
} return ReturnValue;
} BOOLEAN
DoIoControl(
PSCSI_REQUEST_BLOCK Srb
)
{
KdPrintThisFunction(); return TRUE;
} BOOLEAN
StartIo(
__in PVOID DeviceExtension,
__in PSCSI_REQUEST_BLOCK Srb
)
{
BOOLEAN ReturnValue = TRUE; KdPrintThisFunction(); Srb->SrbStatus = SRB_STATUS_SUCCESS;
Srb->ScsiStatus = SCSISTAT_GOOD; switch(Srb->Function) {
case SRB_FUNCTION_SHUTDOWN:
KdPrint(("StartIo: SRB_FUNCTION_SHUTDOWN\n"));
break;
case SRB_FUNCTION_FLUSH:
KdPrint(("StartIo: SRB_FUNCTION_FLUSH\n"));
break;
case SRB_FUNCTION_EXECUTE_SCSI:
// 运行 SCSI 命令
ReturnValue = ExecuteScsi(Srb);
break;
case SRB_FUNCTION_IO_CONTROL:
Srb->SrbStatus = SRB_STATUS_PENDING;
ReturnValue = DoIoControl(Srb);
break; default:
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
} ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
ScsiPortNotification(NextRequest, DeviceExtension);
return ReturnValue;
} BOOLEAN
Interrupt(
__in PVOID DeviceExtension
)
{
KdPrintThisFunction();
return TRUE;
} ULONG FindAdapter(
__in PVOID DeviceExtension,
__in PVOID HwContext,
__in PVOID BusInformation,
__in PCHAR ArgumentString,
__inout PPORT_CONFIGURATION_INFORMATION ConfigInfo,
__out PBOOLEAN Again
)
{
KdPrintThisFunction(); ConfigInfo->AdapterInterfaceType = Isa;
ConfigInfo->AlignmentMask = 0x00000003;
ConfigInfo->AutoRequestSense = TRUE;
ConfigInfo->BufferAccessScsiPortControlled = FALSE;
ConfigInfo->BusInterruptLevel = 0;
ConfigInfo->BusInterruptVector = 0;
ConfigInfo->Dma32BitAddresses = TRUE;
ConfigInfo->Master = TRUE;
ConfigInfo->CachesData = TRUE;
ConfigInfo->NumberOfBuses = 1;
ConfigInfo->MaximumNumberOfTargets = 1;
ConfigInfo->MaximumTransferLength = 0x10000;
ConfigInfo->MultipleRequestPerLu = FALSE;
ConfigInfo->NumberOfPhysicalBreaks = 0x00F8;
ConfigInfo->ScatterGather = TRUE;
ConfigInfo->TaggedQueuing = FALSE; *Again = FALSE;
return SP_RETURN_FOUND;
} SCSI_ADAPTER_CONTROL_STATUS
AdapterControl(
PVOID DeviceExtension,
SCSI_ADAPTER_CONTROL_TYPE CtlType,
PVOID Parameters
)
{
PSCSI_SUPPORTED_CONTROL_TYPE_LIST ScsiList=NULL;
SCSI_ADAPTER_CONTROL_STATUS status = ScsiAdapterControlSuccess; KdPrintThisFunction(); switch (CtlType<span style="font-family: Arial, Helvetica, sans-serif;">) </span>{
case ScsiQuerySupportedControlTypes:
KdPrint(("AdapterControl: ScsiQuerySupportedControlTypes\n"));
ScsiList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
<span style="font-family: Arial, Helvetica, sans-serif;">ScsiList</span>->SupportedTypeList[ScsiStopAdapter] = TRUE;
ScsiList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
ScsiList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
break; case ScsiStopAdapter:
KdPrint(("AdapterControl: ScsiStopAdapter\n"));
break; case ScsiRestartAdapter:
KdPrint(("AdapterControl: ScsiRestartAdapter\n"));
break; default:
status = ScsiAdapterControlUnsuccessful;
break;
} return status;
} BOOLEAN
AdapterState(
__in PVOID DeviceExtension,
__in PVOID Context,
__in BOOLEAN SaveState
)
{
KdPrintThisFunction();
return TRUE;
}

简要地说明一下。Scsiminiport 驱动事实上非常easy,就是调用ScsiPortInitialize 初始化之后,完毕各种 Srb 命令就能够了,源代码中本来想用中文凝视和英文凝视混杂。这是我的一个不好习惯,但凝视明了。极易读懂。

编译出来之后。能够直接安装。然后在磁盘管理里会新出现一个磁盘。初始化这个磁盘就能够了,我只设了 16M 以用来实现,能够通过改动源代码达到你想要的大小。把它用来当浏览器的暂时文件夹存储盘是相当不错的。每次重新启动,该盘会销毁,在微软的 wdf 源代码中有怎样使该盘自己主动初始化的源代码。你也能够加入一些其他功能,比方关机时把该盘中的功能 dump 到一个文件中,设备重新启动后再载入。就可以达到固化的效果。事实上网上有许多的成熟的产品能够使用,自己写一个也不过为了练习而已,驱动没有经过大量測试,这可能会导致蓝屏,而且它也可以在虚拟机上更改。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

SCSI miniport 驾驶一个简单的框架的更多相关文章

  1. 搭建一个简单struts2框架的登陆

    第一步:下载struts2对应的jar包,可以到struts官网下载:http://struts.apache.org/download.cgi#struts252 出于学习的目的,可以把整个完整的压 ...

  2. vue+vux-ui+axios+mock搭建一个简单vue框架

    1.首先感谢同事 2.之前一直在做angularjs的项目,目前vue火热,所以自己搭建了一个的vue框架,在此作为记录 vue+vux-ui这里就不介绍了,有很多博客都写的很详细了. 下面简单记录下 ...

  3. 一个简单RPC框架是怎样炼成的(V)——引入传输层

    开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理    接下来处理传输数据.实际应用场景一般都是基于socket.socket代码比較多, ...

  4. 一个简单RPC框架是怎样炼成的(II)——制定RPC消息

    开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 以下,我们先看一个普通的过程调用 class Client(object): def _ ...

  5. 一个简单RPC框架是怎样炼成的(IV)——实现RPC消息的编解码

    之前我们制定了一个非常easy的RPC消息 的格式,可是还遗留了两个问题,上一篇解决掉了一个.还留下一个 我们并没有实现对应的encode和decode方法,没有基于能够跨设备的字符串传输,而是直接的 ...

  6. 一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制

    开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法 ...

  7. 一个简单RPC框架是怎样炼成的(I)——开局篇

    开场白,这是一个关于RPC的相关概念的普及篇系列,主要是通过一步步的调整,提炼出一个相对完整的RPC框架. RPC(Remote Procedure Call Protocol)--远程过程调用协议, ...

  8. 如何设计Java框架----一个简单的例子【翻译】

    原文:http://www.programcreek.com/2011/09/how-to-design-a-java-framework/ 原文和翻译都只是参考,如有不对,欢迎指正. 你可能会好奇框 ...

  9. Python学习 - 编写一个简单的web框架(二)

    在上一篇日志中已经讨论和实现了根据url执行相应应用,在我阅读了bottle.py官方文档后,按照bottle的设计重写一遍,主要借鉴大牛们的设计思想. 一个bottle.py的简单实例 来看看bot ...

随机推荐

  1. 几本不错的CPU设计以及VLSI的书籍

    1. Microprocessor Design Principales and Practrices with VHDL  特点:电路与VHDL一一对应,比较清楚,而且还用MAX+plus进行仿真 ...

  2. mfc控件与其对应的对象的关联方法

    对话框的控件与其对应类的对象相关联:(两种方法) (1)      通过CWnd::DoDataExchange函数进行关联: 用VC++6.0的MFC ClassWizard中的Member Var ...

  3. android程序中使用命令行及获得命令行执行后的内容

    在开发android项目中,需要在程序中使用命令行执行,获得命令行执行后的结果并做处理. 下面是自己写的一个小例子,供以后参考使用: public String android_command(){ ...

  4. Type Unknown error: java.lang.NullPointerException

    Android 项目开发的时候 出现: Description Resource Path Location Type Unknown error: java.lang.NullPointerExce ...

  5. TPL异步并行编程之取消任务

    TPL异步并行编程之简单使用 在上篇随笔里面说明了Task的使用,仅仅是简单使用,有时候把一个任务交给Task去执行,但是呢还是要管理下,比如说:我要叫这个任务停止了,不做了,任务取消了,或者超时了 ...

  6. Qt+gsoap调用WebService

    1.       前言 Qt本身给我们提供了调用WebService的解决方案qsoap,看了一下他的介绍,感觉实在是太弱了,而且又是个新出的东西,所以还是决定不用他.既然使用Qt,那当然是跨平台的解 ...

  7. Java线程并发中常见的锁--自旋锁 偏向锁

    随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...

  8. 为VisualSVN Server增加在线修改用户密码的功能

    原文:为VisualSVN Server增加在线修改用户密码的功能 附件下载:点击下载 VisualSVN Server是一个非常不错的SVN Server程序,方便,直观,用户管理也异常方便. 不过 ...

  9. Xcode免证书真机调试,解决cannot read entitlement data问题

    本文是根据某个帖子写的(帖子链接在最后放出),但是在配置的过程中,遇到了一个纠结的问题,这个问题折腾了我N久,一直没搞明白到底是什么原因,问题如下: 按照原帖上写的每一步去做了,但是在最后编译的时候出 ...

  10. hdu 4970 Killing Monsters(数学题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4970 Problem Description Kingdom Rush is a popular TD ...