VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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