阅读:4243回复:32
scsi miniport的问题
我在写一个虚拟scsi设备的driver,使用ScsiPortNotification来返回srb到portdriver.但是因为是虚拟设备,所以没有真正的中断,目前是用ScsiPortNotification(RequestTimerCall,)来返回数据,但是好像这个timer最小间隔是10 milliseconds。这样很影响效率,请问一下大家有没有什么办法,可以直接ScsiPortNotification返回给port driver,或者什么方法可以提高效率?
|
|
最新喜欢:![]() |
沙发#
发布于:2005-01-27 13:37
为什么我用上面的方法,老是停在KeWaitForSingleObject上了??并且没有进我的HwStartIo
我的是xp |
|
板凳#
发布于:2005-01-26 17:49
daemon-tools alcohol的数据传输速率好象也不高呀。也就100X左右(17M/S)。是不是还是拜这个scsitimer 所害?
听说有人采用backdoor scsiport driver 可以达到71M/S, 采用哪个VSPORT 可以达到84M/s ,不知道是否是真的? 下边这种方法老大们用过吗? Subject: Re: Anton..Can you help? From: "Anton Kolomyeytsev" <xxx@cooldev.com> Date: Thu, 23 Jan 2003 09:29:39 -0500 Hi, you do not need to send SRBs to some unknown miniport, you need to send SRBs to yourself. From the worker thread you create to call all the code that need to be executed at PASSIVE_LEVEL and in system thread context you just call your own miniport to complete the previous request (SRB) you're handing in the worker thread now. First you need to locate DEVICE_OBJECT that belongs to you (to your miniport). PDEVICE_OBJECT g__PDEVICE_OBJECT__Miniport in global data region. In DriverEntry( ... ) you need to run: PDEVICE_OBJECT l__PDEVICE_OBJECT__Scan = ( ( PDRIVER_OBJECT )( p__PVOID__DriverObject )->DeviceObject ); while ( l__PDEVICE_OBJECT ) { ULONG l__ULONG__DeviceType = l__PDEVICE_OBJECT__Scan->DeviceType; if ( l__ULONG__DeviceType == FILE_DEVICE_CONTROLLER ) { g__PDEVICE_OBJECT__Miniport = l__PDEVICE_OBJECT__Scan; // Keep the pointer!!! break; } l__PDEVICE_OBJECT__Scan = l__PDEVICE_OBJECT__Scan->NextDevice; } Now you have DEVICE_OBJECT of your miniport in global variable. The way shown above is not "safe" but it works for me. If you do not like this way you can always try to enumerate all the SCSI miniports and find your own instance somewhere in the delayed initialization or later by call to ZwCreateFile( ..., "\\Device\\Scsi%u", ... ). Now in the worker thread that just executed code to do something with SRB you need to run this code (p__PSCSI_REQUEST_BLOCK__Srb is the SRB you're executing): KEVENT l__KEVENT; IO_STATUS_BLOCK l__IO_STATUS_BLOCK; PIRP l__PIRP; NTSTATUS l__NTSTATUS; SCSI_REQUEST_BLOCK l__SCSI_REQUEST_BLOCK; PIO_STACK_LOCATION l__PIO_STACK_LOCATION; PVOID l__PVOID__SrbBuffer = ( PVOID )( p__PSCSI_REQUEST_BLOCK__Srb ); // Keep pointer to SRB here LARGE_INTEGER l__LARGE_INTEGER__StartingOffset; KeInitializeEvent( &l__KEVENT, NotificationEvent, FALSE ); l__LARGE_INTEGER.QuadPart = 1; // SCSIPORT.SYS does this, do not know for what l__PIRP = IoBuildSynchronousFsdRequest( IRP_MJ_SCSI, g__PDEVICE_OBJECT__Miniport, // Global device object &l__PVOID__SrbBuffer, sizeof( l__PVOID__SrbBuffer ), &l__LARGE_INTEGER__StartingOffset, &l__KEVENT, &l__IO_STATUS_BLOCK ); RtlZeroMemory( &l__SCSI_REQUEST_BLOCK, sizeof( l__SCSI_REQUEST_BLOCK ) ); l__SCSI_REQUEST_BLOCK.TargetId = l__UCHAR__TargetId; // Your target ID goes here, and all SCSI address should be correct ... l__SCSI_REQUEST_BLOCK.Function = 2; l__SCSI_REQUEST_BLOCK.Length = sizeof( SCSI_REQUEST_BLOCK ); l__SCSI_REQUEST_BLOCK.SrbFlags = ( SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE | SRB_FLAGS_BYPASS_FROZEN_QUEUE ); // DO NOT FORGET TO PUT THIS FLAG OR YOU MAY RUN A DEADLOCK!! l__SCSI_REQUEST_BLOCK.DataBuffer = l__PVOID__SrbBuffer; l__SCSI_REQUEST_BLOCK.DataTransferLength = sizeof( l__PVOID__Buffer ); l__PIO_STACK_LOCATION = IoGetNextIrpStackLocation( l__PIRP ); l__PIO_STACK_LOCATION->MajorFunction = IRP_MJ_SCSI; l__PIO_STACK_LOCATION->MinorFunction = 1; l__PIO_STACK_LOCATION->Parameters.Scsi.Srb = &l__SCSI_REQUEST_BLOCK; l__NTSTATUS = IoCallDriver( g__PDEVICE_OBJECT__Miniport, // Global device object l__PIRP ); if( l__NTSTATUS == STATUS_PENDING ) { KeWaitForSingleObject( &l__KEVENT, Executive, KernelMode, FALSE, NULL ); l__NTSTATUS = l__IO_STATUS_BLOCK.Status; } Analyze l__NTSTATUS that keep operation completion here. So the idea is simple. From the thread that runs independently you can queue SRB that holds the pointer to the SRB you want to complete to your own miniport (if asking SCSIPORT to process the flag with no queue freeze). In the context of the SCSI miniport (HwStartIo) you analyze SRB and complete both SRBs on the same time, first that is pointer in .Buffer of the "parent" SRB and next this SRB itself ("parent"). That's all... I'm very sorry but I'm not going to spend more time on this topic - I've did this already last year and I have other things to do and do not know anything new about this stuff. In your particular case I'll recommend to write WDM driver that will be shared between 2000/XP/.NET and 98/Me and have storage part separated into port drivers (different of course ) for both platforms. Very good sample of doing this is USBLS120 from Microsoft (this sample not part of DDK but can be found on the net). Good luck! Regards, Anton Kolomyeytsev |
|
|
地板#
发布于:2005-01-25 15:04
我只有3MB/s,差劲啊,有没有details关于预取? 加一个LRU ,FIFO,OPT的队列就可以提高突发速率。可以达到daemon-tools 那样BT的300-400M/S的速度的。 不过提高数据传输确实恼火,用scsitimer 老是快不了。 |
|
|
地下室#
发布于:2004-04-30 16:06
预取这个东西就靠自己发挥了,呵呵,先把数据读到内存,下次就可以在startio拷贝数据,完成请求了。
|
|
5楼#
发布于:2004-04-29 09:13
我只有3MB/s,差劲啊,有没有details关于预取?
|
|
6楼#
发布于:2004-04-28 11:56
你是加个预取线程吧,我用这个方法的时候,预取线程和StartIo 总是不能并行运行,总是StartIo把cache搞完后才轮到预取线程运行。不知道你是怎么调优先级的。我的用cdspeed测试只有5M/s,Daemon可以到100M/s,真是变态。
加cache可能会有改善。我们就是这样提速的,差不多在10倍左右。用Nero测试下来,Burst Rate在60M左右。 |
|
7楼#
发布于:2004-04-27 14:00
我知道nt的code出来了,但是没想到这块也会有,一直都在忙,还没空看这些东西呢,主要还是怕看不懂,呵呵
|
|
8楼#
发布于:2004-04-27 11:11
o,真的么?太好了,能告诉我哪里有下么 可以使用BT下载啊,NT4 Sourcr泄露出来都那么久了,你竟然不知道?难道是闭关练功去了? |
|
|
9楼#
发布于:2004-04-27 09:15
o,真的么?太好了,能告诉我哪里有下么
|
|
10楼#
发布于:2004-04-26 16:46
NT4 Source里边有SCSIPORT.SYS的源代码,可以拿来参考一下。
|
|
11楼#
发布于:2004-04-26 14:05
我这里也没有port driver的例子,我自己也在找,现在只在www.storagecraft.com这里发现有人写了这个,准备让公司去买一套过来看看。
|
|
12楼#
发布于:2004-04-25 23:28
请问你的例子是什么系统
port driver 在win98下才会用吧 |
|
13楼#
发布于:2004-04-21 18:06
我用cache没有提高performance,用timer的方式效率一定很低的,微软的办法是重写一个port driver.
你们那里有没有写port driver的高手? |
|
14楼#
发布于:2004-04-21 17:49
terrychen:
你的scsi效率提高了吗?有没有比较好的方法亚 |
|
15楼#
发布于:2004-04-16 11:57
seaquester 大虾,救救小弟阿
把这段代码放到链表中,同时在线程中处理,就出现超时,但如果先把srb放到list中,并马上取出执行,就没有任何问题,请问这是怎么回事. Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->ScsiStatus = SCSISTAT_GOOD; DbgPrint(\"this=%x,m_ScsiHBA=%x\\n\",this,m_ScsiHBA); (this->*m_CmdTable[Srb->Cdb[0]])(Srb); ScsiPortNotification(NextRequest, (PVOID)m_ScsiHBA, Srb ); ScsiPortNotification(RequestComplete, (PVOID)m_ScsiHBA, Srb ); |
|
16楼#
发布于:2004-04-02 17:21
问问各位大牛:俺在Read10中调用如下SubRequest,之后在一个线程中接受事件来处理该Srb,之后将处理的Srb放到定时器的TimerCall中
完成提交,但在重新启动时好像死机一样,好像是Scsi miniport加载时一直处于等待状态,大家说一下我的这种做法可以吗?正确该怎么做呢 BOOLEAN CVThreadDevice::SubmitRequest(PSCSI_REQUEST_BLOCK Srb) { Srb->SrbStatus = SRB_STATUS_PENDING; if( KeGetCurrentIrql()>DISPATCH_LEVEL ) { VPrint(("Current IRQL: %x\n",KeGetCurrentIrql() )); // // KeSetEvent can only be running at DISPATCH_LEVEL and less // LoadStatus(Srb,recNOT_READY); // // use RequestReturn of base class here! // CVDevice::RequestReturn(Srb); return TRUE; } ((PSRB_EXTENSION)Srb->SrbExtension)->Srb = Srb; ExInterlockedInsertTailList( &RequestHead, &((PSRB_EXTENSION)Srb->SrbExtension)->ListEntry, &ListLock ); // // Signal the worker for processing // KeSetEvent( &ThreadEvent, IO_NO_INCREMENT, FALSE ); return TRUE; } |
|
17楼#
发布于:2003-12-31 21:23
这个我已经改了,改成了128k,但是一般系统不会一次i/o请求超过64k的,所以没什么用,估计miniport没戏了,得用别的port driver了
|
|
18楼#
发布于:2003-12-31 19:42
如果你是用文件虚拟设备的话,加cache不是很必要,应为文件系统本来就有cache(注意WRITE_THROUGH只控制写,而INTERMEDIATE_BUFFER不能控制FileSystem的cache)。
你可以把MaximumTransferLength加大点儿试试。 |
|
|
19楼#
发布于:2003-12-31 08:59
加cache,能不能说具体一点呢?我PORT_CONFIGURATION_INFORMATION里面的cachedata也true了,没有什么反映啊,版主说说吧
|
|
上一页
下一页