BOOLEAN DeviceReset( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; PSCSI_REQUEST_BLOCK Srb = &adaptExt->tmf_cmd.Srb; PSRB_EXTENSION srbExt = adaptExt->tmf_cmd.SrbExtension; VirtIOSCSICmd *cmd = &srbExt->cmd; ULONG fragLen; ULONG sgElement; ENTER_FN(); if (adaptExt->dump_mode) { return TRUE; } ASSERT(adaptExt->tmf_infly == FALSE); Srb->SrbExtension = srbExt; RtlZeroMemory((PVOID)cmd, sizeof(VirtIOSCSICmd)); cmd->sc = Srb; cmd->req.tmf.lun[0] = 1; cmd->req.tmf.lun[1] = 0; cmd->req.tmf.lun[2] = 0; cmd->req.tmf.lun[3] = 0; cmd->req.tmf.type = VIRTIO_SCSI_T_TMF; cmd->req.tmf.subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET; sgElement = 0; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->req.tmf, &fragLen); srbExt->sg[sgElement].length = sizeof(cmd->req.tmf); sgElement++; srbExt->out = sgElement; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->resp.tmf, &fragLen); srbExt->sg[sgElement].length = sizeof(cmd->resp.tmf); sgElement++; srbExt->in = sgElement - srbExt->out; StorPortPause(DeviceExtension, 60); if (!SendTMF(DeviceExtension, Srb)) { StorPortResume(DeviceExtension); return FALSE; } adaptExt->tmf_infly = TRUE; return TRUE; }
BOOLEAN KickEvent( IN PVOID DeviceExtension, IN PVirtIOSCSIEventNode EventNode ) { PADAPTER_EXTENSION adaptExt; ULONG fragLen; ENTER_FN(); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RtlZeroMemory((PVOID)EventNode, sizeof(VirtIOSCSIEventNode)); EventNode->sg.physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &EventNode->event, &fragLen); EventNode->sg.length = sizeof(VirtIOSCSIEvent); return SynchronizedKickEventRoutine(DeviceExtension, (PVOID)EventNode); EXIT_FN(); }
static struct virtqueue *FindVirtualQueue(PADAPTER_EXTENSION adaptExt, ULONG index, ULONG vector) { struct virtqueue *vq = NULL; if (adaptExt->uncachedExtensionVa) { ULONG len; PVOID ptr = (PVOID)((ULONG_PTR)adaptExt->uncachedExtensionVa + adaptExt->offset[index]); PHYSICAL_ADDRESS pa = StorPortGetPhysicalAddress(adaptExt, NULL, ptr, &len); if (pa.QuadPart) { vq = VirtIODevicePrepareQueue(&adaptExt->vdev, index, pa, ptr, len, NULL, FALSE); } if (vq == NULL) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> cannot create virtual queue index = %d vector = % pa = %08I64X\n", __FUNCTION__, index, vector, pa.QuadPart)); return NULL; } if (vector) { unsigned res; StorPortWritePortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_QUEUE_VECTOR),(USHORT)vector); res = StorPortReadPortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_QUEUE_VECTOR)); RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> VIRTIO_MSI_QUEUE_VECTOR vector = %d, res = 0x%x\n", __FUNCTION__, vector, res)); if(res == VIRTIO_MSI_NO_VECTOR) { VirtIODeviceDeleteQueue(vq, NULL); vq = NULL; RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> Cannot create vq vector\n", __FUNCTION__)); return NULL; } StorPortWritePortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_CONFIG_VECTOR),(USHORT)vector); res = StorPortReadPortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_CONFIG_VECTOR)); if (res != vector) { VirtIODeviceDeleteQueue(vq, NULL); vq = NULL; RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> Cannot set config vector\n", __FUNCTION__)); return NULL; } } } return vq; }
static ULONGLONG mem_get_physical_address(void *context, void *virt) { ULONG uLength; STOR_PHYSICAL_ADDRESS pa = StorPortGetPhysicalAddress(context, NULL, virt, &uLength); return pa.QuadPart; }
BOOLEAN RhelDoFlush( PVOID DeviceExtension, PSRB_TYPE Srb, BOOLEAN resend, BOOLEAN bIsr ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; PSRB_EXTENSION srbExt = SRB_EXTENSION(Srb); ULONG fragLen = 0UL; PVOID va = NULL; ULONGLONG pa = 0ULL; ULONG QueueNumber = 0; ULONG OldIrql = 0; ULONG MessageId = 0; BOOLEAN result = FALSE; bool notify = FALSE; STOR_LOCK_HANDLE LockHandle = { 0 }; ULONG status = STOR_STATUS_SUCCESS; struct virtqueue *vq = NULL; SET_VA_PA(); if (resend) { MessageId = srbExt->MessageID; QueueNumber = MessageId - 1; } else if (adaptExt->num_queues > 1) { STARTIO_PERFORMANCE_PARAMETERS param; param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS); status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, ¶m); if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) { MessageId = param.MessageNumber; QueueNumber = MessageId - 1; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("%s srb %p, cpu %d :: QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n", __FUNCTION__, Srb, srbExt->cpu, QueueNumber, param.MessageNumber, param.ChannelNumber)); } else { RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortGetStartIoPerfParams failed. srb %p cpu %d status 0x%x.\n",__FUNCTION__, Srb, srbExt->cpu, status)); QueueNumber = 0; MessageId = 1; } } else { QueueNumber = 0; MessageId = 1; } srbExt->MessageID = MessageId; vq = adaptExt->vq[QueueNumber]; srbExt->vbr.out_hdr.sector = 0; srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (struct request *)Srb; srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; srbExt->out = 1; srbExt->in = 1; srbExt->vbr.sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen); srbExt->vbr.sg[0].length = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[1].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen); srbExt->vbr.sg[1].length = sizeof(srbExt->vbr.status); VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE); if (virtqueue_add_buf(vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, &srbExt->vbr, va, pa) >= 0) { notify = virtqueue_kick_prepare(vq); VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE); result = TRUE; #ifdef DBG InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt); #endif } else { VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE); RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s Can not add packet to queue %d.\n", __FUNCTION__, QueueNumber)); StorPortBusy(DeviceExtension, 2); } if (notify) { virtqueue_notify(vq); } return result; }
BOOLEAN VioScsiBuildIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb; ULONG i; ULONG fragLen; ULONG sgElement; ULONG sgMaxElements; PADAPTER_EXTENSION adaptExt; PSRB_EXTENSION srbExt; PSTOR_SCATTER_GATHER_LIST sgList; VirtIOSCSICmd *cmd; ENTER_FN(); cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PSRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; if( (Srb->PathId > 0) || (Srb->TargetId >= adaptExt->scsi_config.max_target) || (Srb->Lun >= adaptExt->scsi_config.max_lun) ) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; StorPortNotification(RequestComplete, DeviceExtension, Srb); return FALSE; } RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<-->%s (%d::%d::%d)\n", DbgGetScsiOpStr(Srb), Srb->PathId, Srb->TargetId, Srb->Lun)); memset(srbExt, 0, sizeof(*srbExt)); cmd = &srbExt->cmd; cmd->sc = Srb; cmd->req.cmd.lun[0] = 1; cmd->req.cmd.lun[1] = Srb->TargetId; cmd->req.cmd.lun[2] = 0; cmd->req.cmd.lun[3] = Srb->Lun; cmd->req.cmd.tag = (unsigned long)Srb; cmd->req.cmd.task_attr = VIRTIO_SCSI_S_SIMPLE; cmd->req.cmd.prio = 0; cmd->req.cmd.crn = 0; memcpy(cmd->req.cmd.cdb, cdb, min(VIRTIO_SCSI_CDB_SIZE, Srb->CdbLength)); sgElement = 0; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->req.cmd, &fragLen); srbExt->sg[sgElement].ulSize = sizeof(cmd->req.cmd); sgElement++; sgList = StorPortGetScatterGatherList(DeviceExtension, Srb); if (sgList) { sgMaxElements = sgList->NumberOfElements; if((Srb->SrbFlags & SRB_FLAGS_DATA_OUT) == SRB_FLAGS_DATA_OUT) { for (i = 0; i < sgMaxElements; i++, sgElement++) { srbExt->sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->sg[sgElement].ulSize = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } } } srbExt->out = sgElement; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->resp.cmd, &fragLen); srbExt->sg[sgElement].ulSize = sizeof(cmd->resp.cmd); sgElement++; if (sgList) { sgMaxElements = sgList->NumberOfElements; if((Srb->SrbFlags & SRB_FLAGS_DATA_OUT) != SRB_FLAGS_DATA_OUT) { for (i = 0; i < sgMaxElements; i++, sgElement++) { srbExt->sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->sg[sgElement].ulSize = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } } } srbExt->in = sgElement - srbExt->out; EXIT_FN(); return TRUE; }