阅读:3296回复:21
kangzh,terrychen大虾看过来,关于scsiminiport,给100分
我的scsiminiport经常会出现bus reset,系统就会挂起,没有任何响应。我认为只要正确处理HwScsiResetBus,系统会从bus reset状态恢复过来,我的HwScsiResetBus的内容如下:
BOOLEAN MyDiskResetBus( IN PVOID HwDeviceExtension, IN ULONG PathId ) { KdPrint(("bus reset.\n")); ScsiPortCompleteRequest( HwDeviceExtension, (UCHAR)PathId, SP_UNTAGGED, SP_UNTAGGED, SRB_STATUS_BUS_RESET ); ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); return TRUE; } 上面例程被调用后,还是不行,系统仍然挂起,请问: 1、bus reset的真正含义是什么? 2、怎样从bus reset状态恢复过来,HwScsiResetBus到底应该怎样写 给100分,help me !!!!! |
|
最新喜欢:TOMG20...
|
沙发#
发布于:2004-08-23 10:20
经常出现总线reset应该是在规定的时间内scsi没有反馈srb给os造成的,一般为10ms,如果及时反馈,应该不会出现这个问题.你在reset之后才反馈,应该已经timeout了
|
|
板凳#
发布于:2004-08-23 14:23
问题是一旦出现bus reset,我还能恢复过来吗?
由于我做的是网络虚拟磁盘,保持响应时间在10ms之内对于网络来说不是那么容易保证的,比如服务器负载重,局域网网络负载重等情况,所以bus reset迟早会发生,这是一个不能回避的问题。 所以在一方面是提高响应时间,另一方面是在出现bus reset时怎样恢复过来,我注意到kangzh和terrychen做网络虚拟磁盘很长时间了,你们是怎样保持响应时间在10ms之内的,又是怎样从bus reset中恢复过来的呢? ?????? 另外,bus reset时要求在HwScsiResetBus中完成所有的srb,而我在bus reset后利用!irpfind发现仍有未完成的irp(srb),显然我的HwScsiResetBus中的ScsiPortCompleteRequest调用并没有完成srb。于是我怀疑我是将在startio中将srb插入队列,交给一个内核线程来处理。在出现bus reset时,有可能线程正在处理该srb,这时HwScsiResetBus中该怎样完成srb呢? 办法一是让HwScsiResetBus和内核线程间有某种同步措施,同时只能有一方在处理srb。但HwScsiResetBus工作在dispatch_level,好像没法使用内核同步对象,即不能waitforxxxobject。 办法二是好像从外部杀掉内核线程,然后完成srb,但好像没有办法从外部杀掉一个内核线程。 我的分析有问题吗?真是痛苦啊! |
|
|
地板#
发布于:2004-08-23 15:09
应该还是你ScsiPortCompleteRequest返回状态的问题,bus reset是一般在10秒中如果还不能返回数据(pending或者没有返回数据)情况下发生,具体timeout 的时间是由scsi_request_block里面的TimeOutValue数值决定的,10ms不能保证,10秒总可以吧,bus reset我没用过,说实在我很怕它,你还是看看你的返回程序吧,ScsiPortCompleteRequest只能在startio函数,或者timercall函数利被调用才能真正的把数据返回给scsi port driver.你再确认一遍,或者把你程序ScsiPortCompleteRequest调用的位置给大家看看。
|
|
地下室#
发布于:2004-08-23 16:35
terrychen, 以下是我的代码(只贴出最主要的vdisk.c文件,其他代码跟这个问题不相关,太多了,就不贴了),其中有些地方是访问tdi的,不用管。我只在HwVDiskTimer中调用了ScsiPortNotification来完成srb。
帮我看看,多谢! #include <ntddk.h> #include <ntddscsi.h> #include <scsi.h> #include <srb.h> #include "vdisk.h" #include "srbhandler.h" extern SrbHandler SrbHandlerArray[0x60]; BOOLEAN SingletonFound = FALSE; ULONG DriverEntry( IN PVOID DriverObject, IN PVOID Argument2 ) { ULONG i, status; HW_INITIALIZATION_DATA hwInitData; DbgPrint("Enter DriverEntry, IRQL:%d\n", KeGetCurrentIrql()); // zero hwInitData ... for (i=0; i<sizeof(hwInitData); i++) { ((UCHAR *)(&hwInitData)) = 0; } hwInitData.HwInitializationDataSize = \ sizeof(HW_INITIALIZATION_DATA); // init hwInitData ... hwInitData.HwInitialize = VDiskInitialize; hwInitData.HwResetBus = VDiskResetBus; hwInitData.HwStartIo = VDiskStartIo; hwInitData.HwFindAdapter = VDiskFindAdapter; // give me virtual address ... hwInitData.MapBuffers = TRUE; hwInitData.NeedPhysicalAddresses = FALSE; // set device extensions ... hwInitData.DeviceExtensionSize = sizeof(VDISK_EXTENSION); //hwInitData.SrbExtensionSize = GetExtraRequestSize(); // Specifiy the bus type ... hwInitData.AdapterInterfaceType = Isa; hwInitData.NumberOfAccessRanges = 1; hwInitData.TaggedQueuing = FALSE; // don't support command queue now // // setting the AutoRequestSence to TRUE indicates that the HBA can perform // a request-sense operation without requiring an explicit request to do so. // we here set it to TRUE mean will set sense data in Srb->SenseInfoBuffer when // error occurs ... // hwInitData.AutoRequestSense = TRUE; hwInitData.MultipleRequestPerLu = FALSE; // don't support command queue now // use SRB extension to store LIST_ENTRY, as to make SRB list. hwInitData.SrbExtensionSize = sizeof(SRB_EXTENSION); status = \ ScsiPortInitialize( DriverObject, // first parameter of DriverEntry Argument2, // second parameter of DriverEntry &hwInitData, // pointer to hwInitData NULL // address of context to be passed to HwScsiFindAdapter ); return status; } /* * called by ScsiPortInitailize, and is responsible for filling in * rest fields of the PORT_CONFIGURATION_INFORMATION structure ... * Params -- * HwDeviceExtension -- points to the miniport driver's per-HBA storage area * HwContext -- points to the context value * BusInformation -- points to bus-type-specific info that the port driver has gathered * ConfigInfo -- config info, which has been partly filled by port driver * Again -- TRUE indicates that the miniport driver want the port driver to call it * again to find another HBA. */ ULONG VDiskFindAdapter( IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again ) { DbgPrint("Enter VDiskFindAdapter, IRQL:%d\n", KeGetCurrentIrql()); if( SingletonFound ) { // // Only support one controller // *Again = FALSE; return SP_RETURN_NOT_FOUND; } SingletonFound = TRUE; ConfigInfo->BusInterruptVector = 0; // virtual device, no interrupt ConfigInfo->BusInterruptLevel = 0; ConfigInfo->ScatterGather = FALSE; // not support scatter/gather // // the MTU of ethernet is 1500, so here the HBA only support max // transfer length of 1024 // ConfigInfo->MaximumTransferLength = MAX_TRANSFER; // 8K //0x10000; // 1024 // // Specifies the maximum number of breaks between address ranges that a data // buffer can have if the HBA supports scatter/gather. 0 means no scatter/gather // support. // ConfigInfo->NumberOfPhysicalBreaks = 0; ConfigInfo->Master = FALSE; // // indeed it's easy to support multiple request per lu with current // request queue implementation. You just need to change TaggedQueuing // and MultipleRequestPerLu to TRUE here and modify RequestReturn. // ConfigInfo->TaggedQueuing = FALSE; ConfigInfo->MultipleRequestPerLu = FALSE; // // with AutoRequestSense, I don't need to implement REQUEST SENSE command. // ConfigInfo->AutoRequestSense = TRUE; ConfigInfo->AlignmentMask = 0x00000003; ConfigInfo->BufferAccessScsiPortControlled = FALSE; ConfigInfo->CachesData = FALSE; ConfigInfo->NumberOfBuses = 1; ConfigInfo->MaximumNumberOfTargets = 4; ConfigInfo->Dma32BitAddresses = TRUE; // we only want to support one HBA ... *Again = FALSE; // // let port driver know that a supported HBA was found and that the // HBA-relevant configuration information was successfully determined // and set in the PORT_CONFIGURATION_INFORMATION structure. // return SP_RETURN_FOUND; } /* * For each supported HBA found by the miniport driver, its HwScsiInitialize * routine is called to set up the HBA's registers and initial state, if any. * If the initialization succeeds, HwScsiInitialize should return TRUE. * Paramters -- * HwDeviceExtension -- Points to the miniport driver's per-HBA storage area. */ BOOLEAN VDiskInitialize( IN PVOID HwDeviceExtension ) { NTSTATUS status; PVDISK_EXTENSION pExt = (PVDISK_EXTENSION)HwDeviceExtension; OBJECT_ATTRIBUTES ObjAttr; IO_STATUS_BLOCK IoStatus; DbgPrint("Enter VDiskInitialize, IRQL:%d\n", KeGetCurrentIrql()); // pExt->BlockCount = pExt->BlockSize = 0; // 初始化两个同步事件 KeInitializeEvent( &(pExt->ThrdSyncEvent), // event handle SynchronizationEvent, // synchronization event FALSE // not signaled ); KeInitializeEvent( &(pExt->SrbListSyncEvent), // event handle SynchronizationEvent, // synchronization event FALSE // not signaled ); // 初始化两个SRB 队列 InitializeListHead(&pExt->SrbList); KeInitializeSpinLock(&pExt->SrbListLock); InitializeListHead(&pExt->CompletedSrbList); KeInitializeSpinLock(&pExt->CompletedSrbListLock); // // 创建工作线程,因为文件操作必须在 // PASSIVE_LEVEL 执行,所以所有的文件操作 // 都让工作线程来执行 // status = PsCreateSystemThread( &(pExt->ThrdHandle), // thread handle (ACCESS_MASK)0L, // desired access NULL, // object attr, NULL for driver created thread NULL, // process handle, NULL for driver created thread NULL, // client id, NULL for driver created thread VDiskWorkerThrd, // start routine HwDeviceExtension // start context ); if ( !NT_SUCCESS(status)) { KdPrint(("Fail to create working thread!\n")); return FALSE; } // 等待工作线程初始化完成 KdPrint(("Waiting for worker thread to complete initialization ...\n")); KeWaitForSingleObject( (PVOID)(&(pExt->ThrdSyncEvent)), // event handle Executive, KernelMode, FALSE, 0 // must be 0 at DISPATCH_LEVEL ); KdPrint(("Continue to run after worker thread has completed initialization ...\n")); // 设置定时器,定期处理完成的SRB ScsiPortNotification(RequestTimerCall,HwDeviceExtension,HwVDiskTimer, VDISK_TIMER_PERIOD); // 0.1s // 返回TRUE 表示初始化成功,可以接受请求了 return TRUE; } /* * All miniport drivers must have a HwScsiStartIo routine. The port driver * calls HwScsiStartIo first with each incoming I/O request for a target on * a SCSI bus. HwScsiStartIo returns TRUE to acknowledge receipt of the SRB. * * NOTE that we use "FILEDISK" to simulate all the disk operation, and all * the file operation must be executed under PASSIVE_LEVEL, so we use a * system thread to conduct file operation. And, the driver communicate with * system thread through 2 list, one for SRBs, and one for completed SRBs. * * VDiskStartIo just insert the comming SRBs into SRB List. * * Parameters -- * HwDeviceExtension -- Points to the miniport driver's per-HBA storage area. * Srb -- points to the SRB passed in by port driver. */ BOOLEAN VDiskStartIo( IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PVDISK_EXTENSION pExt = (PVDISK_EXTENSION)HwDeviceExtension; // Srb->SrbStatus = SRB_STATUS_PENDING; // 将SRB 插入队列尾部 ((PSRB_EXTENSION)(Srb->SrbExtension))->pSrb = Srb; ExInterlockedInsertTailList( &pExt->SrbList, &((PSRB_EXTENSION)(Srb->SrbExtension))->ListEntry, &pExt->SrbListLock ); // 通知工作线程SRB 已经到来 KeSetEvent( &pExt->SrbListSyncEvent, IO_NO_INCREMENT, FALSE ); // miniport driver should always return TRUE here ... return TRUE; } // // // VOID HwVDiskTimer( IN PVOID HwDeviceExtension ) { PLIST_ENTRY ListEntry; PSCSI_REQUEST_BLOCK pSrb; PVDISK_EXTENSION pExt = (PVDISK_EXTENSION)HwDeviceExtension; unsigned int i; // 从完成队列头部取出完成的SRB ListEntry = ExInterlockedRemoveHeadList ( &pExt->CompletedSrbList, &pExt->CompletedSrbListLock ); while( ListEntry!=NULL ) { pSrb = SRB_FROM_ENTRY(ListEntry); KdPrint(("\nA SRB Completed\n")); ReturnFromStartIo( pExt, pSrb ); // 从完成队列头部取出完成的SRB ListEntry = ExInterlockedRemoveHeadList ( &pExt->CompletedSrbList, &pExt->CompletedSrbListLock ); } // 这个定时器不是周期性的,每次响应后必须重新设置 ScsiPortNotification(RequestTimerCall,HwDeviceExtension,HwVDiskTimer, VDISK_TIMER_PERIOD); } /* * HwScsiResetBus resets a given SCSI bus. If the bus is successfully reset, * HwScsiResetBus returns TRUE. * Parameters -- * HwDeviceExtension -- Points to the miniport driver's per-HBA storage area * PathId -- Identifies the SCSI bus to be reset */ BOOLEAN VDiskResetBus( IN PVOID HwDeviceExtension, IN ULONG PathId ) { KdPrint(("bus reset, IRQL:%d\n", KeGetCurrentIrql())); // // ScsiPortCompleteRequest completes all of the active requests for // the given SCSI bus, controller, or LU, including a request being // processed by the calling miniport routine. // /* ScsiPortCompleteRequest( HwDeviceExtension, // points to the per-HBA storage ... (UCHAR)PathId, // identifies the SCSI bus ... SP_UNTAGGED, // identifies the target controler, SP_UNTAGGED means all the target ... SP_UNTAGGED, // identifies the LU, SP_UNTAGGED means all the LU ... SRB_STATUS_BUS_RESET // Specifies the completion status to be set in the SrbStatus member of each SRB. ); // // After completing the bus-reset request and any outstanding requests, // the miniport must call ScsiPortNotification with the NotificationType // NextRequest. // ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); */ // do reset bus ... // ... return TRUE; //return FALSE; } /* * VDiskWorkerThrd open "FILEDISK" and wait for SRB to process. * Parameters -- * thrdContext -- points to the device extension */ VOID VDiskWorkerThrd( PVOID thrdContext) { NTSTATUS status; OBJECT_ATTRIBUTES ObjAttr; IO_STATUS_BLOCK IoStatus; VDISK_EXTENSION *pExt = (PVDISK_EXTENSION)thrdContext; FILE_STANDARD_INFORMATION StandardInfo; UNICODE_STRING FileName; PLIST_ENTRY ListEntry; PSCSI_REQUEST_BLOCK pSrb; TA_IP_ADDRESS transAddr; // 打开本地传输层地址 TuInitTransAddr(&transAddr, 0/*INADDR_ANY*/, htons(5889)); status = TuOpenTransAddr(L"\\Device\\Udp", &transAddr, &pExt->TuLocalAddr); if ( !NT_SUCCESS(status)) { KdPrint(("In VDiskWorkerThrd, Fail to Open Transport Address!\n")); return; } // 查询注册表,读取服务器地址和端口 // ... ((UCHAR *)(&pExt->srvAddr))[0] = 10; ((UCHAR *)(&pExt->srvAddr))[1] = 0; ((UCHAR *)(&pExt->srvAddr))[2] = 0; ((UCHAR *)(&pExt->srvAddr))[3] = 8; pExt->srvPort = htons(5888); // 登录远程服务器 // ... // 通知父进程,已经准备好,可以 接受SRB 了 KeSetEvent( &pExt->ThrdSyncEvent, IO_NO_INCREMENT, FALSE ); // 无限循环,处理SRB KdPrint(("Worker thread is ready for processing SRBs ...\n")); while (TRUE) { // 如果SRB 已经进入队列,父进程会通知我 KeWaitForSingleObject( &pExt->SrbListSyncEvent, Executive, KernelMode, FALSE, 0 ); // 从队列中取出SRB ListEntry = ExInterlockedRemoveHeadList( &pExt->SrbList, &pExt->SrbListLock // spin lock ); // i'll eat all the ready SRBs at one time while (ListEntry != NULL) { pSrb = SRB_FROM_ENTRY(ListEntry); // 处理SRB if ( !VDiskProcessSrb( pExt, pSrb)) { break; } // 从队列中取出SRB ListEntry = ExInterlockedRemoveHeadList( &pExt->SrbList, &pExt->SrbListLock ); } } DbgPrint(("worker thread terminated\n")); PsTerminateSystemThread(status); } /* * Called by VDISK Worker Thread, and deal with all kinds of SRBs * Parameters -- * HwDeviceExtension -- Points to the miniport driver's per-HBA storage area. * Srb -- points to the SRB passed in by port driver. */ BOOLEAN VDiskProcessSrb( IN PVOID HwDeviceExtension, PSCSI_REQUEST_BLOCK pSrb ) { PVDISK_EXTENSION pExt = (PVDISK_EXTENSION)HwDeviceExtension; // DumpSrb( pSrb); pSrb->SrbStatus = SRB_STATUS_SUCCESS; pSrb->ScsiStatus = SCSISTAT_GOOD; switch (pSrb->Function) { case SRB_FUNCTION_EXECUTE_SCSI: // a deivce I/O should be executed on target LU ... HandleExecuteScsi(HwDeviceExtension, pSrb); break; case SRB_FUNCTION_ABORT_COMMAND: // cancel the SRB pointed by 'Srb->NextSrb' ... KdPrint(("about message recved.\n")); HandleAbortCommand(HwDeviceExtension, pSrb); break; case SRB_FUNCTION_RESET_BUS: // // reset the bus, miniport will receive this request only when a // request is time-out, and the subsequent request to terminate // the request is time-out. // The miniport driver should complete all pending requests and // must reset the given bus, but HOWTO complete pending requests. // KdPrint(("reset bus message received.\n")); HandleResetBus(HwDeviceExtension, pSrb); break; case SRB_FUNCTION_TERMINATE_IO: // terminate the request pointed by 'Srb->NextSrb', No IDEA ... break; case SRB_FUNCTION_RECEIVE_EVENT: // // The HBA should be prepared to receive an asynchronous event // notification from the addressed target. No IDEA ... // break; case SRB_FUNCTION_IO_CONTROL: HandleIoControl(HwDeviceExtension, pSrb); break; // // in PORT_CONFIGURATION_INFORMATION structure, there is a field named // 'ResetTargetSupported'. Setting this value to TRUE indicates that the // miniport driver has the ability to reset a target device in response // to an 'SRB_FUNCTION_RESET_DEVICE' request from the port driver. // By default, the value of this member is FALSE. // Since we set this to FALSE, so we needn't deal with it here ... // case SRB_FUNCTION_RESET_DEVICE: // // following 2 requests are sent to a miniport driver only if it set // CachesData to TRUE in the PORT_CONFIGURATION_INFORMATION for the HBA. // we set the CachesData to FALSE, so needn't deal with them here ... // case SRB_FUNCTION_SHUTDOWN: case SRB_FUNCTION_FLUSH: default: pSrb->SrbStatus = SRB_STATUS_INVALID_REQUEST; break; } // // 处理完SRB 之后,将它们插入完成队列, // 定时器会处理这些SRB,并把它们返回给PORT // ExInterlockedInsertTailList( &pExt->CompletedSrbList, &((PSRB_EXTENSION)pSrb->SrbExtension)->ListEntry, &pExt->CompletedSrbListLock ); return TRUE; } /* * Dump SRB * Parameters -- * Srb -- points to the SRB passed in by port driver. * * SCSI_REQUEST_BLOCK is defined as follows ... * typedef struct _SCSI_REQUEST_BLOCK { USHORT Length; UCHAR Function; UCHAR SrbStatus; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR QueueTag; UCHAR QueueAction; UCHAR CdbLength; UCHAR SenseInfoBufferLength; ULONG SrbFlags; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; PVOID SenseInfoBuffer; struct _SCSI_REQUEST_BLOCK *NextSrb; PVOID OriginalRequest; PVOID SrbExtension; union { ULONG InternalStatus; ULONG QueueSortKey; }; UCHAR Cdb[16]; } SCSI_REQUEST_BLOCK, *PSCSI_REQUEST_BLOCK; * * and the "Function" is defined as follows * #define SRB_FUNCTION_EXECUTE_SCSI 0x00 #define SRB_FUNCTION_CLAIM_DEVICE 0x01 #define SRB_FUNCTION_IO_CONTROL 0x02 #define SRB_FUNCTION_RECEIVE_EVENT 0x03 #define SRB_FUNCTION_RELEASE_QUEUE 0x04 #define SRB_FUNCTION_ATTACH_DEVICE 0x05 #define SRB_FUNCTION_RELEASE_DEVICE 0x06 #define SRB_FUNCTION_SHUTDOWN 0x07 #define SRB_FUNCTION_FLUSH 0x08 #define SRB_FUNCTION_ABORT_COMMAND 0x10 #define SRB_FUNCTION_RELEASE_RECOVERY 0x11 #define SRB_FUNCTION_RESET_BUS 0x12 #define SRB_FUNCTION_RESET_DEVICE 0x13 #define SRB_FUNCTION_TERMINATE_IO 0x14 #define SRB_FUNCTION_FLUSH_QUEUE 0x15 #define SRB_FUNCTION_REMOVE_DEVICE 0x16 #define SRB_FUNCTION_WMI 0x17 #define SRB_FUNCTION_LOCK_QUEUE 0x18 #define SRB_FUNCTION_UNLOCK_QUEUE 0x19 * */ VOID DumpSrb( IN PSCSI_REQUEST_BLOCK Srb) { unsigned int i; DbgPrint( "\n\n"); DbgPrint( "SRB Function: %02x\nPathId: %02x\nTargetId: %02x\nLUN: %02x\n", \ Srb->Function, Srb->PathId, Srb->TargetId, Srb->Lun); if ( Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { DbgPrint( "CDB: "); for ( i=0; i<sizeof( Srb->Cdb); i++) DbgPrint( "%02x ", Srb->Cdb); } DbgPrint( "\n\n"); return; } /* * this is a dispatch according to the Srb->Cdb[0] * parameters -- * HwDeviceExtension -- Points to the miniport driver's per-HBA storage area. * Srb -- points to the SRB passed in by port driver. */ VOID HandleExecuteScsi( IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { if ( Srb->Cdb[0] >= SRB_HANDLERS_COUNT) { HandleInvalidRequest( HwDeviceExtension, Srb ); return; } SrbHandlerArray[Srb->Cdb[0]]( HwDeviceExtension, Srb ); return; } VOID HandleIoControl( IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { // // all the io control sent to the miniport must have a header // structure of type SRB_IO_CONTROL. // PSRB_IO_CONTROL pIoCtrlHeader; ULONG IoCtrlCode; KdPrint(("Enter HandleIoControl ...\n")); pIoCtrlHeader = (PSRB_IO_CONTROL)Srb->DataBuffer; IoCtrlCode = pIoCtrlHeader->ControlCode; DumpIoCtrl( pIoCtrlHeader); // we are not intent to deal with the io control ... Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return; } /* * Dump SRB */ VOID DumpIoCtrl( IN PSRB_IO_CONTROL pIoCtrlHeader) { UCHAR Signature[9]; DbgPrint("Header Length: %08x\n", pIoCtrlHeader->HeaderLength); ScsiPortMoveMemory( Signature, pIoCtrlHeader->Signature, 8); Signature[8] = 0; DbgPrint("Signature: %s\n", Signature); DbgPrint("Timeout: %08x\n", pIoCtrlHeader->Timeout); DbgPrint("Control Code: %08x\n", pIoCtrlHeader->ControlCode); DbgPrint("Additional Length: %08x\n", pIoCtrlHeader->Length); return; } /* * */ VOID HandleAbortCommand( IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PSCSI_REQUEST_BLOCK TempSrb; // get the active request on the target LU ... TempSrb = ScsiPortGetSrb( HwDeviceExtension, // Device extension ... Srb->PathId, // identifies the SCSI bus .. Srb->TargetId, // identifies the HBA ... Srb->Lun, // identifies the LU ... SP_UNTAGGED // ); if ( TempSrb != Srb->NextSrb) { // the current request is not the same as the one to be canceled ... Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; goto out; } // do abort ... Srb->SrbStatus = SRB_STATUS_ABORTED; out: ReturnFromStartIo( HwDeviceExtension, Srb); return; } /* * just call VDiskResetBus ... */ VOID HandleResetBus( IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { VDiskResetBus( HwDeviceExtension, Srb->PathId); return; } /* * there are 2 things to do when return from HwScsiStartIo, * 1st, call ScsiPortNotification with Notification type RequestComplete, * 2nd, call ScsiPortNotification with Notification type NextRequest. */ VOID ReturnFromStartIo( IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { // 1st, RequestComplete ... ScsiPortNotification( RequestComplete, HwDeviceExtension, Srb ); // 2nd, NextRequest ... ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); return; } |
|
|
5楼#
发布于:2004-08-23 17:06
建议你在HwVDiskTimer里面
while( ListEntry!=NULL ) { pSrb = SRB_FROM_ENTRY(ListEntry); 后面 加一句 pSrb->SrbStatus = SRB_STATUS_SUCCESS; 试试看,看结构应该ScsiPortNotification没有大问题。 你reset bus是偶然出现还是每次有规律的,如果有规律什么时候出现? |
|
6楼#
发布于:2004-08-23 18:02
〉建议你在HwVDiskTimer里面
〉while( ListEntry!=NULL ) 〉{ 〉pSrb = SRB_FROM_ENTRY(ListEntry); 〉后面 〉加一句 pSrb->SrbStatus = SRB_STATUS_SUCCESS; 并不是所有的srb都要返回SRB_STATUS_SUCCESS,有的还要返回SRB_STATUS_INVALID_REQUEST。我把所有的function为SRB_FUNCTION_EXECUTE_SCSI的srb都返回SRB_STATUS_SUCCESS了。 reset bus一般出现在开机的时候,或是读写较大的文件的时候。 现在,我的驱动读写较小的文件时(100K左右)没什么问题,但读几兆大小的文件时就会产生bus reset。 我刚刚又在VDiskStartIo返回前加入了一句 ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); 也就是miniport每次把srb放入队列后马上从port driver取下一个srb,这样是不是应该限制一下队列的长度,比如最长20? terrychen,kangzh,你们的网络虚拟磁盘工作正常吗?有没有遇到过我所遇到的bus reset的情况,或在读写大文件时有bus reset发生。 |
|
|
7楼#
发布于:2004-08-24 14:12
两位老大不在家吗,顶一顶
|
|
|
8楼#
发布于:2004-08-24 14:58
我没有出现过你说的情况,一般出现这个现象大概有几个原因:1,你的数据偏移不对,不能被操作系统识别,2,没有及时反馈,3,其他错误,你的代码太长,呵呵,我检查不出来,你看看我说的数据偏移是否正确
|
|
9楼#
发布于:2004-08-24 15:26
我的文件系统是ntfs,格式化的时候每块大小设为512字节。读写时,srb的cdb中给出逻辑块号和需要读写多少块,偏移=逻辑块号*512,这样不就可以了吗?
|
|
|
10楼#
发布于:2004-08-24 21:00
顶 !!!!!!!!
|
|
11楼#
发布于:2004-08-25 09:16
我建议你在startio里面这么做,你需要用timercall返回的srb,在startio里面也ScsiPortNotification()回去,不过status改为pending,那些SRB_STATUS_INVALID_REQUEST和你直接返回success的也在startio那里直接ScsiPortNotification()回去,减少出错可能,我觉得还是你ScsiPortNotification()返回有问题。
|
|
12楼#
发布于:2004-08-26 21:12
let me try, however, thanks!
|
|
|
13楼#
发布于:2004-09-03 10:22
ZwCreateFile 加上 FILE_NO_INTERMEDIATE_BUFFERING
|
|
|
14楼#
发布于:2004-09-03 11:23
你程式中所用的CompleteRequest是在complete bus reset 呃
|
|
15楼#
发布于:2004-09-06 17:35
thank u all
在众人的帮助下,我的网络虚拟磁盘基本可以工作了,由于我用的是udp,所以会有丢包,加了超时重发和校验和之后,效果还可以。 我并没有处理bus reset,不过我打算以后处理,johnnyweng的意见很重要。 感谢terrychen和kangzh,我决定散分了,头一次给分,还不知道怎么给,试试看。 |
|
|
16楼#
发布于:2004-09-06 17:48
great,祝贺你了,不知道你打算resetbus怎么处理?我也一直想处理,可是不知道怎么下手
|
|
17楼#
发布于:2004-09-10 10:35
bus reset发生时,scsiport一般调用HwScsiResetBus,可以再做一个OOB(带外)队列,当发生bus reset时,让HwScsiResetBus向OOB队列中插入一个消息。
工作线程每次处理一个SRB后,检查OOB队列,如果有BUS RESET发生,则取出SRB队列中的所有SRB,插入SRB完成队列,并利用scsiportnotification以SRB_STATUS_BUS_RESET状态完成每个srb. 你认为可行吗,我还没试,如果你试验有结果,烦请告知 good luck |
|
|
18楼#
发布于:2004-09-10 10:53
应该不可以吧,当发生bus reset时,好像系统就已经无法控制了,并且如果那样反馈srb,此时的srb并没有携带正确的数据,反馈给操作系统,一样会有问题的
|
|
19楼#
发布于:2004-09-10 13:03
在bus reset时,系统仍在运行,并且工作线程仍可以被调度,所以可以插入。
利用scsiportnotification以SRB_STATUS_BUS_RESET状态完成每个srb,应该不需要携带什么数据吧. |
|
|
上一页
下一页