VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 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 // ready to rumble!
253 pDevExt->devState = WORKING;
254 dprintf(("returning from createDevice with rc = 0x%x\n", rc));
255 return rc;
256}
257
258
259/**
260 * Helper function to handle the PCI device lookup
261 *
262 * @returns NT error codes
263 */
264static NTSTATUS findPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber)
265{
266 NTSTATUS rc;
267
268 ULONG busNumber;
269 ULONG deviceNumber;
270 ULONG functionNumber;
271 PCI_SLOT_NUMBER slotNumber;
272 PCI_COMMON_CONFIG pciData;
273
274 dprintf(("findPCIDevice\n"));
275
276 rc = STATUS_DEVICE_DOES_NOT_EXIST;
277 slotNumber.u.AsULONG = 0;
278 // scan each bus
279 for (busNumber = 0; busNumber < PCI_MAX_BUSES; busNumber++)
280 {
281 // scan each device
282 for (deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)
283 {
284 slotNumber.u.bits.DeviceNumber = deviceNumber;
285 // scan each function (not really required...)
286 for (functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)
287 {
288 slotNumber.u.bits.FunctionNumber = functionNumber;
289 // have a look at what's in this slot
290 if (!HalGetBusData(PCIConfiguration, busNumber, slotNumber.u.AsULONG,
291 &pciData, sizeof(ULONG)))
292 {
293 // no such bus, we're done with it
294 deviceNumber = PCI_MAX_DEVICES;
295 break;
296 }
297
298 if (pciData.VendorID == PCI_INVALID_VENDORID)
299 {
300 // we have to proceed to the next function
301 continue;
302 }
303
304 // check if it's another device
305 if ((pciData.VendorID != VMMDEV_VENDORID) ||
306 (pciData.DeviceID != VMMDEV_DEVICEID))
307 {
308 continue;
309 }
310
311 // Hooray, we've found it!
312 dprintf(("device found!\n"));
313 *pBusNumber = busNumber;
314 *pSlotNumber = slotNumber;
315 rc = STATUS_SUCCESS;
316 }
317 }
318 }
319
320 return rc;
321}
322
323/**
324 * Helper function to cleanup resources
325 *
326 * @param pDrvObj Driver object.
327 * @param pDevObj Device object.
328 */
329static void freeDeviceResources(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
330{
331 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
332
333 // if there's no device extension, we're screwed
334 if (!pDevExt)
335 {
336 dprintf(("freeDeviceResources: FATAL ERROR! device extension pointer is NULL! Not freeing resources!\n"));
337 return;
338 }
339
340 // indicate that the device is no longer ready
341 pDevExt->devState = STOPPED;
342
343 // disconnect interrupts
344 if (pDevExt->interruptObject)
345 {
346 IoDisconnectInterrupt(pDevExt->interruptObject);
347 }
348
349 // unmap mem/io resources
350 hlpVBoxUnmapVMMDevMemory (pDevExt);
351}
352
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