VirtualBox

Changeset 70223 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 19, 2017 5:10:59 PM (7 years ago)
Author:
vboxsync
Message:

VBoxGuest: Split up VGDrvCommonInitDevExt to accommodate plug-and-play on windows. This should fix some error cleanup path issues on windows.

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  
    149149    /** Preallocated generic request for shutdown. */
    150150    VMMDevPowerStateRequest *pPowerStateRequest;
    151     /** Preallocated VMMDevEvents for IRQ handler. */
    152     VMMDevEvents           *pIrqAckEvents;
    153151
    154152    /** Spinlock protecting MouseNotifyCallback. Required since the consumer is
     
    191189static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    192190static void     vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt);
    193 static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj);
    194191static void     vgdrvNtUnload(PDRIVER_OBJECT pDrvObj);
    195192static NTSTATUS vgdrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     
    263260        return STATUS_UNSUCCESSFUL;
    264261    }
     262    VGDrvCommonInitLoggers();
    265263
    266264    LogFunc(("Driver built: %s %s\n", __DATE__, __TIME__));
     
    400398                return rcNt;
    401399            }
    402 
    403400        }
    404401    }
     
    408405     */
    409406    LogRelFunc(("Failed! rcNt=%#x\n", rcNt));
     407    VGDrvCommonDestroyLoggers();
    410408    RTR0Term();
    411409    return rcNt;
     
    513511
    514512/**
    515  * Global initialization stuff.
     513 * Sets up the device and its resources.
    516514 *
    517515 * @param   pDevExt     Our device extension data.
     
    521519 * @param   pRegPath    The registry path for NT4, NULL for NT5+.
    522520 */
    523 static NTSTATUS vgdrvNtInit(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj,
    524                             PIRP pIrp, PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
     521static NTSTATUS vgdrvNtSetupDevice(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj,
     522                                   PIRP pIrp, PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
    525523{
    526524    LogFlowFunc(("ENTER: pDevExt=%p pDevObj=%p pIrq=%p pDrvObj=%p pRegPath=%p\n", pDevExt, pDevObj, pIrp, pDrvObj, pRegPath));
     
    588586                     pvMMIOBase, pDevExt, pDevExt ? pDevExt->Core.pVMMDevMemory : NULL));
    589587
    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);
    595593            if (RT_SUCCESS(vrc))
    596594            {
     595
    597596                vrc = VbglR0GRAlloc((VMMDevRequestHeader **)&pDevExt->pPowerStateRequest,
    598597                                    sizeof(VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
     
    674673                }
    675674
    676                 VGDrvCommonDeleteDevExt(&pDevExt->Core);
     675                VGDrvCommonDeleteDevExtResources(&pDevExt->Core);
    677676            }
    678677            else
    679678            {
    680                 LogFunc(("Could not init device extension, vrc=%Rrc\n", vrc));
     679                LogFunc(("Could not init device extension resources: vrc=%Rrc\n", vrc));
    681680                rcNt = STATUS_DEVICE_CONFIGURATION_ERROR;
    682681            }
     
    695694
    696695#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 */
     705static 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
    697757
    698758/**
     
    742802             */
    743803            Log(("vgdrvNt4CreateDevice: Setting up device extension ...\n"));
    744 
    745804            PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
    746805            RT_ZERO(*pDevExt);
    747 
    748             Log(("vgdrvNt4CreateDevice: Device extension created\n"));
    749806
    750807            /* Store a reference to ourself. */
     
    755812            pDevExt->uSlot = uSlot.u.AsULONG;
    756813
     814            /* Initialize common bits. */
     815            int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core);
     816            if (RT_SUCCESS(vrc))
     817            {
     818                Log(("vgdrvNt4CreateDevice: Device extension created\n"));
    757819# ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
    758             rc = hlpRegisterBugCheckCallback(pDevExt);
     820                rc = hlpRegisterBugCheckCallback(pDevExt);
    759821# endif
    760             if (NT_SUCCESS(rc))
    761             {
    762                 /* Do the actual VBox init ... */
    763                 rc = vgdrvNtInit(pDevExt, pDeviceObject, NULL /*pIrp*/, pDrvObj, pRegPath);
    764822                if (NT_SUCCESS(rc))
    765823                {
    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 */
    768833                }
    769 
    770                 /* bail out */
     834                VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
    771835            }
    772836            IoDeleteSymbolicLink(&DosName);
     
    780844    Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x\n", rc));
    781845    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_VENDORID
    828                     || 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;
    843846}
    844847
     
    882885
    883886            KeInitializeSpinLock(&pDevExt->MouseEventAccessSpinLock);
    884 
    885887            pDevExt->pDeviceObject   = pDeviceObject;
    886888            pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED;
    887889            pDevExt->enmDevState     = VGDRVNTDEVSTATE_STOPPED;
    888890
    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                     */
    896901#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
    897                 vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */
     902                    vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */
    898903#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
    900918                {
    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;
    908921                }
    909 
    910                 IoDetachDevice(pDevExt->pNextLowerDriver);
     922                VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
    911923            }
    912924            else
    913             {
    914                 LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
    915                 rcNt = STATUS_DEVICE_NOT_CONNECTED;
    916             }
     925                rcNt = STATUS_UNSUCCESSFUL;
    917926
    918927            /* bail out */
     
    979988    Log(("vgdrvNt5PlusPnPSendIrpSynchronously: Returning %#x\n", rcNt));
    980989    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 */
     1000static 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 */
     1021static 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);
    9811042}
    9821043
     
    10391100                Log(("vgdrvNtNt5PlusPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n",
    10401101                     pStack->Parameters.StartDevice.AllocatedResources));
    1041 
    10421102                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                }
    10441108                else
    10451109                {
     
    10491113                }
    10501114            }
    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;
    10541122        }
    10551123
     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         */
    10561168        case IRP_MN_CANCEL_REMOVE_DEVICE:
    10571169        {
     
    10681180
    10691181            /* Complete the IRP. */
    1070             break;
     1182            pIrp->IoStatus.Status = rc;
     1183            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     1184            return rc;
    10711185        }
    10721186
     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         */
    10731191        case IRP_MN_SURPRISE_REMOVAL:
    10741192        {
    10751193            Log(("vgdrvNtNt5PlusPnP: IRP_MN_SURPRISE_REMOVAL\n"));
    1076 
    10771194            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              */
    10821195            LogRel(("VBoxGuest: unexpected device removal\n"));
    10831196
     
    10861199
    10871200            IoSkipCurrentIrpStackLocation(pIrp);
    1088 
    10891201            rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
    10901202
     
    10931205        }
    10941206
    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         */
    11261210        case IRP_MN_REMOVE_DEVICE:
    11271211        {
    11281212            Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE\n"));
    1129 
    11301213            VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_REMOVED);
    11311214
    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 
    11381215            /*
    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).
    11421224             */
    11431225            pIrp->IoStatus.Status = STATUS_SUCCESS;
    11441226
    11451227            IoSkipCurrentIrpStackLocation(pIrp);
    1146 
    11471228            rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
    11481229            Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
    11491230
    11501231            IoDetachDevice(pDevExt->pNextLowerDriver);
    1151 
    11521232            Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Removing device ...\n"));
    11531233
    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 */
    11671241
    11681242            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. */
    11721244        }
    11731245
     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         */
    11741287        case IRP_MN_CANCEL_STOP_DEVICE:
    11751288        {
     
    11861299
    11871300            /* Complete the IRP. */
    1188             break;
     1301            pIrp->IoStatus.Status = rc;
     1302            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     1303            return rc;
    11891304        }
    11901305
    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         */
    12221309        case IRP_MN_STOP_DEVICE:
    12231310        {
    12241311            Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE\n"));
    1225 
    12261312            VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_STOPPED);
    12271313
    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             */
    12351322            pIrp->IoStatus.Status = STATUS_SUCCESS;
    1236 
    12371323            IoSkipCurrentIrpStackLocation(pIrp);
    1238 
    12391324            rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
    12401325            Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
    1241 
    12421326            return rc;
    12431327        }
     
    12471331            IoSkipCurrentIrpStackLocation(pIrp);
    12481332            rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
     1333            Log(("vgdrvNtNt5PlusPnP: Unknown request %#x: Lower driver replied: %x\n", pStack->MinorFunction, rc));
    12491334            return rc;
    12501335        }
    12511336    }
    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;
    12581337}
    12591338
     
    15051584
    15061585/**
    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 */
     1590static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj)
    15201591{
    15211592    LogFlowFuncEnter();
    15221593
    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)
    15271602        {
    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);
    15301610        }
    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    }
    15711612#else  /* !TARGET_NT4 */
    15721613    /*
     
    15771618#endif /* !TARGET_NT4 */
    15781619
     1620    VGDrvCommonDestroyLoggers();
    15791621    RTR0Term();
    15801622    LogFlowFunc(("Returning\n"));
     
    19822024        {
    19832025            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. */
    19852027        }
    19862028    }
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r70154 r70223  
    924924
    925925/**
    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 */
     930int VGDrvCommonInitLoggers(void)
     931{
    951932#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
    952933    /*
     
    955936    static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
    956937    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);
    959940    if (RT_SUCCESS(rc))
    960941        RTLogRelSetDefaultInstance(pRelLogger);
    961942    /** @todo Add native hook for getting logger config parameters and setting
    962943     *        them.  On linux we should use the module parameter stuff... */
     944    return rc;
     945#else
     946    return VINF_SUCCESS;
    963947#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 */
     954void VGDrvCommonDestroyLoggers(void)
     955{
     956#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
     957    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
     958    RTLogDestroy(RTLogSetDefaultInstance(NULL));
    970959#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 */
     972int 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));
    971977
    972978    /*
    973979     * Initialize the data.
    974980     */
    975     pDevExt->IOPortBase = IOPortBase;
     981    pDevExt->IOPortBase = UINT16_MAX;
    976982    pDevExt->pVMMDevMemory = NULL;
    977983    pDevExt->hGuestMappings = NIL_RTR0MEMOBJ;
     
    10041010    pDevExt->pReqGuestHeartbeat = NULL;
    10051011
    1006     pDevExt->fFixedEvents = fFixedEvents;
     1012    pDevExt->fFixedEvents = 0;
    10071013    vgdrvBitUsageTrackerClear(&pDevExt->EventFilterTracker);
    10081014    pDevExt->fEventFilterHost = UINT32_MAX;  /* forces a report */
     
    10181024
    10191025    /*
     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 */
     1061void 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 */
     1093int 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    /*
    10201101     * If there is an MMIO region validate the version and size.
    10211102     */
     
    10291110        {
    10301111            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",
    10321113                 pVMMDev, pVMMDev->u32Size, cbMMIO, pVMMDev->u32Version));
    10331114        }
    10341115        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",
    10361117                    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;
    10601118    }
    10611119
     
    10651123     * made by the VMM.
    10661124     */
     1125    pDevExt->IOPortBase = IOPortBase;
    10671126    rc = VbglR0InitPrimary(pDevExt->IOPortBase, (VMMDevMemory *)pDevExt->pVMMDevMemory);
    10681127    if (RT_SUCCESS(rc))
     
    10811140                 * the guest capabilities or mouse status bits set.
    10821141                 */
    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);
    10841147                if (RT_SUCCESS(rc))
    10851148                {
     
    11011164                            rc = vgdrvReportDriverStatus(true /* Driver is active */);
    11021165                            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"));
    11061170                            return VINF_SUCCESS;
    11071171                        }
    1108                         LogRel(("VGDrvCommonInitDevExt: failed to clear mouse status: rc=%Rrc\n", rc));
     1172                        LogRel(("VGDrvCommonInitDevExtResources: failed to clear mouse status: rc=%Rrc\n", rc));
    11091173                    }
    11101174                    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));
    11121176                }
    11131177                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;
    11151180            }
    11161181            else
    1117                 LogRel(("VGDrvCommonInitDevExt: vgdrvReportGuestInfo failed: rc=%Rrc\n", rc));
     1182                LogRel(("VGDrvCommonInitDevExtResources: vgdrvReportGuestInfo failed: rc=%Rrc\n", rc));
    11181183            VbglR0GRFree((VMMDevRequestHeader *)pDevExt->pIrqAckEvents);
    11191184        }
    11201185        else
    1121             LogRel(("VGDrvCommonInitDevExt: VbglR0GRAlloc failed: rc=%Rrc\n", rc));
     1186            LogRel(("VGDrvCommonInitDevExtResources: VbglR0GRAlloc failed: rc=%Rrc\n", rc));
    11221187
    11231188        VbglR0TerminatePrimary();
    11241189    }
    11251190    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 */
     1201static 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 */
     1222void 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);
    11351266#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 */
     1308int 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();
    11361324    return rc; /* (failed) */
    11371325}
     
    13901578
    13911579/**
    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 /**
    14121580 * Destroys the VBoxGuest device extension.
    14131581 *
     
    14191587void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt)
    14201588{
    1421     int rc2;
    14221589    Log(("VGDrvCommonDeleteDevExt:\n"));
    14231590    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();
    14841594}
    14851595
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r70094 r70223  
    140140typedef struct VBOXGUESTDEVEXT
    141141{
     142    /** VBOXGUESTDEVEXT_INIT_STATE_XXX.   */
     143    uint32_t                    uInitState;
    142144    /** The base of the adapter I/O ports. */
    143145    RTIOPORT                    IOPortBase;
     
    251253typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT;
    252254
     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/** @} */
    253262
    254263/**
     
    325334int  VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO,
    326335                           VBOXOSTYPE enmOSType, uint32_t fEvents);
     336void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt);
     337
     338int  VGDrvCommonInitLoggers(void);
     339void VGDrvCommonDestroyLoggers(void);
     340int  VGDrvCommonInitDevExtFundament(PVBOXGUESTDEVEXT pDevExt);
     341void VGDrvCommonDeleteDevExtFundament(PVBOXGUESTDEVEXT pDevExt);
     342int  VGDrvCommonInitDevExtResources(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase,
     343                                    void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents);
     344void VGDrvCommonDeleteDevExtResources(PVBOXGUESTDEVEXT pDevExt);
     345int  VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType);
     346
    327347bool VBDrvCommonIsOptionValueTrue(const char *pszValue);
    328348void VGDrvCommonProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue);
     
    330350bool VGDrvCommonIsOurIRQ(PVBOXGUESTDEVEXT pDevExt);
    331351bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt);
    332 void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt);
    333 int  VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType);
     352
    334353#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
    335354void VGDrvCommonWaitDoWakeUps(PVBOXGUESTDEVEXT pDevExt);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette