VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxGuest/NTLegacy.cpp@ 31364

Last change on this file since 31364 was 31364, checked in by vboxsync, 15 years ago

Some more fixes for Guest Additions version lookup/status; moved some duplicate helper function to VbglR0.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1/** @file
2 *
3 * VBoxGuest -- VirtualBox Win32 guest support driver
4 *
5 * Copyright (C) 2006-2007 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16// enable backdoor logging
17//#define LOG_ENABLED
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include "NTLegacy.h"
23#include "Helper.h"
24
25#include <VBox/VBoxGuestLib.h>
26
27/*******************************************************************************
28* Defined Constants And Macros *
29*******************************************************************************/
30
31
32/*******************************************************************************
33* Internal Functions *
34*******************************************************************************/
35extern "C"
36{
37static NTSTATUS findPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber);
38static void freeDeviceResources(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
39}
40
41#ifdef ALLOC_PRAGMA
42#pragma alloc_text (INIT, ntCreateDevice)
43#pragma alloc_text (INIT, findPCIDevice)
44#pragma alloc_text (INIT, freeDeviceResources)
45#endif
46
47/**
48 * Helper function to create the device object
49 *
50 * @returns NT status code
51 * @param
52 */
53NTSTATUS ntCreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
54{
55 ULONG busNumber, slotNumber;
56 int vrc = VINF_SUCCESS;
57 NTSTATUS rc = STATUS_SUCCESS;
58
59 dprintf(("VBoxGuest::ntCreateDevice: entered, pDrvObj=%x, pDevObj=%x, pRegPath=%x\n",
60 pDrvObj, pDevObj, pRegPath));
61
62 /*
63 * Find our virtual PCI device
64 */
65 rc = findPCIDevice(&busNumber, (PCI_SLOT_NUMBER*)&slotNumber);
66 if (!NT_SUCCESS(rc))
67 {
68 dprintf(("VBoxGuest::createDevice: device not found, returning\n"));
69 return rc;
70 }
71
72 /*
73 * Create device.
74 */
75 PDEVICE_OBJECT deviceObject = NULL;
76 UNICODE_STRING DevName;
77 RtlInitUnicodeString(&DevName, VBOXGUEST_DEVICE_NAME_NT);
78 rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
79 if (!NT_SUCCESS(rc))
80 {
81 dprintf(("VBoxGuest::ntCreateDevice: IoCreateDevice failed with rc=%#x!\n", rc));
82 return rc;
83 }
84 dprintf(("VBoxGuest::ntCreateDevice: device created\n"));
85 UNICODE_STRING DosName;
86 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
87 rc = IoCreateSymbolicLink(&DosName, &DevName);
88 if (!NT_SUCCESS(rc))
89 {
90 dprintf(("VBoxGuest::ntCreateDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc));
91 IoDeleteDevice(deviceObject);
92 return rc;
93 }
94 dprintf(("VBoxGuest::ntCreateDevice: symlink created\n"));
95
96 /*
97 * Setup the device extension.
98 */
99 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)deviceObject->DeviceExtension;
100 RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT));
101
102 if (pDevObj) /* pDevObj always is NULL at the moment, so don't attach to the driver stack */
103 {
104 pDevExt->nextLowerDriver = IoAttachDeviceToDeviceStack(deviceObject, pDevObj);
105 if (pDevExt->nextLowerDriver == NULL)
106 {
107 dprintf(("VBoxGuest::ntCreateDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDrive\n"));
108 IoDeleteSymbolicLink(&DosName);
109 IoDeleteDevice(deviceObject);
110 return STATUS_NO_SUCH_DEVICE;
111 }
112 dprintf(("VBoxGuest::ntCreateDevice: device attached to stack\n"));
113 }
114
115#ifdef VBOX_WITH_HGCM
116 /* Create global spinlock for all driver sessions */
117 int rc2 = RTSpinlockCreate(&pDevExt->SessionSpinlock);
118 if (RT_FAILURE(rc2))
119 {
120 dprintf(("VBoxGuest::ntCreateDevice: RTSpinlockCreate failed\n"));
121 IoDetachDevice(pDevExt->nextLowerDriver);
122 IoDeleteSymbolicLink(&DosName);
123 IoDeleteDevice(deviceObject);
124 return STATUS_DRIVER_UNABLE_TO_LOAD;
125 }
126 dprintf(("VBoxGuest::ntCreateDevice: spinlock created\n"));
127#endif
128
129 /* Store a reference to ourself */
130 pDevExt->deviceObject = deviceObject;
131 /* Store bus and slot number we've queried before */
132 pDevExt->busNumber = busNumber;
133 pDevExt->slotNumber = slotNumber;
134
135#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
136 rc = hlpRegisterBugCheckCallback(pDevExt);
137#endif
138
139 //
140 // let's have a look at what our PCI adapter offers
141 //
142 dprintf(("VBoxGuest::ntCreateDevice: starting to scan PCI resources of VBoxGuest\n"));
143 // assign the PCI resources
144 PCM_RESOURCE_LIST resourceList;
145 UNICODE_STRING classNameString;
146 RtlInitUnicodeString(&classNameString, L"VBoxGuestAdapter");
147 rc = HalAssignSlotResources(pRegPath, &classNameString,
148 pDrvObj, pDevObj,
149 PCIBus, busNumber, slotNumber,
150 &resourceList);
151 if (!NT_SUCCESS(rc))
152 {
153 dprintf(("VBoxGuest::ntCreateDevice: HalAssignSlotResources failed with rc=%#x!\n", rc));
154 freeDeviceResources(pDrvObj, pDevObj);
155 return rc;
156 }
157
158 rc = VBoxScanPCIResourceList(resourceList, pDevExt);
159
160 rc = VbglInit (pDevExt->startPortAddress, pDevExt->pVMMDevMemory);
161 if (!RT_SUCCESS(rc))
162 {
163 dprintf(("VBoxGuest::START_DEVICE: VbglInit failed. rc = %d\n", rc));
164 }
165
166
167 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pDevExt->irqAckEvents, sizeof (VMMDevEvents), VMMDevReq_AcknowledgeEvents);
168 if (!RT_SUCCESS(rc))
169 {
170 dprintf(("VBoxGuest::START_DEVICE: VbglAlloc failed for irqAckEvents. rc = %d\n", rc));
171 }
172 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pDevExt->powerStateRequest, sizeof (VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
173 if (!RT_SUCCESS(rc))
174 {
175 dprintf(("VBoxGuest::START_DEVICE: VbglAlloc failed for powerStateRequest. rc = %d\n", rc));
176 }
177
178#if 0
179 //
180 // now proceed to the busmaster DMA stuff
181 //
182
183 DEVICE_DESCRIPTION deviceDescription;
184 ULONG numberOfMapRegisters;
185 deviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
186 deviceDescription.Master = TRUE;
187 deviceDescription.ScatterGather = TRUE;
188 deviceDescription.BusNumber = pDevExt->busNumber;
189 deviceDescription.InterfaceType = PCIBus;
190 deviceDescription.MaximumLength = MAXIMUM_TRANSFER_LENGTH;
191 pDevExt->adapterObject = HalGetAdapter(&deviceDescription, &numberOfMapRegisters);
192 if (pDevExt->adapterObject == NULL)
193 {
194 dprintf(("VBoxGuest::ntCreateDevice: HalGetAdapter failed!\n"));
195 freeDeviceResources(pDrvObj, pDevObj);
196 return rc;
197 }
198
199 // @todo allocate S/G buffer
200#endif
201
202
203 //
204 // it's time to map the I/O and memory spaces
205 //
206
207 // Map physical address of VMMDev memory
208 rc = hlpVBoxMapVMMDevMemory (pDevExt);
209 if (!NT_SUCCESS(rc))
210 {
211 dprintf(("VBoxGuest::ntCreateDevice: Unable to map VMMDev Memory, rc=%#x!\n", rc));
212 freeDeviceResources(pDrvObj, pDevObj);
213 return rc;
214 }
215
216 //
217 // now we need an ISR and DPC
218 //
219
220 // register DPC routine
221 dprintf(("VBoxGuest::ntCreateDevice: initializing DPC...\n"));
222 IoInitializeDpcRequest(pDevExt->deviceObject, VBoxGuestDpcHandler);
223 // get an interrupt vector
224 ULONG vector;
225 KIRQL irql;
226 KAFFINITY affinity;
227 // only proceed if the device provides an interrupt
228 if (pDevExt->interruptLevel || pDevExt->interruptVector)
229 {
230 vector = HalGetInterruptVector(PCIBus,
231 pDevExt->busNumber,
232 pDevExt->interruptLevel,
233 pDevExt->interruptVector,
234 &irql,
235 &affinity);
236 dprintf(("VBoxGuest::ntCreateDevice: HalGetInterruptVector returns vector %u\n", vector));
237 rc = IoConnectInterrupt(&pDevExt->interruptObject, // out: interrupt object
238 (PKSERVICE_ROUTINE)VBoxGuestIsrHandler, // ISR
239 pDevExt, // context
240 NULL, // optional spinlock
241 vector, // interrupt vector
242 irql, // interrupt level
243 irql, // interrupt level
244 pDevExt->interruptMode, // LevelSensitive or Latched
245 TRUE, // shareable interrupt
246 affinity, // CPU affinity
247 FALSE); // don't save FPU stack
248 if (!NT_SUCCESS(rc))
249 {
250 dprintf(("VBoxGuest::ntCreateDevice: Unable to connect interrupt, rc=%#x!\n", rc));
251 pDevExt->interruptObject = NULL;
252 freeDeviceResources(pDrvObj, pDevObj);
253 return rc;
254 }
255 dprintf(("VBoxGuest::ntCreateDevice: IRQ connected!\n"));
256 }
257
258 if (NT_SUCCESS(rc))
259 {
260 // create our thread to inform the VBoxMouse driver
261 rc = createThreads(pDevExt);
262 }
263
264 if (NT_SUCCESS(rc))
265 {
266 // initialize the event notification semaphore
267 KeInitializeEvent(&pDevExt->keventNotification, NotificationEvent, FALSE);
268
269 /* Preallocated constant timeout 250ms for HGCM async waiter. */
270 pDevExt->HGCMWaitTimeout.QuadPart = 250;
271 pDevExt->HGCMWaitTimeout.QuadPart *= -10000; /* relative in 100ns units */
272 }
273
274 /** @todo Cleanup on failure. */
275
276 /** @todo Don't mix up IPRT rc and NTSTATUS rc above! */
277
278 vrc = VBoxInitMemBalloon(pDevExt);
279 if (RT_SUCCESS(vrc))
280 {
281 vrc = VbglR0MiscReportGuestInfo(hlpVBoxWinVersionToOSType(winVersion));
282 if (RT_FAILURE(vrc))
283 dprintf(("VBoxGuest::ntCreateDevice: could not report information to host, rc = %d, exiting!\n", rc));
284 }
285
286 if ( NT_ERROR(rc)
287 || RT_FAILURE(vrc))
288 {
289 freeDeviceResources(pDrvObj, pDevObj);
290 return STATUS_UNSUCCESSFUL;
291 }
292
293 // ready to rumble!
294 pDevExt->devState = WORKING;
295 dprintf(("returning from ntCreateDevice with rc = 0x%x\n, vrc = %Rrc", rc, vrc));
296 return rc;
297}
298
299
300/**
301 * Helper function to handle the PCI device lookup
302 *
303 * @returns NT error codes
304 */
305static NTSTATUS findPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber)
306{
307 NTSTATUS rc;
308
309 ULONG busNumber;
310 ULONG deviceNumber;
311 ULONG functionNumber;
312 PCI_SLOT_NUMBER slotNumber;
313 PCI_COMMON_CONFIG pciData;
314
315 dprintf(("findPCIDevice\n"));
316
317 rc = STATUS_DEVICE_DOES_NOT_EXIST;
318 slotNumber.u.AsULONG = 0;
319 // scan each bus
320 for (busNumber = 0; busNumber < PCI_MAX_BUSES; busNumber++)
321 {
322 // scan each device
323 for (deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)
324 {
325 slotNumber.u.bits.DeviceNumber = deviceNumber;
326 // scan each function (not really required...)
327 for (functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)
328 {
329 slotNumber.u.bits.FunctionNumber = functionNumber;
330 // have a look at what's in this slot
331 if (!HalGetBusData(PCIConfiguration, busNumber, slotNumber.u.AsULONG,
332 &pciData, sizeof(ULONG)))
333 {
334 // no such bus, we're done with it
335 deviceNumber = PCI_MAX_DEVICES;
336 break;
337 }
338
339 if (pciData.VendorID == PCI_INVALID_VENDORID)
340 {
341 // we have to proceed to the next function
342 continue;
343 }
344
345 // check if it's another device
346 if ((pciData.VendorID != VMMDEV_VENDORID) ||
347 (pciData.DeviceID != VMMDEV_DEVICEID))
348 {
349 continue;
350 }
351
352 // Hooray, we've found it!
353 dprintf(("device found!\n"));
354 *pBusNumber = busNumber;
355 *pSlotNumber = slotNumber;
356 rc = STATUS_SUCCESS;
357 }
358 }
359 }
360
361 return rc;
362}
363
364/**
365 * Helper function to cleanup resources
366 *
367 * @param pDrvObj Driver object.
368 * @param pDevObj Device object.
369 */
370static void freeDeviceResources(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
371{
372 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
373
374 // if there's no device extension, we're screwed
375 if (!pDevExt)
376 {
377 dprintf(("freeDeviceResources: FATAL ERROR! device extension pointer is NULL! Not freeing resources!\n"));
378 return;
379 }
380
381 // indicate that the device is no longer ready
382 pDevExt->devState = STOPPED;
383
384 // disconnect interrupts
385 if (pDevExt->interruptObject)
386 {
387 IoDisconnectInterrupt(pDevExt->interruptObject);
388 }
389
390 // unmap mem/io resources
391 hlpVBoxUnmapVMMDevMemory (pDevExt);
392
393 VBoxCleanupMemBalloon(pDevExt);
394}
395
Note: See TracBrowser for help on using the repository browser.

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