VirtualBox

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

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

InnoTek -> innotek: all the headers and comments.

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