VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxPci/VBoxPci.c@ 35959

Last change on this file since 35959 was 35959, checked in by vboxsync, 14 years ago

PCI: further R0/driver work

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/* $Id $ */
2/** @file
3 * VBoxPci - PCI card passthrough support (Host), Common Code.
4 */
5
6/*
7 * Copyright (C) 2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @page pg_rawpci VBoxPci - host PCI support
19 *
20 * This is a kernel module that works as host proxy between guest and
21 * PCI hardware.
22 *
23 */
24
25#define LOG_GROUP LOG_GROUP_DEV_PCI_RAW
26#include <VBox/log.h>
27#include <VBox/err.h>
28#include <VBox/sup.h>
29#include <VBox/version.h>
30
31#include <iprt/string.h>
32#include <iprt/assert.h>
33#include <iprt/spinlock.h>
34#include <iprt/uuid.h>
35#include <iprt/asm.h>
36#include <iprt/mem.h>
37
38#include "VBoxPciInternal.h"
39
40
41/**
42 * Implements the SUPDRV component factor interface query method.
43 *
44 * @returns Pointer to an interface. NULL if not supported.
45 *
46 * @param pSupDrvFactory Pointer to the component factory registration structure.
47 * @param pSession The session - unused.
48 * @param pszInterfaceUuid The factory interface id.
49 */
50static DECLCALLBACK(void *) vboxPciQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
51{
52 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, SupDrvFactory));
53
54 /*
55 * Convert the UUID strings and compare them.
56 */
57 RTUUID UuidReq;
58 int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
59 if (RT_SUCCESS(rc))
60 {
61 if (!RTUuidCompareStr(&UuidReq, RAWPCIFACTORY_UUID_STR))
62 {
63 ASMAtomicIncS32(&pGlobals->cFactoryRefs);
64 return &pGlobals->RawPciFactory;
65 }
66 }
67 else
68 Log(("VBoxRawPci: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
69
70 return NULL;
71}
72
73/**
74 * @copydoc RAWPCIDEVPORT:: pfnRetain
75 */
76DECLHIDDEN(void) vboxPciDevRetain(PRAWPCIDEVPORT pThis)
77{
78}
79
80/**
81 * @copydoc RAWPCIDEVPORT:: pfnRelease
82 */
83DECLHIDDEN(void) vboxPciDevRelease(PRAWPCIDEVPORT pThis)
84{
85}
86
87/**
88 * @copydoc RAWPCIDEVPORT:: pfnRelease
89 */
90DECLHIDDEN(int) vboxPciDevInit(PRAWPCIDEVPORT pThis, uint32_t fFlags)
91{
92 return VINF_SUCCESS;
93}
94
95
96/**
97 * Creates a new instance.
98 *
99 * @returns VBox status code.
100 * @param pGlobals The globals.
101 * @param pszName The instance name.
102 * @param ppDevPort Where to store the pointer to our port interface.
103 */
104static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
105 uint32_t u32HostAddress,
106 uint32_t fFlags,
107 PRAWPCIDEVPORT *ppDevPort)
108{
109 int rc;
110 PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
111 if (!pNew)
112 return VERR_NO_MEMORY;
113
114 pNew->pGlobals = pGlobals;
115 pNew->hSpinlock = NIL_RTSPINLOCK;
116 pNew->cRefs = 1;
117 pNew->pNext = NULL;
118 pNew->HostPciAddress = u32HostAddress;
119
120 pNew->DevPort.u32Version = RAWPCIDEVPORT_VERSION;
121 pNew->DevPort.pfnRetain = vboxPciDevRetain;
122 pNew->DevPort.pfnRelease = vboxPciDevRelease;
123 pNew->DevPort.pfnInit = vboxPciDevInit;
124 pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
125
126 rc = RTSpinlockCreate(&pNew->hSpinlock);
127
128 if (RT_SUCCESS(rc))
129 {
130 rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
131 if (RT_SUCCESS(rc))
132 {
133 *ppDevPort = &pNew->DevPort;
134 }
135 else
136 {
137 RTSpinlockDestroy(pNew->hSpinlock);
138 RTMemFree(pNew);
139 }
140 return rc;
141 }
142
143 return rc;
144}
145
146
147/**
148 * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
149 */
150static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
151 uint32_t u32HostAddress,
152 uint32_t fFlags,
153 PRAWPCIDEVPORT *ppDevPort)
154{
155 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
156 int rc;
157
158 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
159 Assert(pGlobals->cFactoryRefs > 0);
160 rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
161 AssertRCReturn(rc, rc);
162
163 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, ppDevPort);
164
165 RTSemFastMutexRelease(pGlobals->hFastMtx);
166
167 return rc;
168}
169
170/**
171 * @copydoc RAWPCIFACTORY::pfnRelease
172 */
173static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
174{
175 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
176
177 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
178 Assert(cRefs >= 0); NOREF(cRefs);
179 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
180}
181
182
183
184
185static DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
186{
187 int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
188 bool fRc = !pGlobals->pInstanceHead
189 && pGlobals->cFactoryRefs <= 0;
190 RTSemFastMutexRelease(pGlobals->hFastMtx);
191 AssertRC(rc);
192 return fRc;
193}
194
195
196static DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
197{
198 int rc;
199 Assert(!pGlobals->fIDCOpen);
200
201 /*
202 * Establish a connection to SUPDRV and register our component factory.
203 */
204 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
205 if (RT_SUCCESS(rc))
206 {
207 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
208 if (RT_SUCCESS(rc))
209 {
210 pGlobals->fIDCOpen = true;
211 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
212 return rc;
213 }
214
215 /* bail out. */
216 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
217 SUPR0IdcClose(&pGlobals->SupDrvIDC);
218 }
219
220 return rc;
221}
222
223/**
224 * Try to close the IDC connection to SUPDRV if established.
225 *
226 * @returns VBox status code.
227 * @retval VINF_SUCCESS on success.
228 * @retval VERR_WRONG_ORDER if we're busy.
229 *
230 * @param pGlobals Pointer to the globals.
231 */
232DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
233{
234 int rc;
235
236 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
237
238 /*
239 * Check before trying to deregister the factory.
240 */
241 if (!vboxPciCanUnload(pGlobals))
242 return VERR_WRONG_ORDER;
243
244 if (!pGlobals->fIDCOpen)
245 rc = VINF_SUCCESS;
246 else
247 {
248 /*
249 * Disconnect from SUPDRV.
250 */
251 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
252 AssertRC(rc);
253 SUPR0IdcClose(&pGlobals->SupDrvIDC);
254 pGlobals->fIDCOpen = false;
255 }
256
257 return rc;
258}
259
260
261/**
262 * Initializes the globals.
263 *
264 * @returns VBox status code.
265 * @param pGlobals Pointer to the globals.
266 */
267DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
268{
269 /*
270 * Initialize the common portions of the structure.
271 */
272 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
273 if (RT_SUCCESS(rc))
274 {
275 pGlobals->pInstanceHead = NULL;
276 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
277 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
278 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
279 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
280 pGlobals->fIDCOpen = false;
281 }
282 return rc;
283}
284
285
286/**
287 * Deletes the globals.
288 *
289 *
290 * @param pGlobals Pointer to the globals.
291 */
292DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
293{
294 Assert(!pGlobals->fIDCOpen);
295
296 /*
297 * Release resources.
298 */
299 if (pGlobals->hFastMtx)
300 {
301 RTSemFastMutexDestroy(pGlobals->hFastMtx);
302 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
303 }
304}
305
306
307int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
308{
309
310 /*
311 * Initialize the common portions of the structure.
312 */
313 int rc = vboxPciInitGlobals(pGlobals);
314 if (RT_SUCCESS(rc))
315 {
316 rc = vboxPciInitIdc(pGlobals);
317 if (RT_SUCCESS(rc))
318 return rc;
319
320 /* bail out. */
321 vboxPciDeleteGlobals(pGlobals);
322 }
323
324 return rc;
325}
326
327void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
328{
329 int rc = vboxPciDeleteIdc(pGlobals);
330
331 if (RT_SUCCESS(rc))
332 vboxPciDeleteGlobals(pGlobals);
333}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette