static VOID XenScsi_CheckNewDevice(PVOID DeviceExtension) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; //FUNCTION_ENTER(); if (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_PAUSED, SHARED_PAUSED_PASSIVE_PAUSED) == SHARED_PAUSED_PASSIVE_PAUSED) { KdPrint((__DRIVER_NAME " scsiport paused\n")); xsdd->scsiport_paused = TRUE; } if (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_UNPAUSED, SHARED_PAUSED_PASSIVE_UNPAUSED) == SHARED_PAUSED_PASSIVE_UNPAUSED) { int i; KdPrint((__DRIVER_NAME " scsiport unpaused\n")); xsdd->scsiport_paused = FALSE; for (i = 0; i < 8; i++) { if (xsdd->bus_changes[i]) { KdPrint((__DRIVER_NAME " Sending BusChangeDetected for channel %d\n", i)); ScsiPortNotification(BusChangeDetected, DeviceExtension, i); } } ScsiPortNotification(NextRequest, DeviceExtension); } if (xsdd->scsiport_paused) /* check more often if we are paused */ ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 100 * 1000); /* 100ms second from the last check */ else ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 1 * 1000 * 1000); /* 1 second from the last check */ //FUNCTION_EXIT(); }
LONG ImScsiCompletePendingSrbs( __in pHW_HBA_EXT pHBAExt // Adapter device-object extension from port driver. ) { pMP_WorkRtnParms pWkRtnParms; LONG done = 0; KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs start. pHBAExt = 0x%p\n", pHBAExt)); for (;;) { PLIST_ENTRY request = ExInterlockedRemoveHeadList(&pMPDrvInfoGlobal->ResponseList, &pMPDrvInfoGlobal->ResponseListLock); if (request == NULL) { LONG was_pending = _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, -done); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs finished.\n")); return was_pending - done; } ++done; pWkRtnParms = (pMP_WorkRtnParms)CONTAINING_RECORD(request, MP_WorkRtnParms, ResponseListEntry); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs: Completing pWkRtnParms = 0x%p, pSrb = 0x%p\n", pWkRtnParms, pWkRtnParms->pSrb)); ScsiPortNotification(RequestComplete, pWkRtnParms->pHBAExt, pWkRtnParms->pSrb); ScsiPortNotification(NextRequest, pWkRtnParms->pHBAExt); ExFreePoolWithTag(pWkRtnParms, MP_TAG_GENERAL); // Free parm list. } }
BOOLEAN VirtIoInterrupt( IN PVOID DeviceExtension ) { pblk_req vbr; unsigned int len; PADAPTER_EXTENSION adaptExt; BOOLEAN isInterruptServiced = FALSE; PSCSI_REQUEST_BLOCK Srb; ULONG intReason = 0; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); intReason = VirtIODeviceISR((VirtIODevice*)DeviceExtension); if ( intReason == 1) { isInterruptServiced = TRUE; while((vbr = (pblk_req)adaptExt->vq->vq_ops->get_buf(adaptExt->vq, &len)) != NULL) { Srb = (PSCSI_REQUEST_BLOCK)vbr->req; if (Srb) { switch (vbr->status) { case VIRTIO_BLK_S_OK: Srb->SrbStatus = SRB_STATUS_SUCCESS; break; case VIRTIO_BLK_S_UNSUPP: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; break; default: Srb->SrbStatus = SRB_STATUS_ERROR; RhelDbgPrint(TRACE_LEVEL_ERROR, ("SRB_STATUS_ERROR\n")); break; } } if (vbr->out_hdr.type == VIRTIO_BLK_T_FLUSH) { #ifdef USE_STORPORT --adaptExt->in_fly; #endif CompleteSRB(DeviceExtension, Srb); } else if (vbr->out_hdr.type == VIRTIO_BLK_T_GET_ID) { adaptExt->sn_ok = TRUE; } else if (Srb) { #ifdef USE_STORPORT --adaptExt->in_fly; #endif CompleteDPC(DeviceExtension, vbr, 0); } } } else if (intReason == 3) { adaptExt->rescan_geometry = TRUE; ScsiPortNotification( BusChangeDetected, DeviceExtension, 0); isInterruptServiced = TRUE; } #ifdef USE_STORPORT if (adaptExt->in_fly > 0) { adaptExt->vq->vq_ops->kick(adaptExt->vq); } #endif RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s isInterruptServiced = %d\n", __FUNCTION__, isInterruptServiced)); return isInterruptServiced; }
VOID FORCEINLINE CompleteDPC( IN PVOID DeviceExtension, IN pblk_req vbr, IN ULONG MessageID ) { PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK)vbr->req; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; #ifndef USE_STORPORT PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; UNREFERENCED_PARAMETER( MessageID ); #endif RemoveEntryList(&vbr->list_entry); #ifdef USE_STORPORT if(!adaptExt->dump_mode && adaptExt->dpc_ok) { InsertTailList(&adaptExt->complete_list, &vbr->list_entry); StorPortIssueDpc(DeviceExtension, &adaptExt->completion_dpc, ULongToPtr(MessageID), NULL); return; } CompleteSRB(DeviceExtension, Srb); #else if (Srb->DataTransferLength > srbExt->Xfer) { Srb->DataTransferLength = srbExt->Xfer; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } ScsiPortNotification(RequestComplete, DeviceExtension, Srb); if(srbExt->call_next) { ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); } if (adaptExt->flush_state == FlushRequested) { adaptExt->flush_state = FlushInflight; RhelDoFlush(DeviceExtension); } #endif }
static void XenvbdFilterRequestPoll(VOID) { ScsiPortNotification(RequestTimerCall, XenvbdDeviceExtension, XenvbdTimerFunc, 10000); }
VOID CompleteSRB( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { ScsiPortNotification(RequestComplete, DeviceExtension, Srb); #ifndef USE_STORPORT ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); #endif }
LONG ImScsiCompletePendingSrbs( __in pHW_HBA_EXT pHBAExt, // Adapter device-object extension from port driver. __inout __deref PKIRQL LowestAssumedIrql ) { pMP_WorkRtnParms pWkRtnParms; LONG done = 0; KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs start. pHBAExt = 0x%p\n", pHBAExt)); for (;;) { KLOCK_QUEUE_HANDLE lock_handle; PLIST_ENTRY request; ImScsiAcquireLock(&pMPDrvInfoGlobal->ResponseListLock, &lock_handle, *LowestAssumedIrql); request = RemoveHeadList(&pMPDrvInfoGlobal->ResponseList); if (request == &pMPDrvInfoGlobal->ResponseList) { request = NULL; } ImScsiReleaseLock(&lock_handle, LowestAssumedIrql); if (request == NULL) { LONG was_pending = _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, -done); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs finished.\n")); return was_pending - done; } ++done; pWkRtnParms = (pMP_WorkRtnParms)CONTAINING_RECORD(request, MP_WorkRtnParms, ResponseListEntry); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs: Completing pWkRtnParms = 0x%p, pSrb = 0x%p\n", pWkRtnParms, pWkRtnParms->pSrb)); ScsiPortNotification(RequestComplete, pWkRtnParms->pHBAExt, pWkRtnParms->pSrb); ScsiPortNotification(NextRequest, pWkRtnParms->pHBAExt); ExFreePoolWithTag(pWkRtnParms, MP_TAG_GENERAL); // Free parm list. } }
void HATimer (IN PVOID HAObject) { TRACE(6, ("HATimer(): Timer entered\n")); ((ADAPTER_PTR)HAObject)->Service(HA_TIMER, (ADAPTER_PTR)HAObject, 0l); ScsiPortNotification(RequestTimerCall, HAObject, HATimer, HAPollTime); }
void Notify (ADAPTER_PTR HA, IO_REQ_PTR Req) { if (ReqState(Req).InternalRequest) (*(ReqPost(Req)))(Req); else ScsiPortNotification(RequestComplete, HA, Req); }
static BOOLEAN XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId) { UNREFERENCED_PARAMETER(DeviceExtension); UNREFERENCED_PARAMETER(PathId); FUNCTION_ENTER(); KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql())); ScsiPortNotification(NextRequest, DeviceExtension); FUNCTION_EXIT(); return TRUE; }
static BOOLEAN XenScsi_HwScsiInitialize(PVOID DeviceExtension) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; UNREFERENCED_PARAMETER(DeviceExtension); FUNCTION_ENTER(); xsdd->shared_paused = SHARED_PAUSED_SCSIPORT_UNPAUSED; ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 1 * 1000 * 1000); /* 1 second */ FUNCTION_EXIT(); return TRUE; }
BOOLEAN HAInit (PVOID HAObject) { ADAPTER_PTR HA = HAObject; TRACE(3, ("HAInit(): \n")); HA->Ext->InternalRequest.Length = sizeof(HA->Ext->InternalRequest); HA->Ext->InternalRequest.SrbExtension = &(HA->Ext->IntlReqExtension); ReqCommand(&(HA->Ext->InternalRequest)) = SRB_FUNCTION_EXECUTE_SCSI; // internally generated command ReqAdapterPtr(&HA->Ext->InternalRequest) = HA; ReqState(&(HA->Ext->InternalRequest)).InternalRequest = 1; ((ADAPTER_PTR)HAObject)->Service(HA_INITIALIZE, (ADAPTER_PTR)HAObject, 0l); ScsiPortNotification(RequestTimerCall, HAObject, HATimer, HAPollTime); return TRUE; }
VOID MpHwTimer( __in pHW_HBA_EXT pHBAExt ) { ULONG wait = 40000; LONG pending; KdPrint2(("PhDskMnt::MpHwTimer start. pHBAExt = 0x%p\n", pHBAExt)); pending = ImScsiCompletePendingSrbs(pHBAExt); if (pending > 0) { KdPrint2(("PhDskMnt::MpHwTimer finished, %i items pending, restarting in %u µs.\n", pending, wait)); ScsiPortNotification(RequestTimerCall, pHBAExt, MpHwTimer, wait); } else KdPrint2(("PhDskMnt::MpHwTimer finished, nothing left to do.\n")); }
void APINotifyReset (ADAPTER_PTR HA) { TRACE(0, ("APINotifyReset():\n")); ScsiPortNotification(ResetDetected, HA); }
BOOLEAN MpHwStartIo( __in PVOID DeviceExtension, // Adapter device-object extension from port driver. __inout __deref PSCSI_REQUEST_BLOCK pSrb ) { KIRQL lowest_assumed_irql = PASSIVE_LEVEL; ResultType Result = ResultDone; pHW_HBA_EXT pHBAExt = (pHW_HBA_EXT)DeviceExtension; #ifdef USE_SCSIPORT UCHAR PathId = pSrb->PathId; UCHAR TargetId = pSrb->TargetId; UCHAR Lun = pSrb->Lun; #endif KdPrint2(("PhDskMnt::MpHwStartIo: pHBAExt = 0x%p, pSrb = 0x%p, Path=%i, Target=%i, Lun=%i, IRQL=%i\n", pHBAExt, pSrb, (int)pSrb->PathId, (int)pSrb->TargetId, (int)pSrb->Lun, KeGetCurrentIrql())); pSrb->SrbStatus = SRB_STATUS_PENDING; pSrb->ScsiStatus = SCSISTAT_GOOD; ImScsiCompletePendingSrbs(pHBAExt, &lowest_assumed_irql); _InterlockedExchangeAdd((volatile LONG *)&pHBAExt->SRBsSeen, 1); // Bump count of SRBs encountered. // Next, if true, will cause port driver to remove the associated LUNs if, for example, devmgmt.msc is asked "scan for hardware changes." //if (pHBAExt->bDontReport) //{ // Act as though the HBA/path is gone? // pSrb->SrbStatus = SRB_STATUS_NO_DEVICE; // goto done; //} switch (pSrb->Function) { case SRB_FUNCTION_IO_CONTROL: ScsiIoControl(pHBAExt, pSrb, &Result, &lowest_assumed_irql); break; case SRB_FUNCTION_EXECUTE_SCSI: if (pSrb->Cdb[0] == SCSIOP_REPORT_LUNS) { ScsiOpReportLuns(pHBAExt, pSrb, &lowest_assumed_irql); } else { ScsiExecute(pHBAExt, pSrb, &Result, &lowest_assumed_irql); } break; case SRB_FUNCTION_RESET_LOGICAL_UNIT: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_LOGICAL_UNIT.\n"); pSrb->SrbStatus = ScsiResetLun(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_DEVICE: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_DEVICE.\n"); pSrb->SrbStatus = ScsiResetDevice(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_BUS: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_BUS.\n"); pSrb->SrbStatus = MpHwResetBus(pHBAExt, pSrb->PathId); break; case SRB_FUNCTION_PNP: ScsiPnP(pHBAExt, (PSCSI_PNP_REQUEST_BLOCK)pSrb, &lowest_assumed_irql); break; case SRB_FUNCTION_POWER: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_POWER.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; case SRB_FUNCTION_SHUTDOWN: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_SHUTDOWN.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; default: KdPrint(("PhDskMnt::MpHwStartIo: Unknown pSrb Function = 0x%X\n", pSrb->Function)); //StorPortLogError(pHBAExt, pSrb, pSrb->PathId, pSrb->TargetId, pSrb->Lun, SP_PROTOCOL_ERROR, 0x0200 | pSrb->Cdb[0]); ScsiSetCheckCondition(pSrb, SRB_STATUS_ERROR, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_ILLEGAL_COMMAND, 0); break; } // switch (pSrb->Function) if (Result == ResultDone) { // Complete now? #ifdef USE_SCSIPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete', 'NextRequest' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestComplete, pHBAExt, pSrb); ScsiPortNotification(NextRequest, pHBAExt); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif #ifdef USE_STORPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete' to port StorPort.\n")); StorPortNotification(RequestComplete, pHBAExt, pSrb); #endif } else { #ifdef USE_SCSIPORT _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, 1); KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestTimerCall' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestTimerCall, pHBAExt, MpHwTimer, (ULONG)1); ScsiPortNotification(NextLuRequest, pHBAExt, PathId, TargetId, Lun); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif } KdPrint2(("PhDskMnt::MpHwStartIo End.\n")); return TRUE; } // End MpHwStartIo().
VOID MiniTimer( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { BOOLEAN BusChanged; MiniCounter ++; BusChanged = FALSE; do { PLIST_ENTRY listEntry; PCCB ccb; PSCSI_REQUEST_BLOCK srb; // Get Completed CCB listEntry = ExInterlockedRemoveHeadList( &HwDeviceExtension->CcbCompletionList, &HwDeviceExtension->CcbCompletionListSpinLock ); if(listEntry == NULL) break; ccb = CONTAINING_RECORD(listEntry, CCB, ListEntry); srb = ccb->Srb; ASSERT(srb); ASSERT(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_TIMER_COMPLETE)); KDPrint(1,("completed SRB:%p SCSIOP:%x\n", srb, srb->Cdb[0])); if(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED)) { BusChanged = TRUE; } // // Free a CCB // LSCcbPostCompleteCcb(ccb); ScsiPortNotification( RequestComplete, HwDeviceExtension, srb ); InterlockedDecrement(&HwDeviceExtension->RequestExecuting); } while(1); if(BusChanged) { KDPrint(1,("Bus change detected. RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); ScsiPortNotification( BusChangeDetected, HwDeviceExtension, NULL ); } if((MiniCounter % 1000) == 0) KDPrint(4,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); if(HwDeviceExtension->RequestExecuting != 0) { ScsiPortNotification( RequestTimerCall, HwDeviceExtension, MiniTimer, 1 ); } else { HwDeviceExtension->TimerOn = FALSE; if(ADAPTER_ISSTATUS(HwDeviceExtension,ADAPTER_STATUS_RUNNING)) ScsiPortNotification( RequestTimerCall, HwDeviceExtension, MiniTimer, 1 //1000 ); } ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); return; }
BOOLEAN BT958WmiSrb( IN PHW_DEVICE_EXTENSION HwDeviceExtension, IN OUT PSCSI_WMI_REQUEST_BLOCK Srb ) /*++ Routine Description: Process an SRB_FUNCTION_WMI request packet. This routine is called from the SCSI port driver synchronized with the kernel via BT958StartIo. On completion of WMI processing, the SCSI port driver is notified that the adapter can take another request, if any are available. Arguments: HwDeviceExtension - HBA miniport driver's adapter data storage. Srb - IO request packet. Return Value: Value to return to BT958StartIo caller. Always TRUE. --*/ { UCHAR status; SCSIWMI_REQUEST_CONTEXT requestContext; ULONG retSize; BOOLEAN pending; // Validate our assumptions. ASSERT(Srb->Function == SRB_FUNCTION_WMI); ASSERT(Srb->Length == sizeof(SCSI_WMI_REQUEST_BLOCK)); ASSERT(Srb->DataTransferLength >= sizeof(ULONG)); ASSERT(Srb->DataBuffer); // Check if the WMI SRB is targeted for the adapter or one of the disks if (!(Srb->WMIFlags & SRB_WMI_FLAGS_ADAPTER_REQUEST)) { // This is targeted to one of the disks, since there are no per disk // wmi information we return an error. Note that if there was per // disk information, then you'd likely have a differen WmiLibContext // and a different set of guids. Srb->DataTransferLength = 0; Srb->SrbStatus = SRB_STATUS_SUCCESS; } else { // Process the incoming WMI request. pending = ScsiPortWmiDispatchFunction(&HwDeviceExtension->WmiLibContext, Srb->WMISubFunction, HwDeviceExtension, &requestContext, Srb->DataPath, Srb->DataTransferLength, Srb->DataBuffer); // We assume that the wmi request will never pend so that we can // allocate the requestContext from stack. If the WMI request could // ever pend then we'd need to allocate the request context from // the SRB extension. // ASSERT(! pending); retSize = ScsiPortWmiGetReturnSize(&requestContext); status = ScsiPortWmiGetReturnStatus(&requestContext); // We can do this since we assume it is done synchronously Srb->DataTransferLength = retSize; // // Adapter ready for next request. // Srb->SrbStatus = status; } ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); return TRUE; }
BOOLEAN RhelDoReadWrite(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { PCDB cdb; ULONG fragLen; ULONG sgElement; ULONG BytesLeft; PVOID DataBuffer; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; int num_free; PVOID va; ULONGLONG pa; ULONG i; ULONG sgMaxElements; cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; BytesLeft= Srb->DataTransferLength; DataBuffer = Srb->DataBuffer; memset(srbExt, 0, sizeof (RHEL_SRB_EXTENSION)); sgMaxElements = MAX_PHYS_SEGMENTS + 1; for (i = 0, sgElement = 1; (i < sgMaxElements) && BytesLeft; i++, sgElement++) { srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, Srb, DataBuffer, &fragLen); srbExt->vbr.sg[sgElement].ulSize = fragLen; srbExt->Xfer += fragLen; BytesLeft -= fragLen; DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + fragLen); } srbExt->vbr.out_hdr.sector = RhelGetLba(DeviceExtension, cdb); srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (struct request *)Srb; if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_OUT; srbExt->out = sgElement; srbExt->in = 1; } else { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_IN; srbExt->out = 1; srbExt->in = sgElement; } srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen); srbExt->vbr.sg[0].ulSize = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen); srbExt->vbr.sg[sgElement].ulSize = sizeof(srbExt->vbr.status); SET_VA_PA(); num_free = adaptExt->vq->vq_ops->add_buf(adaptExt->vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, &srbExt->vbr, va, pa); if ( num_free >= 0) { InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); adaptExt->vq->vq_ops->kick(adaptExt->vq); srbExt->call_next = FALSE; if(!adaptExt->indirect && num_free < VIRTIO_MAX_SG) { srbExt->call_next = TRUE; } else { ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); } } return TRUE; }
BOOLEAN StartIO (IN PVOID HAObject, IN PSCSI_REQUEST_BLOCK Req) { ADAPTER_PTR HA = HAObject; DEVICE_PTR DevP; int i; TRACE(2, ("StartIO(): Req @%x, Function = 0x%x, Req->SrbExtension @%x\n", Req, Req->Function, Req->SrbExtension)); switch (Req->Function) { case SRB_FUNCTION_EXECUTE_SCSI: ReqNext(Req) = (IO_REQ_PTR)NILL; ReqAdapterPtr(Req) = HA; for (i=0; i < sizeof(ReqState(Req)); i++) ((U8 *)&ReqState(Req))[i] = 0; ReqState(Req).ReqType = RTNormalReq; if ( (DevP = ScsiPortGetLogicalUnit(HA, Req->PathId, ReqTargetID(Req), ReqTargetLUN(Req))) == NILL) { TRACE(3, ("ExecuteReq(): Unable to get device info\n")); Req->SrbStatus = SRB_STATUS_NO_DEVICE; return FALSE; } ReqDevP(Req) = DevP; if (!DevP->Flags.Initialized) QueueInternalRequest(HA, Req, RTGetInfoReq); else IExecuteReq(HA, DevP, Req, NORMAL_REQ); break; case SRB_FUNCTION_RESET_BUS: TRACE(3, ("StartIO(): RESET_BUS command\n")); ResetBus(HAObject, Req->PathId); break; case SRB_FUNCTION_RESET_DEVICE: case SRB_FUNCTION_TERMINATE_IO: case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_SHUTDOWN: Req->SrbStatus = SRB_STATUS_SUCCESS; ScsiPortNotification(RequestComplete, HA, Req); break; case SRB_FUNCTION_ABORT_COMMAND: TRACE(0, ("StartIO(): Request at %x to abort request %x\n", Req, Req->NextSrb)); if ((DevP = ScsiPortGetLogicalUnit(HA, Req->PathId, ReqTargetID(Req), ReqTargetLUN(Req))) == NILL || (DevP->Flags.Initialized == 0) || !AbortRequest(HA, DevP, Req->NextSrb) ) { TRACE(0, ("StartIO(): Abort operation failed\n")); Req->SrbStatus = SRB_STATUS_ABORT_FAILED; } else { TRACE(0, ("StartIO(): Abort operation success\n")); Req->SrbStatus = SRB_STATUS_SUCCESS; } ScsiPortNotification(RequestComplete, HA, Req); break; case SRB_FUNCTION_RELEASE_RECOVERY: case SRB_FUNCTION_RECEIVE_EVENT: case SRB_FUNCTION_IO_CONTROL: default: TRACE(0, ("StartIO(): Unsupported command: 0x%x\n", Req->Function)); APISetStatus(Req, S_REQ_OPCODE, Terminal, NotSenseable); return FALSE; break; } ScsiPortNotification(NextLuRequest, HA, Req->PathId, Req->TargetId, Req->Lun); return TRUE; }
VOID ScsiPortCompleteRequest( IN PVOID HwDeviceExtension, IN UCHAR PathId, IN UCHAR TargetId, IN UCHAR Lun, IN UCHAR SrbStatus ) /*++ Routine Description: Complete all active requests for the specified logical unit. Arguments: DeviceExtenson - Supplies the HBA miniport driver's adapter data storage. TargetId, Lun and PathId - specify device address on a SCSI bus. SrbStatus - Status to be returned in each completed SRB. Return Value: None. --*/ { PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension); ULONG binNumber; for (binNumber = 0; binNumber < NUMBER_LOGICAL_UNIT_BINS; binNumber++) { PLOGICAL_UNIT_BIN bin = &deviceExtension->LogicalUnitList[binNumber]; PLOGICAL_UNIT_EXTENSION logicalUnit; ULONG limit = 0; logicalUnit = bin->List; DebugPrint((2, "ScsiPortCompleteRequest: Completing requests in " "bin %d [%#p]\n", binNumber, bin)); for(logicalUnit = bin->List; logicalUnit != NULL; logicalUnit = logicalUnit->NextLogicalUnit) { PLIST_ENTRY entry; ASSERT(limit++ < 1000); // // See if this logical unit matches the pattern. Check for -1 // first since this seems to be the most popular way to complete // requests. // if (((PathId == SP_UNTAGGED) || (PathId == logicalUnit->PathId)) && ((TargetId == SP_UNTAGGED) || (TargetId == logicalUnit->TargetId)) && ((Lun == SP_UNTAGGED) || (Lun == logicalUnit->Lun))) { // // Complete any pending abort reqeusts. // if (logicalUnit->AbortSrb != NULL) { logicalUnit->AbortSrb->SrbStatus = SrbStatus; ScsiPortNotification( RequestComplete, HwDeviceExtension, logicalUnit->AbortSrb ); } if(logicalUnit->CurrentUntaggedRequest != NULL) { SpCompleteSrb(deviceExtension, logicalUnit->CurrentUntaggedRequest, SrbStatus); } // // Complete each of the requests in the queue. // entry = logicalUnit->RequestList.Flink; while (entry != &logicalUnit->RequestList) { PSRB_DATA srbData; ASSERT(limit++ < 1000); srbData = CONTAINING_RECORD(entry, SRB_DATA, RequestList); SpCompleteSrb(deviceExtension, srbData, SrbStatus); entry = srbData->RequestList.Flink; } } } } return; } // end ScsiPortCompleteRequest()
static BOOLEAN XenScsi_HwScsiInterrupt(PVOID DeviceExtension) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; PSCSI_REQUEST_BLOCK Srb; RING_IDX i, rp; int j; vscsiif_response_t *rep; int more_to_do = TRUE; vscsiif_shadow_t *shadow; BOOLEAN last_interrupt = FALSE; XenScsi_CheckNewDevice(DeviceExtension); if (!dump_mode && !xsdd->vectors.EvtChn_AckEvent(xsdd->vectors.context, xsdd->event_channel, &last_interrupt)) { return FALSE; } //FUNCTION_ENTER(); while (more_to_do) { rp = xsdd->ring.sring->rsp_prod; KeMemoryBarrier(); for (i = xsdd->ring.rsp_cons; i != rp; i++) { rep = RING_GET_RESPONSE(&xsdd->ring, i); shadow = &xsdd->shadows[rep->rqid]; Srb = shadow->Srb; Srb->ScsiStatus = (UCHAR)rep->rslt; memset(Srb->SenseInfoBuffer, 0, Srb->SenseInfoBufferLength); if (rep->sense_len > 0 && Srb->SenseInfoBuffer != NULL) { memcpy(Srb->SenseInfoBuffer, rep->sense_buffer, min(Srb->SenseInfoBufferLength, rep->sense_len)); } switch(rep->rslt) { case 0: //KdPrint((__DRIVER_NAME " Xen Operation complete - result = 0x%08x, sense_len = %d, residual = %d\n", rep->rslt, rep->sense_len, rep->residual_len)); Srb->SrbStatus = SRB_STATUS_SUCCESS; if (Srb->Cdb[0] == 0x03) { KdPrint((__DRIVER_NAME " REQUEST_SENSE DataTransferLength = %d, residual = %d\n", Srb->DataTransferLength, rep->residual_len)); //for (j = 0; j < Srb->DataTransferLength - rep->residual_len; j++) // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->DataBuffer)[j])); } break; case 0x00010000: /* Device does not exist */ KdPrint((__DRIVER_NAME " Xen Operation error - cdb[0] = %02x, result = 0x%08x, sense_len = %d, residual = %d\n", (ULONG)Srb->Cdb[0], rep->rslt, rep->sense_len, rep->residual_len)); Srb->SrbStatus = SRB_STATUS_NO_DEVICE; break; default: KdPrint((__DRIVER_NAME " Xen Operation error - cdb[0] = %02x, result = 0x%08x, sense_len = %d, residual = %d\n", (ULONG)Srb->Cdb[0], rep->rslt, rep->sense_len, rep->residual_len)); Srb->SrbStatus = SRB_STATUS_ERROR; //for (j = 0; j < Srb->SenseInfoBufferLength; j++) // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->SenseInfoBuffer)[j])); if (rep->sense_len > 0 && !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) && Srb->SenseInfoBuffer != NULL) { KdPrint((__DRIVER_NAME " Doing autosense\n")); Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; } else if (Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) { PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); KdPrint((__DRIVER_NAME " Autosense disabled\n")); if (lud != NULL) { KdPrint((__DRIVER_NAME " Saving sense data\n")); lud->sense_len = rep->sense_len; memcpy(lud->sense_buffer, Srb->SenseInfoBuffer, lud->sense_len); } } } /* work around a bug in scsiback that gives an incorrect result to REPORT_LUNS - fail it if the output is only 8 bytes */ if (Srb->Cdb[0] == 0xa0 && Srb->SrbStatus == SRB_STATUS_SUCCESS && Srb->DataTransferLength - rep->residual_len == 8) { /* SRB_STATUS_ERROR appears to be sufficient here - no need to worry about sense data or anything */ KdPrint((__DRIVER_NAME " Worked around bad REPORT_LUNS emulation for %d:%d:%d\n", Srb->PathId, Srb->TargetId, Srb->Lun)); Srb->SrbStatus = SRB_STATUS_ERROR; } //remaining = Srb->DataTransferLength; for (j = 0; j < shadow->req.nr_segments; j++) { xsdd->vectors.GntTbl_EndAccess(xsdd->vectors.context, shadow->req.seg[j].gref, TRUE, (ULONG)'SCSI'); put_grant_on_freelist(xsdd, shadow->req.seg[j].gref); shadow->req.seg[j].gref = 0; } if (Srb->SrbStatus == SRB_STATUS_SUCCESS && rep->residual_len) { // KdPrint((__DRIVER_NAME " SRB_STATUS_DATA_OVERRUN DataTransferLength = %d, adjusted = %d\n", // Srb->DataTransferLength, Srb->DataTransferLength - rep->residual_len)); Srb->DataTransferLength -= rep->residual_len; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } put_shadow_on_freelist(xsdd, shadow); ScsiPortNotification(RequestComplete, xsdd, Srb); if (!xsdd->scsiport_paused) ScsiPortNotification(NextRequest, DeviceExtension); } xsdd->ring.rsp_cons = i; if (i != xsdd->ring.req_prod_pvt) { RING_FINAL_CHECK_FOR_RESPONSES(&xsdd->ring, more_to_do); } else { xsdd->ring.sring->rsp_event = i + 1; more_to_do = FALSE; } } //FUNCTION_EXIT(); return last_interrupt; }
static BOOLEAN XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; scsi_dev_t *dev; //FUNCTION_ENTER(); XenScsi_CheckNewDevice(DeviceExtension); if (xsdd->scsiport_paused) { KdPrint((__DRIVER_NAME " Busy\n")); Srb->SrbStatus = SRB_STATUS_BUSY; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); //FUNCTION_EXIT(); return TRUE; } for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink; dev != (scsi_dev_t *)&xsdd->dev_list_head; dev = (scsi_dev_t * )dev->entry.Flink) { if (dev->channel == Srb->PathId && dev->id == Srb->TargetId && dev->lun == Srb->Lun) break; } if (dev == (scsi_dev_t *)&xsdd->dev_list_head) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); //KdPrint((__DRIVER_NAME " Out of bounds\n")); ScsiPortNotification(NextRequest, DeviceExtension); //FUNCTION_EXIT(); return TRUE; } switch (Srb->Function) { case SRB_FUNCTION_EXECUTE_SCSI: switch (Srb->Cdb[0]) { case 0x03: { /* REQUEST_SENSE*/ /* but what about when we allow multiple requests per lu? */ PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); if (lud != NULL && lud->sense_len) { int i; KdPrint((__DRIVER_NAME " Emulating REQUEST_SENSE (lu data = %p)\n", lud)); memcpy(Srb->DataBuffer, lud->sense_buffer, min(lud->sense_len, Srb->DataTransferLength)); if (lud->sense_len > Srb->DataTransferLength) { KdPrint((__DRIVER_NAME " Sense overrun Srb->DataTransferLength = %d, lud->sense_len = %d\n", Srb->DataTransferLength, lud->sense_len)); Srb->DataTransferLength = lud->sense_len; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } else { Srb->SrbStatus = SRB_STATUS_SUCCESS; } for (i = 0; i < min(lud->sense_len, 8); i++) KdPrint((__DRIVER_NAME " sense %02x: %02x\n", i, (ULONG)((PUCHAR)lud->sense_buffer)[i])); lud->sense_len = 0; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; } else { KdPrint((__DRIVER_NAME " Issuing REQUEST_SENSE (lud = %p)\n", lud)); } // fall through } default: XenScsi_PutSrbOnRing(xsdd, Srb); Srb->SrbStatus = SRB_STATUS_PENDING; break; } break; case SRB_FUNCTION_IO_CONTROL: KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; case SRB_FUNCTION_FLUSH: KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; default: KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function)); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; } //FUNCTION_EXIT(); return TRUE; }
VOID CompleteDpcRoutine( IN PSTOR_DPC Dpc, IN PVOID Context, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) { STOR_LOCK_HANDLE LockHandle; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)Context; #ifdef MSI_SUPPORTED ULONG MessageID = PtrToUlong(SystemArgument1); ULONG OldIrql; #endif #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); } else { #endif StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); #ifdef MSI_SUPPORTED } #endif while (!IsListEmpty(&adaptExt->complete_list)) { PSCSI_REQUEST_BLOCK Srb; PRHEL_SRB_EXTENSION srbExt; pblk_req vbr; vbr = (pblk_req) RemoveHeadList(&adaptExt->complete_list); Srb = (PSCSI_REQUEST_BLOCK)vbr->req; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); } else { #endif StorPortReleaseSpinLock (Context, &LockHandle); #ifdef MSI_SUPPORTED } #endif if (Srb->DataTransferLength > srbExt->Xfer) { Srb->DataTransferLength = srbExt->Xfer; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } ScsiPortNotification(RequestComplete, Context, Srb); #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); } else { #endif StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); #ifdef MSI_SUPPORTED } #endif } #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); } else { #endif StorPortReleaseSpinLock (Context, &LockHandle); #ifdef MSI_SUPPORTED } #endif return; }
BOOLEAN VirtIoBuildIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb; ULONG i; ULONG dummy; ULONG sgElement; ULONG sgMaxElements; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; PSTOR_SCATTER_GATHER_LIST sgList; cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; if(Srb->PathId || Srb->TargetId || Srb->Lun) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); return FALSE; } switch (cdb->CDB6GENERIC.OperationCode) { case SCSIOP_READ: case SCSIOP_WRITE: case SCSIOP_WRITE_VERIFY: case SCSIOP_READ6: case SCSIOP_WRITE6: case SCSIOP_READ12: case SCSIOP_WRITE12: case SCSIOP_WRITE_VERIFY12: case SCSIOP_READ16: case SCSIOP_WRITE16: case SCSIOP_WRITE_VERIFY16: { break; } default: { Srb->SrbStatus = SRB_STATUS_SUCCESS; return TRUE; } } sgList = StorPortGetScatterGatherList(DeviceExtension, Srb); sgMaxElements = min((MAX_PHYS_SEGMENTS + 1), sgList->NumberOfElements); srbExt->Xfer = 0; for (i = 0, sgElement = 1; i < sgMaxElements; i++, sgElement++) { srbExt->vbr.sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->vbr.sg[sgElement].ulSize = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } srbExt->vbr.out_hdr.sector = RhelGetLba(DeviceExtension, cdb); srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (PVOID)Srb; srbExt->fua = (cdb->CDB10.ForceUnitAccess == 1); if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_OUT; srbExt->out = sgElement; srbExt->in = 1; } else { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_IN; srbExt->out = 1; srbExt->in = sgElement; } srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &dummy); srbExt->vbr.sg[0].ulSize = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &dummy); srbExt->vbr.sg[sgElement].ulSize = sizeof(srbExt->vbr.status); return TRUE; }
BOOLEAN MpHwStartIo( __in pHW_HBA_EXT pHBAExt, // Adapter device-object extension from port driver. __in __out PSCSI_REQUEST_BLOCK pSrb ) { UCHAR Result = ResultDone; #ifdef USE_SCSIPORT UCHAR PathId = pSrb->PathId; UCHAR TargetId = pSrb->TargetId; UCHAR Lun = pSrb->Lun; #endif KdPrint2(("PhDskMnt::MpHwStartIo: pHBAExt = 0x%p, pSrb = 0x%p, Path=%i, Target=%i, Lun=%i, IRQL=%i\n", pHBAExt, pSrb, (int) pSrb->PathId, (int) pSrb->TargetId, (int) pSrb->Lun, KeGetCurrentIrql())); pSrb->SrbStatus = SRB_STATUS_PENDING; pSrb->ScsiStatus = SCSISTAT_GOOD; ImScsiCompletePendingSrbs(pHBAExt); _InterlockedExchangeAdd((volatile LONG *)&pHBAExt->SRBsSeen, 1); // Bump count of SRBs encountered. // Next, if true, will cause port driver to remove the associated LUNs if, for example, devmgmt.msc is asked "scan for hardware changes." //if (pHBAExt->bDontReport) //{ // Act as though the HBA/path is gone? // pSrb->SrbStatus = SRB_STATUS_INVALID_LUN; // goto done; //} switch (pSrb->Function) { case SRB_FUNCTION_IO_CONTROL: ScsiIoControl(pHBAExt, pSrb, &Result); break; case SRB_FUNCTION_EXECUTE_SCSI: ScsiExecute(pHBAExt, pSrb, &Result); break; case SRB_FUNCTION_RESET_LOGICAL_UNIT: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_LOGICAL_UNIT.\n"); pSrb->SrbStatus = ScsiResetLun(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_DEVICE: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_DEVICE.\n"); pSrb->SrbStatus = ScsiResetDevice(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_BUS: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_BUS.\n"); pSrb->SrbStatus = MpHwResetBus(pHBAExt, pSrb->PathId); break; case SRB_FUNCTION_PNP: MpHwHandlePnP(pHBAExt, (PSCSI_PNP_REQUEST_BLOCK)pSrb); break; case SRB_FUNCTION_POWER: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_POWER.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; case SRB_FUNCTION_SHUTDOWN: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_SHUTDOWN.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; default: KdPrint(("PhDskMnt::MpHwStartIo: Unknown pSrb Function = 0x%x\n", pSrb->Function)); ScsiSetCheckCondition(pSrb, SRB_STATUS_ERROR, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_ILLEGAL_COMMAND, 0); break; } // switch (pSrb->Function) if (Result == ResultDone) { // Complete now? // Note: A miniport with real hardware would not always be calling RequestComplete from HwScsiStartIo. Rather, // the miniport would typically be doing real I/O and would call RequestComplete only at the end of that // real I/O, in its HwScsiInterrupt or in a DPC routine. #ifdef USE_SCSIPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete', 'NextRequest' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestComplete, pHBAExt, pSrb); ScsiPortNotification(NextRequest, pHBAExt); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif #ifdef USE_STORPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete' to port StorPort.\n")); StorPortNotification(RequestComplete, pHBAExt, pSrb); #endif } else { #ifdef USE_SCSIPORT _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, 1); KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestTimerCall' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestTimerCall, pHBAExt, MpHwTimer, (ULONG) 1); ScsiPortNotification(NextLuRequest, pHBAExt, PathId, TargetId, Lun); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif } KdPrint2(("PhDskMnt::MpHwStartIo End.\n")); return TRUE; } // End MpHwStartIo().
BOOLEAN VirtIoBuildIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb; ULONG i; ULONG dummy; ULONG sgElement; ULONG sgMaxElements; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; PSTOR_SCATTER_GATHER_LIST sgList; ULONGLONG lba; ULONG blocks; cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; if(Srb->PathId || Srb->TargetId || Srb->Lun) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); return FALSE; } switch (cdb->CDB6GENERIC.OperationCode) { case SCSIOP_READ: case SCSIOP_WRITE: case SCSIOP_WRITE_VERIFY: case SCSIOP_READ6: case SCSIOP_WRITE6: case SCSIOP_READ12: case SCSIOP_WRITE12: case SCSIOP_WRITE_VERIFY12: case SCSIOP_READ16: case SCSIOP_WRITE16: case SCSIOP_WRITE_VERIFY16: { break; } default: { Srb->SrbStatus = SRB_STATUS_SUCCESS; return TRUE; } } lba = RhelGetLba(DeviceExtension, cdb); blocks = (Srb->DataTransferLength + adaptExt->info.blk_size - 1) / adaptExt->info.blk_size; if (lba > adaptExt->lastLBA) { RhelDbgPrint(TRACE_LEVEL_ERROR, ("SRB_STATUS_BAD_SRB_BLOCK_LENGTH lba = %llu lastLBA= %llu\n", lba, adaptExt->lastLBA)); Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH; CompleteSRB(DeviceExtension, Srb); return FALSE; } if ((lba + blocks) > adaptExt->lastLBA) { blocks = (ULONG)(adaptExt->lastLBA + 1 - lba); RhelDbgPrint(TRACE_LEVEL_ERROR, ("lba = %llu lastLBA= %llu blocks = %lu\n", lba, adaptExt->lastLBA, blocks)); Srb->DataTransferLength = (ULONG)(blocks * adaptExt->info.blk_size); } sgList = StorPortGetScatterGatherList(DeviceExtension, Srb); sgMaxElements = min((MAX_PHYS_SEGMENTS + 1), sgList->NumberOfElements); srbExt->Xfer = 0; for (i = 0, sgElement = 1; i < sgMaxElements; i++, sgElement++) { srbExt->vbr.sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->vbr.sg[sgElement].length = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } srbExt->vbr.out_hdr.sector = lba; srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (PVOID)Srb; srbExt->fua = (cdb->CDB10.ForceUnitAccess == 1); if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_OUT; srbExt->out = sgElement; srbExt->in = 1; } else { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_IN; srbExt->out = 1; srbExt->in = sgElement; } srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &dummy); srbExt->vbr.sg[0].length = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &dummy); srbExt->vbr.sg[sgElement].length = sizeof(srbExt->vbr.status); return TRUE; }