阅读:3179回复:14
SCSI MINIPORT 怎么给自己发送SRB?
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_SCSI, pDevice, &Srb, sizeof(Srb), &Offset, &Event, &IoStatus ); 建立一个同步IRP发送SRB,但是发送完就一直停在KeWaitForSingleObject了,如果创建一个异步IRP,发送过去就蓝平了。 |
|
|
沙发#
发布于:2007-06-19 07:25
pDevice从哪里拿到的?另外,你是在什么时候发送的?
|
|
|
板凳#
发布于:2007-06-19 10:03
PDEVICE是自己的设备对象,是SCSI CONTROLLER。
在系统线程里发送的。 |
|
|
地板#
发布于:2007-06-19 10:05
LARGE_INTEGER Offset;
Offset.QuadPart = 0; SCSI_REQUEST_BLOCK Srb; Irp = IoBuildSynchronousFsdRequest( IRP_MJ_SCSI, pDevice, &Srb, sizeof(Srb), &Offset, &Event, &IoStatus ); RtlCopyMemory(&Srb,pSrb,sizeof(SCSI_REQUEST_BLOCK)); Srb.TargetId = 4; // Your target ID Srb.Function = SRB_FUNCTION_FLUSH;//100;//; SRB_FUNCTION_IO_CONTROL Srb.Length = sizeof( SCSI_REQUEST_BLOCK ); Srb.SrbFlags = ( SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE | SRB_FLAGS_BYPASS_FROZEN_QUEUE ); // DO NOT FORGET TO PUT THIS FLAG OR YOU //Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER |SRB_FLAGS_BYPASS_FROZEN_QUEUE; Srb.SrbExtension = pSrb->SrbExtension; Srb.NextSrb = NULL; Srb.OriginalRequest = Irp; Srb.SenseInfoBuffer = NULL; Srb.SenseInfoBufferLength = 0; Srb.DataBuffer = &IoBuf; Srb.DataTransferLength = sizeof( IoBuf ); PIO_STACK_LOCATION IrpSp = IoGetNextIrpStackLocation( Irp ); IrpSp->MajorFunction = IRP_MJ_SCSI; IrpSp->MinorFunction = 1; IrpSp->Parameters.Scsi.Srb = &Srb; Status = IoCallDriver(pDevice,Irp); if( Status == STATUS_PENDING ) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = IoStatus.Status; } if(!NT_SUCCESS(Status)) { KdPrint(("Device io error %X\n",Status)); } |
|
|
地下室#
发布于:2007-06-19 17:20
好像不能这样做把,miniport 与portdriver 合在一起才是一个标准的驱动。发给miniport 会不会已经在DISPATCH_LEVEL 了?你发给portdriver 试一下捏??
|
|
|
5楼#
发布于:2007-06-19 21:48
SenseData需要自己分配空间
仔细检查一下,有好几个值都需要自己分配空间 |
|
|
6楼#
发布于:2007-06-20 11:45
确实试到DL了,因为在StartIO历程里已经不能完成SRB了
但是发送给PORT DRIVER也还是无效。 另外不需要SenseData啊,所以置为NULL了。 |
|
|
7楼#
发布于:2007-06-21 09:30
1。你说的Controller Device Object其实就是那个SCSI Adapter了,有见过Adapter回应SRB的么?SRB都是由Target/Lun来回应的,打开DeviceTree仔细看看就明白了。你应该找到自己的Target/Lun对应的Device Object(比如通过DriveLetter或者GUID),然后向它发送IRP_MJ_SCSI/SRB,对Adapter,只能发送IOCTL_SCSI_GET_ADDRESS之类的
2。我说的“什么时候”发送,是说在DriverEntry、DeviceIoControl还是其他的Dispatch Routine里面,因为在有的情况下会有dead lock 3。至于如何送SRB,去看src\storage\class\classpnp的class.c中ClassSendSrbSynchronous,略作修改就可以用了,而且其中的flags很重要如果设置不对,会造成frozen,如果buffer没有弄好,也会有crash |
|
|
8楼#
发布于:2007-06-21 16:44
不要调用IoCallDriver,直接调用StartIo试试吧。
KeRaiseIrql( DISPATCH_LEVEL, &oldIrql ); DeviceObject->DriverObject->DriverStartIo( DeviceObject, Irp ); KeLowerIrql( DISPATCH_LEVEL, oldIrql ); |
|
9楼#
发布于:2007-06-22 09:40
tooflat
斑竹这招高,实在是高!!直接进portdriver 了? |
|
|
10楼#
发布于:2007-06-25 17:49
直接发送SRB到控制器是可以的,但是前提是至少有一个PORT DRIVER
我现在修改了一下,可以发送SRB也能收到了,但是我想在STARTIO里完成以前的SRB,好像还是不行。 tooflat 老大说的 ,那岂不是还是不在原来的上下文里,还是不能完成以前的SRB? |
|
|
11楼#
发布于:2007-06-25 20:49
DriverStartIO还是HwStartIO ?
|
|
12楼#
发布于:2007-06-27 11:55
HwStartIO
|
|
|
13楼#
发布于:2007-06-29 09:12
HwStartIO已经是在正确的上下文里了。
|
|
14楼#
发布于:2007-06-29 13:20
对,但是标志不对也不行,现在可以了,速度一下提高了好几十倍。
|
|
|