VirtualBox

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

Last change on this file since 25021 was 18019, checked in by vboxsync, 16 years ago

VBoxGuest/Windows: Added bugcheck detection + details (not enabled by default yet).

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