VirtualBox

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

Last change on this file since 4612 was 4612, checked in by vboxsync, 17 years ago

Implemented ballooning on the guest side. (completely untested and disabled)

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