VirtualBox

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

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

VBoxGuest: Fixed spinlock creation for NT4.

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