Changeset 70223 in vbox for trunk/src/VBox
- Timestamp:
- Dec 19, 2017 5:10:59 PM (7 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxGuest
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp
r70220 r70223 149 149 /** Preallocated generic request for shutdown. */ 150 150 VMMDevPowerStateRequest *pPowerStateRequest; 151 /** Preallocated VMMDevEvents for IRQ handler. */152 VMMDevEvents *pIrqAckEvents;153 151 154 152 /** Spinlock protecting MouseNotifyCallback. Required since the consumer is … … 191 189 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp); 192 190 static void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt); 193 static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj);194 191 static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj); 195 192 static NTSTATUS vgdrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); … … 263 260 return STATUS_UNSUCCESSFUL; 264 261 } 262 VGDrvCommonInitLoggers(); 265 263 266 264 LogFunc(("Driver built: %s %s\n", __DATE__, __TIME__)); … … 400 398 return rcNt; 401 399 } 402 403 400 } 404 401 } … … 408 405 */ 409 406 LogRelFunc(("Failed! rcNt=%#x\n", rcNt)); 407 VGDrvCommonDestroyLoggers(); 410 408 RTR0Term(); 411 409 return rcNt; … … 513 511 514 512 /** 515 * Global initialization stuff.513 * Sets up the device and its resources. 516 514 * 517 515 * @param pDevExt Our device extension data. … … 521 519 * @param pRegPath The registry path for NT4, NULL for NT5+. 522 520 */ 523 static NTSTATUS vgdrvNt Init(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj,524 PIRP pIrp, PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)521 static NTSTATUS vgdrvNtSetupDevice(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj, 522 PIRP pIrp, PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath) 525 523 { 526 524 LogFlowFunc(("ENTER: pDevExt=%p pDevObj=%p pIrq=%p pDrvObj=%p pRegPath=%p\n", pDevExt, pDevObj, pIrp, pDrvObj, pRegPath)); … … 588 586 pvMMIOBase, pDevExt, pDevExt ? pDevExt->Core.pVMMDevMemory : NULL)); 589 587 590 int vrc = VGDrvCommonInitDevExt (&pDevExt->Core,591 pDevExt->Core.IOPortBase,592 pvMMIOBase, cbMMIO,593 vgdrvNtVersionToOSType(g_enmVGDrvNtVer),594 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);588 int vrc = VGDrvCommonInitDevExtResources(&pDevExt->Core, 589 pDevExt->Core.IOPortBase, 590 pvMMIOBase, cbMMIO, 591 vgdrvNtVersionToOSType(g_enmVGDrvNtVer), 592 VMMDEV_EVENT_MOUSE_POSITION_CHANGED); 595 593 if (RT_SUCCESS(vrc)) 596 594 { 595 597 596 vrc = VbglR0GRAlloc((VMMDevRequestHeader **)&pDevExt->pPowerStateRequest, 598 597 sizeof(VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus); … … 674 673 } 675 674 676 VGDrvCommonDeleteDevExt (&pDevExt->Core);675 VGDrvCommonDeleteDevExtResources(&pDevExt->Core); 677 676 } 678 677 else 679 678 { 680 LogFunc(("Could not init device extension ,vrc=%Rrc\n", vrc));679 LogFunc(("Could not init device extension resources: vrc=%Rrc\n", vrc)); 681 680 rcNt = STATUS_DEVICE_CONFIGURATION_ERROR; 682 681 } … … 695 694 696 695 #ifdef TARGET_NT4 696 697 /** 698 * Helper function to handle the PCI device lookup. 699 * 700 * @returns NT status code. 701 * 702 * @param puBus Where to return the bus number on success. 703 * @param pSlot Where to return the slot number on success. 704 */ 705 static NTSTATUS vgdrvNt4FindPciDevice(PULONG puBus, PPCI_SLOT_NUMBER pSlot) 706 { 707 Log(("vgdrvNt4FindPciDevice\n")); 708 709 PCI_SLOT_NUMBER Slot; 710 Slot.u.AsULONG = 0; 711 712 /* Scan each bus. */ 713 for (ULONG uBus = 0; uBus < PCI_MAX_BUSES; uBus++) 714 { 715 /* Scan each device. */ 716 for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++) 717 { 718 Slot.u.bits.DeviceNumber = deviceNumber; 719 720 /* Scan each function (not really required...). */ 721 for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++) 722 { 723 Slot.u.bits.FunctionNumber = functionNumber; 724 725 /* Have a look at what's in this slot. */ 726 PCI_COMMON_CONFIG PciData; 727 if (!HalGetBusData(PCIConfiguration, uBus, Slot.u.AsULONG, &PciData, sizeof(ULONG))) 728 { 729 /* No such bus, we're done with it. */ 730 deviceNumber = PCI_MAX_DEVICES; 731 break; 732 } 733 734 if (PciData.VendorID == PCI_INVALID_VENDORID) 735 /* We have to proceed to the next function. */ 736 continue; 737 738 /* Check if it's another device. */ 739 if ( PciData.VendorID != VMMDEV_VENDORID 740 || PciData.DeviceID != VMMDEV_DEVICEID) 741 continue; 742 743 /* Hooray, we've found it! */ 744 Log(("vgdrvNt4FindPciDevice: Device found! Bus=%#x Slot=%#u (dev %#x, fun %#x, rvd %#x)\n", 745 uBus, Slot.u.AsULONG, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, Slot.u.bits.Reserved)); 746 747 *puBus = uBus; 748 *pSlot = Slot; 749 return STATUS_SUCCESS; 750 } 751 } 752 } 753 754 return STATUS_DEVICE_DOES_NOT_EXIST; 755 } 756 697 757 698 758 /** … … 742 802 */ 743 803 Log(("vgdrvNt4CreateDevice: Setting up device extension ...\n")); 744 745 804 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; 746 805 RT_ZERO(*pDevExt); 747 748 Log(("vgdrvNt4CreateDevice: Device extension created\n"));749 806 750 807 /* Store a reference to ourself. */ … … 755 812 pDevExt->uSlot = uSlot.u.AsULONG; 756 813 814 /* Initialize common bits. */ 815 int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core); 816 if (RT_SUCCESS(vrc)) 817 { 818 Log(("vgdrvNt4CreateDevice: Device extension created\n")); 757 819 # ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 758 rc = hlpRegisterBugCheckCallback(pDevExt);820 rc = hlpRegisterBugCheckCallback(pDevExt); 759 821 # endif 760 if (NT_SUCCESS(rc))761 {762 /* Do the actual VBox init ... */763 rc = vgdrvNtInit(pDevExt, pDeviceObject, NULL /*pIrp*/, pDrvObj, pRegPath);764 822 if (NT_SUCCESS(rc)) 765 823 { 766 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc)); 767 return rc; 824 /* Do the actual VBox init ... */ 825 rc = vgdrvNtSetupDevice(pDevExt, pDeviceObject, NULL /*pIrp*/, pDrvObj, pRegPath); 826 if (NT_SUCCESS(rc)) 827 { 828 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc)); 829 return rc; 830 } 831 832 /* bail out */ 768 833 } 769 770 /* bail out */ 834 VGDrvCommonDeleteDevExtFundament(&pDevExt->Core); 771 835 } 772 836 IoDeleteSymbolicLink(&DosName); … … 780 844 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x\n", rc)); 781 845 return rc; 782 }783 784 785 /**786 * Helper function to handle the PCI device lookup.787 *788 * @returns NT status code.789 *790 * @param puBus Where to return the bus number on success.791 * @param pSlot Where to return the slot number on success.792 */793 static NTSTATUS vgdrvNt4FindPciDevice(PULONG puBus, PPCI_SLOT_NUMBER pSlot)794 {795 Log(("vgdrvNt4FindPciDevice\n"));796 797 PCI_SLOT_NUMBER Slot;798 Slot.u.AsULONG = 0;799 800 /* Scan each bus. */801 for (ULONG uBus = 0; uBus < PCI_MAX_BUSES; uBus++)802 {803 /* Scan each device. */804 for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)805 {806 Slot.u.bits.DeviceNumber = deviceNumber;807 808 /* Scan each function (not really required...). */809 for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)810 {811 Slot.u.bits.FunctionNumber = functionNumber;812 813 /* Have a look at what's in this slot. */814 PCI_COMMON_CONFIG PciData;815 if (!HalGetBusData(PCIConfiguration, uBus, Slot.u.AsULONG, &PciData, sizeof(ULONG)))816 {817 /* No such bus, we're done with it. */818 deviceNumber = PCI_MAX_DEVICES;819 break;820 }821 822 if (PciData.VendorID == PCI_INVALID_VENDORID)823 /* We have to proceed to the next function. */824 continue;825 826 /* Check if it's another device. */827 if ( PciData.VendorID != VMMDEV_VENDORID828 || PciData.DeviceID != VMMDEV_DEVICEID)829 continue;830 831 /* Hooray, we've found it! */832 Log(("vgdrvNt4FindPciDevice: Device found! Bus=%#x Slot=%#u (dev %#x, fun %#x, rvd %#x)\n",833 uBus, Slot.u.AsULONG, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, Slot.u.bits.Reserved));834 835 *puBus = uBus;836 *pSlot = Slot;837 return STATUS_SUCCESS;838 }839 }840 }841 842 return STATUS_DEVICE_DOES_NOT_EXIST;843 846 } 844 847 … … 882 885 883 886 KeInitializeSpinLock(&pDevExt->MouseEventAccessSpinLock); 884 885 887 pDevExt->pDeviceObject = pDeviceObject; 886 888 pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED; 887 889 pDevExt->enmDevState = VGDRVNTDEVSTATE_STOPPED; 888 890 889 pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj); 890 if (pDevExt->pNextLowerDriver != NULL) 891 { 892 /* 893 * If we reached this point we're fine with the basic driver setup, 894 * so continue to init our own things. 895 */ 891 int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core); 892 if (RT_SUCCESS(vrc)) 893 { 894 pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj); 895 if (pDevExt->pNextLowerDriver != NULL) 896 { 897 /* 898 * If we reached this point we're fine with the basic driver setup, 899 * so continue to init our own things. 900 */ 896 901 #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 897 vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */902 vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */ 898 903 #endif 899 if (NT_SUCCESS(rcNt)) 904 if (NT_SUCCESS(rcNt)) 905 { 906 /* Ensure we are not called at elevated IRQL, even if our code isn't pagable any more. */ 907 pDeviceObject->Flags |= DO_POWER_PAGABLE; 908 909 /* Driver is ready now. */ 910 pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 911 LogFlowFunc(("Returning with rcNt=%#x (success)\n", rcNt)); 912 return rcNt; 913 } 914 915 IoDetachDevice(pDevExt->pNextLowerDriver); 916 } 917 else 900 918 { 901 /* Ensure we are not called at elevated IRQL, even if our code isn't pagable any more. */ 902 pDeviceObject->Flags |= DO_POWER_PAGABLE; 903 904 /* Driver is ready now. */ 905 pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 906 LogFlowFunc(("Returning with rcNt=%#x (success)\n", rcNt)); 907 return rcNt; 919 LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n")); 920 rcNt = STATUS_DEVICE_NOT_CONNECTED; 908 921 } 909 910 IoDetachDevice(pDevExt->pNextLowerDriver); 922 VGDrvCommonDeleteDevExtFundament(&pDevExt->Core); 911 923 } 912 924 else 913 { 914 LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n")); 915 rcNt = STATUS_DEVICE_NOT_CONNECTED; 916 } 925 rcNt = STATUS_UNSUCCESSFUL; 917 926 918 927 /* bail out */ … … 979 988 Log(("vgdrvNt5PlusPnPSendIrpSynchronously: Returning %#x\n", rcNt)); 980 989 return rcNt; 990 } 991 992 993 /** 994 * Deletes the device hardware resources. 995 * 996 * Used during removal, stopping and legacy module unloading. 997 * 998 * @param pDevExt The device extension. 999 */ 1000 static void vgdrvNtDeleteDeviceResources(PVBOXGUESTDEVEXTWIN pDevExt) 1001 { 1002 if (pDevExt->pInterruptObject) 1003 { 1004 IoDisconnectInterrupt(pDevExt->pInterruptObject); 1005 pDevExt->pInterruptObject = NULL; 1006 } 1007 if (pDevExt->Core.uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES) 1008 VGDrvCommonDeleteDevExtResources(&pDevExt->Core); 1009 vgdrvNtUnmapVMMDevMemory(pDevExt); 1010 } 1011 1012 1013 /** 1014 * Deletes the device extension fundament and unlinks the device 1015 * 1016 * Used during removal and legacy module unloading. Must have called 1017 * vgdrvNtDeleteDeviceResources. 1018 * 1019 * @param pDevExt The device extension. 1020 */ 1021 static void vgdrvNtDeleteDeviceFundamentAndUnlink(PDEVICE_OBJECT pDevObj, PVBOXGUESTDEVEXTWIN pDevExt) 1022 { 1023 /* 1024 * Delete the remainder of the device extension. 1025 */ 1026 pDevExt->pPowerStateRequest = NULL; /* Will be deleted by the following call. */ 1027 VGDrvCommonDeleteDevExtFundament(&pDevExt->Core); 1028 1029 #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 1030 hlpDeregisterBugCheckCallback(pDevExt); 1031 #endif 1032 1033 /* 1034 * Delete the DOS symlink to the device and finally the device itself. 1035 */ 1036 UNICODE_STRING DosName; 1037 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); 1038 IoDeleteSymbolicLink(&DosName); 1039 1040 Log(("vgdrvNtDeleteDeviceFundamentAndUnlink: Deleting device ...\n")); 1041 IoDeleteDevice(pDevObj); 981 1042 } 982 1043 … … 1039 1100 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n", 1040 1101 pStack->Parameters.StartDevice.AllocatedResources)); 1041 1042 1102 if (pStack->Parameters.StartDevice.AllocatedResources) 1043 rc = vgdrvNtInit(pDevExt, pDevObj, pIrp, NULL, NULL); 1103 { 1104 rc = vgdrvNtSetupDevice(pDevExt, pDevObj, pIrp, NULL, NULL); 1105 if (!NT_SUCCESS(rc)) 1106 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: vgdrvNtSetupDevice failed: %#x\n", rc)); 1107 } 1044 1108 else 1045 1109 { … … 1049 1113 } 1050 1114 } 1051 if (NT_ERROR(rc)) 1052 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: Error: rc = 0x%x\n", rc)); 1053 break; 1115 else 1116 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: vgdrvNt5PlusPnPSendIrpSynchronously failed: %#x + %#x\n", 1117 rc, pIrp->IoStatus.Status)); 1118 1119 pIrp->IoStatus.Status = rc; 1120 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 1121 return rc; 1054 1122 } 1055 1123 1124 1125 /* 1126 * Sent before removing the device and/or driver. 1127 */ 1128 case IRP_MN_QUERY_REMOVE_DEVICE: 1129 { 1130 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE\n")); 1131 1132 #ifdef VBOX_REBOOT_ON_UNINSTALL 1133 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n")); 1134 rc = STATUS_UNSUCCESSFUL; 1135 #endif 1136 /** @todo refuse to remove ourselves when we've got client 1137 * sessions attached... */ 1138 1139 if (NT_SUCCESS(rc)) 1140 { 1141 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGREMOVE); 1142 1143 /* This IRP passed down to lower driver. */ 1144 pIrp->IoStatus.Status = STATUS_SUCCESS; 1145 1146 IoSkipCurrentIrpStackLocation(pIrp); 1147 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1148 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1149 1150 /* We must not do anything the IRP after doing IoSkip & CallDriver 1151 since the driver below us will complete (or already have completed) the IRP. 1152 I.e. just return the status we got from IoCallDriver */ 1153 } 1154 else 1155 { 1156 pIrp->IoStatus.Status = rc; 1157 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 1158 } 1159 1160 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Returning with rc = 0x%x\n", rc)); 1161 return rc; 1162 } 1163 1164 /* 1165 * Cancels a pending remove, IRP_MN_QUERY_REMOVE_DEVICE. 1166 * We only have to revert the state. 1167 */ 1056 1168 case IRP_MN_CANCEL_REMOVE_DEVICE: 1057 1169 { … … 1068 1180 1069 1181 /* Complete the IRP. */ 1070 break; 1182 pIrp->IoStatus.Status = rc; 1183 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 1184 return rc; 1071 1185 } 1072 1186 1187 /* 1188 * We do nothing here actually, esp. since this request is not expected for VBoxGuest. 1189 * The cleanup will be done in IRP_MN_REMOVE_DEVICE, which follows this call. 1190 */ 1073 1191 case IRP_MN_SURPRISE_REMOVAL: 1074 1192 { 1075 1193 Log(("vgdrvNtNt5PlusPnP: IRP_MN_SURPRISE_REMOVAL\n")); 1076 1077 1194 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_SURPRISEREMOVED); 1078 1079 /* Do nothing here actually. Cleanup is done in IRP_MN_REMOVE_DEVICE.1080 * This request is not expected for VBoxGuest.1081 */1082 1195 LogRel(("VBoxGuest: unexpected device removal\n")); 1083 1196 … … 1086 1199 1087 1200 IoSkipCurrentIrpStackLocation(pIrp); 1088 1089 1201 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1090 1202 … … 1093 1205 } 1094 1206 1095 case IRP_MN_QUERY_REMOVE_DEVICE: 1096 { 1097 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE\n")); 1098 1099 #ifdef VBOX_REBOOT_ON_UNINSTALL 1100 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n")); 1101 rc = STATUS_UNSUCCESSFUL; 1102 #endif 1103 1104 if (NT_SUCCESS(rc)) 1105 { 1106 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGREMOVE); 1107 1108 /* This IRP passed down to lower driver. */ 1109 pIrp->IoStatus.Status = STATUS_SUCCESS; 1110 1111 IoSkipCurrentIrpStackLocation(pIrp); 1112 1113 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1114 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1115 1116 /* we must not do anything the IRP after doing IoSkip & CallDriver 1117 * since the driver below us will complete (or already have completed) the IRP. 1118 * I.e. just return the status we got from IoCallDriver */ 1119 return rc; 1120 } 1121 1122 /* Complete the IRP on failure. */ 1123 break; 1124 } 1125 1207 /* 1208 * Device and/or driver removal. Destroy everything. 1209 */ 1126 1210 case IRP_MN_REMOVE_DEVICE: 1127 1211 { 1128 1212 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE\n")); 1129 1130 1213 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_REMOVED); 1131 1214 1132 /* Free hardware resources. */1133 /** @todo this should actually free I/O ports, interrupts, etc.1134 * Update/bird: vgdrvNtCleanup actually does that... So, what's there to do? */1135 rc = vgdrvNtCleanup(pDevObj);1136 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: vgdrvNtCleanup rc = 0x%08X\n", rc));1137 1138 1215 /* 1139 * We need to send the remove down the stack before we detach, 1140 * but we don't need to wait for the completion of this operation 1141 * (and to register a completion routine). 1216 * Disconnect interrupts and delete all hardware resources. 1217 * Note! This may already have been done if we're STOPPED already, if that's a possibility. 1218 */ 1219 vgdrvNtDeleteDeviceResources(pDevExt); 1220 1221 /* 1222 * We need to send the remove down the stack before we detach, but we don't need 1223 * to wait for the completion of this operation (nor register a completion routine). 1142 1224 */ 1143 1225 pIrp->IoStatus.Status = STATUS_SUCCESS; 1144 1226 1145 1227 IoSkipCurrentIrpStackLocation(pIrp); 1146 1147 1228 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1148 1229 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1149 1230 1150 1231 IoDetachDevice(pDevExt->pNextLowerDriver); 1151 1152 1232 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Removing device ...\n")); 1153 1233 1154 /* Destroy device extension and clean up everything else. */ 1155 VGDrvCommonDeleteDevExt(&pDevExt->Core); 1156 1157 /* Remove DOS device + symbolic link. */ 1158 UNICODE_STRING win32Name; 1159 RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS); 1160 IoDeleteSymbolicLink(&win32Name); 1161 1162 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Deleting device ...\n")); 1163 1164 /* Last action: Delete our device! pDevObj is *not* failed 1165 * anymore after this call! */ 1166 IoDeleteDevice(pDevObj); 1234 /* 1235 * Delete the remainder of the device extension data, unlink it from the namespace and delete it. 1236 */ 1237 vgdrvNtDeleteDeviceFundamentAndUnlink(pDevObj, pDevExt); 1238 1239 pDevObj = NULL; /* invalid */ 1240 pDevExt = NULL; /* invalid */ 1167 1241 1168 1242 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Device removed!\n")); 1169 1170 /* Propagating rc from IoCallDriver. */ 1171 return rc; /* Make sure that we don't do anything below here anymore! */ 1243 return rc; /* Propagating rc from IoCallDriver. */ 1172 1244 } 1173 1245 1246 1247 /* 1248 * Sent before stopping the device/driver to check whether it is okay to do so. 1249 */ 1250 case IRP_MN_QUERY_STOP_DEVICE: 1251 { 1252 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE\n")); 1253 1254 /** @todo Check whether we can stop the device. Similar to 1255 * removal above */ 1256 rc = STATUS_SUCCESS; 1257 if (NT_SUCCESS(rc)) 1258 { 1259 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGSTOP); 1260 1261 /* This IRP passed down to lower driver. */ 1262 pIrp->IoStatus.Status = STATUS_SUCCESS; 1263 1264 IoSkipCurrentIrpStackLocation(pIrp); 1265 1266 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1267 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1268 1269 /* we must not do anything with the IRP after doing IoSkip & CallDriver since the 1270 driver below us will complete (or already have completed) the IRP. I.e. just 1271 return the status we got from IoCallDriver. */ 1272 } 1273 else 1274 { 1275 pIrp->IoStatus.Status = rc; 1276 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 1277 } 1278 1279 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Returning with rc = 0x%x\n", rc)); 1280 return rc; 1281 } 1282 1283 /* 1284 * Cancels a pending remove, IRP_MN_QUERY_STOP_DEVICE. 1285 * We only have to revert the state. 1286 */ 1174 1287 case IRP_MN_CANCEL_STOP_DEVICE: 1175 1288 { … … 1186 1299 1187 1300 /* Complete the IRP. */ 1188 break; 1301 pIrp->IoStatus.Status = rc; 1302 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 1303 return rc; 1189 1304 } 1190 1305 1191 case IRP_MN_QUERY_STOP_DEVICE: 1192 { 1193 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE\n")); 1194 1195 #ifdef VBOX_REBOOT_ON_UNINSTALL /** @todo r=bird: this code and log msg is pointless as rc = success and status will be overwritten below. */ 1196 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n")); 1197 pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; 1198 #endif 1199 1200 if (NT_SUCCESS(rc)) 1201 { 1202 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGSTOP); 1203 1204 /* This IRP passed down to lower driver. */ 1205 pIrp->IoStatus.Status = STATUS_SUCCESS; 1206 1207 IoSkipCurrentIrpStackLocation(pIrp); 1208 1209 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1210 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1211 1212 /* we must not do anything with the IRP after doing IoSkip & CallDriver 1213 * since the driver below us will complete (or already have completed) the IRP. 1214 * I.e. just return the status we got from IoCallDriver */ 1215 return rc; 1216 } 1217 1218 /* Complete the IRP on failure. */ 1219 break; 1220 } 1221 1306 /* 1307 * Stop the device. 1308 */ 1222 1309 case IRP_MN_STOP_DEVICE: 1223 1310 { 1224 1311 Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE\n")); 1225 1226 1312 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_STOPPED); 1227 1313 1228 /* Free hardware resources. */ 1229 /** @todo this should actually free I/O ports, interrupts, etc. 1230 * Update/bird: vgdrvNtCleanup actually does that... So, what's there to do? */ 1231 rc = vgdrvNtCleanup(pDevObj); 1232 Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc)); 1233 1234 /* Pass to the lower driver. */ 1314 /* 1315 * Release the hardware resources. 1316 */ 1317 vgdrvNtDeleteDeviceResources(pDevExt); 1318 1319 /* 1320 * Pass the request to the lower driver. 1321 */ 1235 1322 pIrp->IoStatus.Status = STATUS_SUCCESS; 1236 1237 1323 IoSkipCurrentIrpStackLocation(pIrp); 1238 1239 1324 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1240 1325 Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1241 1242 1326 return rc; 1243 1327 } … … 1247 1331 IoSkipCurrentIrpStackLocation(pIrp); 1248 1332 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1333 Log(("vgdrvNtNt5PlusPnP: Unknown request %#x: Lower driver replied: %x\n", pStack->MinorFunction, rc)); 1249 1334 return rc; 1250 1335 } 1251 1336 } 1252 1253 pIrp->IoStatus.Status = rc;1254 IoCompleteRequest(pIrp, IO_NO_INCREMENT);1255 1256 Log(("vgdrvNtNt5PlusPnP: Returning with rc = 0x%x\n", rc));1257 return rc;1258 1337 } 1259 1338 … … 1505 1584 1506 1585 /** 1507 * Cleans up hardware resources. 1508 * Do not delete DevExt here. 1509 * 1510 * @todo r=bird: HC SVNT DRACONES! 1511 * 1512 * This code leaves clients hung when vgdrvNtInit is called afterwards. 1513 * This happens when for instance hotplugging a CPU. Problem is 1514 * vgdrvNtInit doing a full VGDrvCommonInitDevExt, orphaning all pDevExt 1515 * members, like session lists and stuff. 1516 * 1517 * @param pDevObj Device object. 1518 */ 1519 static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj) 1586 * Unload the driver. 1587 * 1588 * @param pDrvObj Driver object. 1589 */ 1590 static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj) 1520 1591 { 1521 1592 LogFlowFuncEnter(); 1522 1593 1523 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; 1524 if (pDevExt) 1525 { 1526 if (pDevExt->pInterruptObject) 1594 #ifdef TARGET_NT4 1595 /* 1596 * We need to destroy the device object here on NT4 and earlier. 1597 */ 1598 PDEVICE_OBJECT pDevObj = pDrvObj->DeviceObject; 1599 if (pDevObj) 1600 { 1601 if (g_enmVGDrvNtVer <= VGDRVNTVER_WINNT4) 1527 1602 { 1528 IoDisconnectInterrupt(pDevExt->pInterruptObject); 1529 pDevExt->pInterruptObject = NULL; 1603 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; 1604 AssertPtr(pDevExt); 1605 AssertMsg(pDevExt->Core.uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES, 1606 ("uInitState=%#x\n", pDevExt->Core.uInitState)); 1607 1608 vgdrvNtDeleteDeviceResources(pDevExt); 1609 vgdrvNtDeleteDeviceFundamentAndUnlink(pDevObj, pDevExt); 1530 1610 } 1531 1532 /** @todo cleanup the rest stuff */ 1533 1534 1535 #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 1536 hlpDeregisterBugCheckCallback(pDevExt); /* ignore failure! */ 1537 #endif 1538 /* According to MSDN we have to unmap previously mapped memory. */ 1539 vgdrvNtUnmapVMMDevMemory(pDevExt); 1540 } 1541 1542 return STATUS_SUCCESS; 1543 } 1544 1545 1546 /** 1547 * Unload the driver. 1548 * 1549 * @param pDrvObj Driver object. 1550 */ 1551 static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj) 1552 { 1553 LogFlowFuncEnter(); 1554 1555 #ifdef TARGET_NT4 1556 vgdrvNtCleanup(pDrvObj->DeviceObject); 1557 1558 /* Destroy device extension and clean up everything else. */ 1559 if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension) 1560 VGDrvCommonDeleteDevExt((PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension); 1561 1562 /* 1563 * I don't think it's possible to unload a driver which processes have 1564 * opened, at least we'll blindly assume that here. 1565 */ 1566 UNICODE_STRING DosName; 1567 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); 1568 IoDeleteSymbolicLink(&DosName); 1569 1570 IoDeleteDevice(pDrvObj->DeviceObject); 1611 } 1571 1612 #else /* !TARGET_NT4 */ 1572 1613 /* … … 1577 1618 #endif /* !TARGET_NT4 */ 1578 1619 1620 VGDrvCommonDestroyLoggers(); 1579 1621 RTR0Term(); 1580 1622 LogFlowFunc(("Returning\n")); … … 1982 2024 { 1983 2025 Log3Func(("Requesting DPC ...\n")); 1984 IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL); 2026 IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL); /** @todo r=bird: pCurrentIrp is not set anywhere. sigh. */ 1985 2027 } 1986 2028 } -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
r70154 r70223 924 924 925 925 /** 926 * Initializes the VBoxGuest device extension when the 927 * device driver is loaded. 928 * 929 * The native code locates the VMMDev on the PCI bus and retrieve 930 * the MMIO and I/O port ranges, this function will take care of 931 * mapping the MMIO memory (if present). Upon successful return 932 * the native code should set up the interrupt handler. 933 * 934 * @returns VBox status code. 935 * 936 * @param pDevExt The device extension. Allocated by the native code. 937 * @param IOPortBase The base of the I/O port range. 938 * @param pvMMIOBase The base of the MMIO memory mapping. 939 * This is optional, pass NULL if not present. 940 * @param cbMMIO The size of the MMIO memory mapping. 941 * This is optional, pass 0 if not present. 942 * @param enmOSType The guest OS type to report to the VMMDev. 943 * @param fFixedEvents Events that will be enabled upon init and no client 944 * will ever be allowed to mask. 945 */ 946 int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, 947 void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents) 948 { 949 int rc, rc2; 950 926 * Initializes the release logger (debug is implicit), if configured. 927 * 928 * @returns IPRT status code. 929 */ 930 int VGDrvCommonInitLoggers(void) 931 { 951 932 #ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER 952 933 /* … … 955 936 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; 956 937 PRTLOGGER pRelLogger; 957 rc = RTLogCreate(&pRelLogger, 0 /*fFlags*/, "all", "VBOXGUEST_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,958 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL);938 int rc = RTLogCreate(&pRelLogger, 0 /*fFlags*/, "all", "VBOXGUEST_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, 939 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL); 959 940 if (RT_SUCCESS(rc)) 960 941 RTLogRelSetDefaultInstance(pRelLogger); 961 942 /** @todo Add native hook for getting logger config parameters and setting 962 943 * them. On linux we should use the module parameter stuff... */ 944 return rc; 945 #else 946 return VINF_SUCCESS; 963 947 #endif 964 965 /* 966 * Adjust fFixedEvents. 967 */ 968 #ifdef VBOX_WITH_HGCM 969 fFixedEvents |= VMMDEV_EVENT_HGCM; 948 } 949 950 951 /** 952 * Destroys the loggers. 953 */ 954 void VGDrvCommonDestroyLoggers(void) 955 { 956 #ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER 957 RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); 958 RTLogDestroy(RTLogSetDefaultInstance(NULL)); 970 959 #endif 960 } 961 962 963 /** 964 * Initialize the device extension fundament. 965 * 966 * There are no device resources at this point, VGDrvCommonInitDevExtResources 967 * should be called when they are available. 968 * 969 * @returns VBox status code. 970 * @param pDevExt The device extension to init. 971 */ 972 int VGDrvCommonInitDevExtFundament(PVBOXGUESTDEVEXT pDevExt) 973 { 974 int rc; 975 AssertMsg( pDevExt->uInitState != VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT 976 && pDevExt->uInitState != VBOXGUESTDEVEXT_INIT_STATE_RESOURCES, ("uInitState=%#x\n", pDevExt->uInitState)); 971 977 972 978 /* 973 979 * Initialize the data. 974 980 */ 975 pDevExt->IOPortBase = IOPortBase;981 pDevExt->IOPortBase = UINT16_MAX; 976 982 pDevExt->pVMMDevMemory = NULL; 977 983 pDevExt->hGuestMappings = NIL_RTR0MEMOBJ; … … 1004 1010 pDevExt->pReqGuestHeartbeat = NULL; 1005 1011 1006 pDevExt->fFixedEvents = fFixedEvents;1012 pDevExt->fFixedEvents = 0; 1007 1013 vgdrvBitUsageTrackerClear(&pDevExt->EventFilterTracker); 1008 1014 pDevExt->fEventFilterHost = UINT32_MAX; /* forces a report */ … … 1018 1024 1019 1025 /* 1026 * Create the wait and session spinlocks as well as the ballooning mutex. 1027 */ 1028 rc = RTSpinlockCreate(&pDevExt->EventSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestEvent"); 1029 if (RT_SUCCESS(rc)) 1030 { 1031 rc = RTSpinlockCreate(&pDevExt->SessionSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestSession"); 1032 if (RT_SUCCESS(rc)) 1033 { 1034 rc = RTSemFastMutexCreate(&pDevExt->MemBalloon.hMtx); 1035 if (RT_SUCCESS(rc)) 1036 { 1037 pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT; 1038 return VINF_SUCCESS; 1039 } 1040 1041 LogRel(("VGDrvCommonInitDevExt: failed to create mutex, rc=%Rrc!\n", rc)); 1042 RTSpinlockDestroy(pDevExt->SessionSpinlock); 1043 } 1044 else 1045 LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc)); 1046 RTSpinlockDestroy(pDevExt->EventSpinlock); 1047 } 1048 else 1049 LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc)); 1050 1051 pDevExt->uInitState = 0; 1052 return rc; 1053 } 1054 1055 1056 /** 1057 * Counter to VGDrvCommonInitDevExtFundament. 1058 * 1059 * @param pDevExt The device extension. 1060 */ 1061 void VGDrvCommonDeleteDevExtFundament(PVBOXGUESTDEVEXT pDevExt) 1062 { 1063 int rc2; 1064 AssertMsgReturnVoid(pDevExt->uInitState == VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT, ("uInitState=%#x\n", pDevExt->uInitState)); 1065 pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_DELETED; 1066 1067 rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2); 1068 rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2); 1069 rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2); 1070 } 1071 1072 1073 /** 1074 * Initializes the VBoxGuest device extension resource parts. 1075 * 1076 * The native code locates the VMMDev on the PCI bus and retrieve the MMIO and 1077 * I/O port ranges, this function will take care of mapping the MMIO memory (if 1078 * present). Upon successful return the native code should set up the interrupt 1079 * handler. 1080 * 1081 * @returns VBox status code. 1082 * 1083 * @param pDevExt The device extension. Allocated by the native code. 1084 * @param IOPortBase The base of the I/O port range. 1085 * @param pvMMIOBase The base of the MMIO memory mapping. 1086 * This is optional, pass NULL if not present. 1087 * @param cbMMIO The size of the MMIO memory mapping. 1088 * This is optional, pass 0 if not present. 1089 * @param enmOSType The guest OS type to report to the VMMDev. 1090 * @param fFixedEvents Events that will be enabled upon init and no client 1091 * will ever be allowed to mask. 1092 */ 1093 int VGDrvCommonInitDevExtResources(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, 1094 void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents) 1095 { 1096 int rc; 1097 AssertMsgReturn(pDevExt->uInitState == VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT, ("uInitState=%#x\n", pDevExt->uInitState), 1098 VERR_INVALID_STATE); 1099 1100 /* 1020 1101 * If there is an MMIO region validate the version and size. 1021 1102 */ … … 1029 1110 { 1030 1111 pDevExt->pVMMDevMemory = pVMMDev; 1031 Log(("VGDrvCommonInitDevExt : VMMDevMemory: mapping=%p size=%#RX32 (%#RX32) version=%#RX32\n",1112 Log(("VGDrvCommonInitDevExtResources: VMMDevMemory: mapping=%p size=%#RX32 (%#RX32) version=%#RX32\n", 1032 1113 pVMMDev, pVMMDev->u32Size, cbMMIO, pVMMDev->u32Version)); 1033 1114 } 1034 1115 else /* try live without it. */ 1035 LogRel(("VGDrvCommonInitDevExt : Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32 (expected <= %RX32)\n",1116 LogRel(("VGDrvCommonInitDevExtResources: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32 (expected <= %RX32)\n", 1036 1117 pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size, cbMMIO)); 1037 }1038 1039 /*1040 * Create the wait and session spinlocks as well as the ballooning mutex.1041 */1042 rc = RTSpinlockCreate(&pDevExt->EventSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestEvent");1043 if (RT_SUCCESS(rc))1044 rc = RTSpinlockCreate(&pDevExt->SessionSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestSession");1045 if (RT_FAILURE(rc))1046 {1047 LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc));1048 if (pDevExt->EventSpinlock != NIL_RTSPINLOCK)1049 RTSpinlockDestroy(pDevExt->EventSpinlock);1050 return rc;1051 }1052 1053 rc = RTSemFastMutexCreate(&pDevExt->MemBalloon.hMtx);1054 if (RT_FAILURE(rc))1055 {1056 LogRel(("VGDrvCommonInitDevExt: failed to create mutex, rc=%Rrc!\n", rc));1057 RTSpinlockDestroy(pDevExt->SessionSpinlock);1058 RTSpinlockDestroy(pDevExt->EventSpinlock);1059 return rc;1060 1118 } 1061 1119 … … 1065 1123 * made by the VMM. 1066 1124 */ 1125 pDevExt->IOPortBase = IOPortBase; 1067 1126 rc = VbglR0InitPrimary(pDevExt->IOPortBase, (VMMDevMemory *)pDevExt->pVMMDevMemory); 1068 1127 if (RT_SUCCESS(rc)) … … 1081 1140 * the guest capabilities or mouse status bits set. 1082 1141 */ 1083 rc = vgdrvResetEventFilterOnHost(pDevExt, pDevExt->fFixedEvents); 1142 #ifdef VBOX_WITH_HGCM 1143 fFixedEvents |= VMMDEV_EVENT_HGCM; 1144 #endif 1145 pDevExt->fFixedEvents = fFixedEvents; 1146 rc = vgdrvResetEventFilterOnHost(pDevExt, fFixedEvents); 1084 1147 if (RT_SUCCESS(rc)) 1085 1148 { … … 1101 1164 rc = vgdrvReportDriverStatus(true /* Driver is active */); 1102 1165 if (RT_FAILURE(rc)) 1103 LogRel(("VGDrvCommonInitDevExt: VBoxReportGuestDriverStatus failed, rc=%Rrc\n", rc)); 1104 1105 LogFlowFunc(("VGDrvCommonInitDevExt: returns success\n")); 1166 LogRel(("VGDrvCommonInitDevExtResources: VBoxReportGuestDriverStatus failed, rc=%Rrc\n", rc)); 1167 1168 pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_RESOURCES; 1169 LogFlowFunc(("VGDrvCommonInitDevExtResources: returns success\n")); 1106 1170 return VINF_SUCCESS; 1107 1171 } 1108 LogRel(("VGDrvCommonInitDevExt : failed to clear mouse status: rc=%Rrc\n", rc));1172 LogRel(("VGDrvCommonInitDevExtResources: failed to clear mouse status: rc=%Rrc\n", rc)); 1109 1173 } 1110 1174 else 1111 LogRel(("VGDrvCommonInitDevExt : failed to clear guest capabilities: rc=%Rrc\n", rc));1175 LogRel(("VGDrvCommonInitDevExtResources: failed to clear guest capabilities: rc=%Rrc\n", rc)); 1112 1176 } 1113 1177 else 1114 LogRel(("VGDrvCommonInitDevExt: failed to set fixed event filter: rc=%Rrc\n", rc)); 1178 LogRel(("VGDrvCommonInitDevExtResources: failed to set fixed event filter: rc=%Rrc\n", rc)); 1179 pDevExt->fFixedEvents = 0; 1115 1180 } 1116 1181 else 1117 LogRel(("VGDrvCommonInitDevExt : vgdrvReportGuestInfo failed: rc=%Rrc\n", rc));1182 LogRel(("VGDrvCommonInitDevExtResources: vgdrvReportGuestInfo failed: rc=%Rrc\n", rc)); 1118 1183 VbglR0GRFree((VMMDevRequestHeader *)pDevExt->pIrqAckEvents); 1119 1184 } 1120 1185 else 1121 LogRel(("VGDrvCommonInitDevExt : VbglR0GRAlloc failed: rc=%Rrc\n", rc));1186 LogRel(("VGDrvCommonInitDevExtResources: VbglR0GRAlloc failed: rc=%Rrc\n", rc)); 1122 1187 1123 1188 VbglR0TerminatePrimary(); 1124 1189 } 1125 1190 else 1126 LogRel(("VGDrvCommonInitDevExt: VbglR0InitPrimary failed: rc=%Rrc\n", rc)); 1127 1128 rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2); 1129 rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2); 1130 rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2); 1131 1132 #ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER 1133 RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); 1134 RTLogDestroy(RTLogSetDefaultInstance(NULL)); 1191 LogRel(("VGDrvCommonInitDevExtResources: VbglR0InitPrimary failed: rc=%Rrc\n", rc)); 1192 pDevExt->IOPortBase = UINT16_MAX; 1193 return rc; 1194 } 1195 1196 1197 /** 1198 * Deletes all the items in a wait chain. 1199 * @param pList The head of the chain. 1200 */ 1201 static void vgdrvDeleteWaitList(PRTLISTNODE pList) 1202 { 1203 while (!RTListIsEmpty(pList)) 1204 { 1205 int rc2; 1206 PVBOXGUESTWAIT pWait = RTListGetFirst(pList, VBOXGUESTWAIT, ListNode); 1207 RTListNodeRemove(&pWait->ListNode); 1208 1209 rc2 = RTSemEventMultiDestroy(pWait->Event); AssertRC(rc2); 1210 pWait->Event = NIL_RTSEMEVENTMULTI; 1211 pWait->pSession = NULL; 1212 RTMemFree(pWait); 1213 } 1214 } 1215 1216 1217 /** 1218 * Counter to VGDrvCommonInitDevExtResources. 1219 * 1220 * @param pDevExt The device extension. 1221 */ 1222 void VGDrvCommonDeleteDevExtResources(PVBOXGUESTDEVEXT pDevExt) 1223 { 1224 Log(("VGDrvCommonDeleteDevExtResources:\n")); 1225 AssertMsgReturnVoid(pDevExt->uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES, ("uInitState=%#x\n", pDevExt->uInitState)); 1226 pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT; 1227 1228 /* 1229 * Stop and destroy HB timer and disable host heartbeat checking. 1230 */ 1231 if (pDevExt->pHeartbeatTimer) 1232 { 1233 RTTimerDestroy(pDevExt->pHeartbeatTimer); 1234 vgdrvHeartbeatHostConfigure(pDevExt, false); 1235 } 1236 1237 VbglR0GRFree(pDevExt->pReqGuestHeartbeat); 1238 pDevExt->pReqGuestHeartbeat = NULL; 1239 1240 /* 1241 * Clean up the bits that involves the host first. 1242 */ 1243 vgdrvTermUnfixGuestMappings(pDevExt); 1244 if (!RTListIsEmpty(&pDevExt->SessionList)) 1245 { 1246 LogRelFunc(("session list not empty!\n")); 1247 RTListInit(&pDevExt->SessionList); 1248 } 1249 1250 /* 1251 * Update the host flags (mouse status etc) not to reflect this session. 1252 */ 1253 pDevExt->fFixedEvents = 0; 1254 vgdrvResetEventFilterOnHost(pDevExt, 0 /*fFixedEvents*/); 1255 vgdrvResetCapabilitiesOnHost(pDevExt); 1256 vgdrvResetMouseStatusOnHost(pDevExt); 1257 1258 vgdrvCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL); 1259 1260 /* 1261 * Cleanup all the other resources. 1262 */ 1263 vgdrvDeleteWaitList(&pDevExt->WaitList); 1264 #ifdef VBOX_WITH_HGCM 1265 vgdrvDeleteWaitList(&pDevExt->HGCMWaitList); 1135 1266 #endif 1267 #ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP 1268 vgdrvDeleteWaitList(&pDevExt->WakeUpList); 1269 #endif 1270 vgdrvDeleteWaitList(&pDevExt->WokenUpList); 1271 vgdrvDeleteWaitList(&pDevExt->FreeList); 1272 1273 VbglR0TerminatePrimary(); 1274 1275 1276 pDevExt->pVMMDevMemory = NULL; 1277 pDevExt->IOPortBase = 0; 1278 pDevExt->pIrqAckEvents = NULL; /* Freed by VbglR0TerminatePrimary. */ 1279 } 1280 1281 1282 /** 1283 * Initializes the VBoxGuest device extension when the device driver is loaded. 1284 * 1285 * The native code locates the VMMDev on the PCI bus and retrieve the MMIO and 1286 * I/O port ranges, this function will take care of mapping the MMIO memory (if 1287 * present). Upon successful return the native code should set up the interrupt 1288 * handler. 1289 * 1290 * Instead of calling this method, the host specific code choose to perform a 1291 * more granular initialization using: 1292 * 1. VGDrvCommonInitLoggers 1293 * 2. VGDrvCommonInitDevExtFundament 1294 * 3. VGDrvCommonInitDevExtResources 1295 * 1296 * @returns VBox status code. 1297 * 1298 * @param pDevExt The device extension. Allocated by the native code. 1299 * @param IOPortBase The base of the I/O port range. 1300 * @param pvMMIOBase The base of the MMIO memory mapping. 1301 * This is optional, pass NULL if not present. 1302 * @param cbMMIO The size of the MMIO memory mapping. 1303 * This is optional, pass 0 if not present. 1304 * @param enmOSType The guest OS type to report to the VMMDev. 1305 * @param fFixedEvents Events that will be enabled upon init and no client 1306 * will ever be allowed to mask. 1307 */ 1308 int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, 1309 void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents) 1310 { 1311 int rc; 1312 VGDrvCommonInitLoggers(); 1313 1314 rc = VGDrvCommonInitDevExtFundament(pDevExt); 1315 if (RT_SUCCESS(rc)) 1316 { 1317 rc = VGDrvCommonInitDevExtResources(pDevExt, IOPortBase, pvMMIOBase, cbMMIO, enmOSType, fFixedEvents); 1318 if (RT_SUCCESS(rc)) 1319 return rc; 1320 1321 VGDrvCommonDeleteDevExtFundament(pDevExt); 1322 } 1323 VGDrvCommonDestroyLoggers(); 1136 1324 return rc; /* (failed) */ 1137 1325 } … … 1390 1578 1391 1579 /** 1392 * Deletes all the items in a wait chain.1393 * @param pList The head of the chain.1394 */1395 static void vgdrvDeleteWaitList(PRTLISTNODE pList)1396 {1397 while (!RTListIsEmpty(pList))1398 {1399 int rc2;1400 PVBOXGUESTWAIT pWait = RTListGetFirst(pList, VBOXGUESTWAIT, ListNode);1401 RTListNodeRemove(&pWait->ListNode);1402 1403 rc2 = RTSemEventMultiDestroy(pWait->Event); AssertRC(rc2);1404 pWait->Event = NIL_RTSEMEVENTMULTI;1405 pWait->pSession = NULL;1406 RTMemFree(pWait);1407 }1408 }1409 1410 1411 /**1412 1580 * Destroys the VBoxGuest device extension. 1413 1581 * … … 1419 1587 void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt) 1420 1588 { 1421 int rc2;1422 1589 Log(("VGDrvCommonDeleteDevExt:\n")); 1423 1590 Log(("VBoxGuest: The additions driver is terminating.\n")); 1424 1425 /* 1426 * Stop and destroy HB timer and 1427 * disable host heartbeat checking. 1428 */ 1429 if (pDevExt->pHeartbeatTimer) 1430 { 1431 RTTimerDestroy(pDevExt->pHeartbeatTimer); 1432 vgdrvHeartbeatHostConfigure(pDevExt, false); 1433 } 1434 1435 VbglR0GRFree(pDevExt->pReqGuestHeartbeat); 1436 pDevExt->pReqGuestHeartbeat = NULL; 1437 1438 /* 1439 * Clean up the bits that involves the host first. 1440 */ 1441 vgdrvTermUnfixGuestMappings(pDevExt); 1442 if (!RTListIsEmpty(&pDevExt->SessionList)) 1443 { 1444 LogRelFunc(("session list not empty!\n")); 1445 RTListInit(&pDevExt->SessionList); 1446 } 1447 /* Update the host flags (mouse status etc) not to reflect this session. */ 1448 pDevExt->fFixedEvents = 0; 1449 vgdrvResetEventFilterOnHost(pDevExt, 0 /*fFixedEvents*/); 1450 vgdrvResetCapabilitiesOnHost(pDevExt); 1451 vgdrvResetMouseStatusOnHost(pDevExt); 1452 1453 vgdrvCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL); 1454 1455 /* 1456 * Cleanup all the other resources. 1457 */ 1458 rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2); 1459 rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2); 1460 rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2); 1461 1462 vgdrvDeleteWaitList(&pDevExt->WaitList); 1463 #ifdef VBOX_WITH_HGCM 1464 vgdrvDeleteWaitList(&pDevExt->HGCMWaitList); 1465 #endif 1466 #ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP 1467 vgdrvDeleteWaitList(&pDevExt->WakeUpList); 1468 #endif 1469 vgdrvDeleteWaitList(&pDevExt->WokenUpList); 1470 vgdrvDeleteWaitList(&pDevExt->FreeList); 1471 1472 VbglR0TerminatePrimary(); 1473 1474 pDevExt->pVMMDevMemory = NULL; 1475 1476 pDevExt->IOPortBase = 0; 1477 pDevExt->pIrqAckEvents = NULL; 1478 1479 #ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER 1480 RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); 1481 RTLogDestroy(RTLogSetDefaultInstance(NULL)); 1482 #endif 1483 1591 VGDrvCommonDeleteDevExtResources(pDevExt); 1592 VGDrvCommonDeleteDevExtFundament(pDevExt); 1593 VGDrvCommonDestroyLoggers(); 1484 1594 } 1485 1595 -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h
r70094 r70223 140 140 typedef struct VBOXGUESTDEVEXT 141 141 { 142 /** VBOXGUESTDEVEXT_INIT_STATE_XXX. */ 143 uint32_t uInitState; 142 144 /** The base of the adapter I/O ports. */ 143 145 RTIOPORT IOPortBase; … … 251 253 typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT; 252 254 255 /** @name VBOXGUESTDEVEXT_INIT_STATE_XXX - magic values for validating init 256 * state of the device extension structur. 257 * @{ */ 258 #define VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT UINT32_C(0x0badcafe) 259 #define VBOXGUESTDEVEXT_INIT_STATE_RESOURCES UINT32_C(0xcafebabe) 260 #define VBOXGUESTDEVEXT_INIT_STATE_DELETED UINT32_C(0xdeadd0d0) 261 /** @} */ 253 262 254 263 /** … … 325 334 int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO, 326 335 VBOXOSTYPE enmOSType, uint32_t fEvents); 336 void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt); 337 338 int VGDrvCommonInitLoggers(void); 339 void VGDrvCommonDestroyLoggers(void); 340 int VGDrvCommonInitDevExtFundament(PVBOXGUESTDEVEXT pDevExt); 341 void VGDrvCommonDeleteDevExtFundament(PVBOXGUESTDEVEXT pDevExt); 342 int VGDrvCommonInitDevExtResources(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, 343 void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents); 344 void VGDrvCommonDeleteDevExtResources(PVBOXGUESTDEVEXT pDevExt); 345 int VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType); 346 327 347 bool VBDrvCommonIsOptionValueTrue(const char *pszValue); 328 348 void VGDrvCommonProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue); … … 330 350 bool VGDrvCommonIsOurIRQ(PVBOXGUESTDEVEXT pDevExt); 331 351 bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt); 332 void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt); 333 int VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType); 352 334 353 #ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP 335 354 void VGDrvCommonWaitDoWakeUps(PVBOXGUESTDEVEXT pDevExt);
Note:
See TracChangeset
for help on using the changeset viewer.