VirtualBox

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

Last change on this file since 31517 was 31517, checked in by vboxsync, 14 years ago

VBoxGuest: VBoxGuest2.cpp/h, fixed file headers, moved comments to the right place, corrected the function prefix.

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