BOOLEAN VirtIoMSInterruptRoutine ( IN PVOID DeviceExtension, IN ULONG MessageID ) { pblk_req vbr; unsigned int len; PADAPTER_EXTENSION adaptExt; PSCSI_REQUEST_BLOCK Srb; BOOLEAN isInterruptServiced = FALSE; PRHEL_SRB_EXTENSION srbExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<--->%s : MessageID 0x%x\n", __FUNCTION__, MessageID)); if (MessageID == 0) { RhelGetDiskGeometry(DeviceExtension); return 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) { --adaptExt->in_fly; CompleteSRB(DeviceExtension, Srb); } else if (vbr->out_hdr.type == VIRTIO_BLK_T_GET_ID) { adaptExt->sn_ok = TRUE; } else if (Srb) { --adaptExt->in_fly; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; if (srbExt->fua == TRUE) { RemoveEntryList(&vbr->list_entry); Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb, FALSE)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } else { srbExt->fua = FALSE; } } else { CompleteDPC(DeviceExtension, vbr, MessageID); } } isInterruptServiced = TRUE; } if (adaptExt->in_fly > 0) { adaptExt->vq->vq_ops->kick(adaptExt->vq); } return isInterruptServiced; }
BOOLEAN VirtIoHwInitialize( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt; BOOLEAN ret = FALSE; #ifdef MSI_SUPPORTED MESSAGE_INTERRUPT_INFORMATION msi_info; #endif RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; adaptExt->msix_vectors = 0; #ifdef MSI_SUPPORTED while(StorPortGetMSIInfo(DeviceExtension, adaptExt->msix_vectors, &msi_info) == STOR_STATUS_SUCCESS) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageId = %x\n", msi_info.MessageId)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageData = %x\n", msi_info.MessageData)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptVector = %x\n", msi_info.InterruptVector)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptLevel = %x\n", msi_info.InterruptLevel)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptMode = %s\n", msi_info.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched")); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageAddress = %p\n\n", msi_info.MessageAddress)); ++adaptExt->msix_vectors; } if(!adaptExt->dump_mode && (adaptExt->msix_vectors > 1)) { adaptExt->vq = FindVirtualQueue(adaptExt, 0, adaptExt->msix_vectors - 1); } #endif if(!adaptExt->vq) { adaptExt->vq = FindVirtualQueue(adaptExt, 0, 0); } if (!adaptExt->vq) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find snd virtual queue\n")); VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_FAILED); return ret; } RhelGetDiskGeometry(DeviceExtension); memset(&adaptExt->inquiry_data, 0, sizeof(INQUIRYDATA)); adaptExt->inquiry_data.ANSIVersion = 4; adaptExt->inquiry_data.ResponseDataFormat = 2; adaptExt->inquiry_data.CommandQueue = 1; adaptExt->inquiry_data.DeviceType = DIRECT_ACCESS_DEVICE; adaptExt->inquiry_data.Wide32Bit = 1; adaptExt->inquiry_data.AdditionalLength = 91; ScsiPortMoveMemory(&adaptExt->inquiry_data.VendorId, "Red Hat ", sizeof("Red Hat ")); ScsiPortMoveMemory(&adaptExt->inquiry_data.ProductId, "VirtIO", sizeof("VirtIO")); ScsiPortMoveMemory(&adaptExt->inquiry_data.ProductRevisionLevel, "0001", sizeof("0001")); ScsiPortMoveMemory(&adaptExt->inquiry_data.VendorSpecific, "0001", sizeof("0001")); if(!adaptExt->dump_mode && !adaptExt->sn_ok) { RhelGetSerialNumber(DeviceExtension); } ret = TRUE; #ifdef USE_STORPORT if(!adaptExt->dump_mode && !adaptExt->dpc_ok) { ret = StorPortEnablePassiveInitialization(DeviceExtension, VirtIoPassiveInitializeRoutine); } #endif if (ret) { VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_DRIVER_OK); } else { VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_FAILED); } return ret; }
BOOLEAN VirtIoInterrupt( IN PVOID DeviceExtension ) { pblk_req vbr; unsigned int len; PADAPTER_EXTENSION adaptExt; BOOLEAN isInterruptServiced = FALSE; PSCSI_REQUEST_BLOCK Srb; ULONG intReason = 0; PRHEL_SRB_EXTENSION srbExt; 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 srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; if (srbExt->fua) { RemoveEntryList(&vbr->list_entry); Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb, FALSE)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } else { srbExt->fua = FALSE; } } else { CompleteDPC(DeviceExtension, vbr, 0); } } } } else if (intReason == 3) { RhelGetDiskGeometry(DeviceExtension); 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; }
UCHAR RhelScsiGetInquiryData( IN PVOID DeviceExtension, IN OUT PSCSI_REQUEST_BLOCK Srb ) { PINQUIRYDATA InquiryData; ULONG dataLen; UCHAR SrbStatus = SRB_STATUS_INVALID_LUN; PCDB cdb = (PCDB)&Srb->Cdb[0]; PADAPTER_EXTENSION adaptExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; InquiryData = (PINQUIRYDATA)Srb->DataBuffer; dataLen = Srb->DataTransferLength; if (adaptExt->rescan_geometry) { RhelGetDiskGeometry(DeviceExtension); adaptExt->rescan_geometry = FALSE; } SrbStatus = SRB_STATUS_SUCCESS; if((cdb->CDB6INQUIRY3.PageCode != VPD_SUPPORTED_PAGES) && (cdb->CDB6INQUIRY3.EnableVitalProductData == 0)) { Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; } else if ((cdb->CDB6INQUIRY3.PageCode == VPD_SUPPORTED_PAGES) && (cdb->CDB6INQUIRY3.EnableVitalProductData == 1)) { PVPD_SUPPORTED_PAGES_PAGE SupportPages; SupportPages = (PVPD_SUPPORTED_PAGES_PAGE)Srb->DataBuffer; memset(SupportPages, 0, sizeof(VPD_SUPPORTED_PAGES_PAGE)); SupportPages->PageCode = VPD_SUPPORTED_PAGES; SupportPages->PageLength = 3; SupportPages->SupportedPageList[0] = VPD_SUPPORTED_PAGES; SupportPages->SupportedPageList[1] = VPD_SERIAL_NUMBER; SupportPages->SupportedPageList[2] = VPD_DEVICE_IDENTIFIERS; Srb->DataTransferLength = sizeof(VPD_SUPPORTED_PAGES_PAGE) + SupportPages->PageLength; } else if ((cdb->CDB6INQUIRY3.PageCode == VPD_SERIAL_NUMBER) && (cdb->CDB6INQUIRY3.EnableVitalProductData == 1)) { PVPD_SERIAL_NUMBER_PAGE SerialPage; SerialPage = (PVPD_SERIAL_NUMBER_PAGE)Srb->DataBuffer; SerialPage->PageCode = VPD_SERIAL_NUMBER; if (!adaptExt->sn_ok) { SerialPage->PageLength = 1; SerialPage->SerialNumber[0] = '0'; } else { SerialPage->PageLength = BLOCK_SERIAL_STRLEN; ScsiPortMoveMemory(&SerialPage->SerialNumber, &adaptExt->sn, BLOCK_SERIAL_STRLEN); } Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + SerialPage->PageLength; } else if ((cdb->CDB6INQUIRY3.PageCode == VPD_DEVICE_IDENTIFIERS) && (cdb->CDB6INQUIRY3.EnableVitalProductData == 1)) { PVPD_IDENTIFICATION_PAGE IdentificationPage; PVPD_IDENTIFICATION_DESCRIPTOR IdentificationDescr; IdentificationPage = (PVPD_IDENTIFICATION_PAGE)Srb->DataBuffer; memset(IdentificationPage, 0, sizeof(VPD_IDENTIFICATION_PAGE)); IdentificationPage->PageCode = VPD_DEVICE_IDENTIFIERS; IdentificationPage->PageLength = sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 11; IdentificationDescr = (PVPD_IDENTIFICATION_DESCRIPTOR)IdentificationPage->Descriptors; memset(IdentificationDescr, 0, sizeof(VPD_IDENTIFICATION_DESCRIPTOR)); IdentificationDescr->CodeSet = VpdCodeSetBinary; IdentificationDescr->IdentifierType = VpdIdentifierTypeEUI64; IdentificationDescr->IdentifierLength = 11; IdentificationDescr->Identifier[0] = '1'; IdentificationDescr->Identifier[1] = 'A'; IdentificationDescr->Identifier[2] = 'F'; IdentificationDescr->Identifier[3] = '4'; IdentificationDescr->Identifier[4] = '1'; IdentificationDescr->Identifier[5] = '0'; IdentificationDescr->Identifier[6] = '0'; IdentificationDescr->Identifier[7] = '1'; IdentificationDescr->Identifier[8] = '_'; IdentificationDescr->Identifier[9] = '0' + (adaptExt->rescan_cnt / 10); IdentificationDescr->Identifier[10] = '0' + (adaptExt->rescan_cnt % 10); Srb->DataTransferLength = sizeof(VPD_IDENTIFICATION_PAGE) + IdentificationPage->PageLength; } else if (dataLen > sizeof(INQUIRYDATA)) { ScsiPortMoveMemory(InquiryData, &adaptExt->inquiry_data, sizeof(INQUIRYDATA)); Srb->DataTransferLength = sizeof(INQUIRYDATA); } else { ScsiPortMoveMemory(InquiryData, &adaptExt->inquiry_data, dataLen); Srb->DataTransferLength = dataLen; } return SrbStatus; }