Esempio n. 1
0
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();
}
Esempio n. 2
0
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
}
Esempio n. 5
0
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.
    }
}
Esempio n. 8
0
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);

}
Esempio n. 9
0
void
Notify (ADAPTER_PTR HA, IO_REQ_PTR Req)
{

  if (ReqState(Req).InternalRequest)
    (*(ReqPost(Req)))(Req);
  else
    ScsiPortNotification(RequestComplete, HA, Req);

}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;

}
Esempio n. 13
0
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"));
}
Esempio n. 14
0
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().
Esempio n. 16
0
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;
}
Esempio n. 17
0
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;
}
Esempio n. 19
0
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;

}
Esempio n. 20
0
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()
Esempio n. 21
0
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;
}
Esempio n. 22
0
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;
}
Esempio n. 25
0
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;
}