Changeset 41705 in vbox
- Timestamp:
- Jun 14, 2012 11:41:34 AM (12 years ago)
- Location:
- trunk/src/VBox/Additions
- Files:
-
- 4 added
- 1 deleted
- 2 edited
- 2 copied
- 1 moved
-
common/VBoxGuest/Makefile.kmk (modified) (1 diff)
-
common/VBoxGuest/testcase (deleted)
-
solaris/Makefile.kmk (modified) (1 diff)
-
solaris/Mouse (added)
-
solaris/Mouse/Makefile.kmk (added)
-
solaris/Mouse/deps.s (added)
-
solaris/Mouse/testcase (added)
-
solaris/Mouse/testcase/solaris.h (copied) (copied from trunk/src/VBox/Additions/common/VBoxGuest/testcase/solaris.h ) (2 diffs)
-
solaris/Mouse/testcase/tstVBoxMouse-solaris.c (copied) (copied from trunk/src/VBox/Additions/common/VBoxGuest/testcase/tstVBoxGuest-solaris.c ) (1 diff)
-
solaris/Mouse/vboxmouse.c (moved) (moved from trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris-streams.c ) (51 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
r41683 r41705 213 213 endif 214 214 215 216 if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK)217 ifn1of ($(KBUILD_TARGET), solaris win) # No variadic macros in Visual C++ 2002; Unresolved RTR0AssertPanicSystem on Solaris 11 / gcc 4.5.2.218 PROGRAMS += tstVBoxGuest-solaris219 tstVBoxGuest-solaris_TEMPLATE = VBOXR3TSTEXE220 tstVBoxGuest-solaris_SOURCES = \221 VBoxGuest-solaris-streams.c \222 testcase/tstVBoxGuest-solaris.c223 tstVBoxGuest-solaris_DEFS = TESTCASE224 tstVBoxGuest-solaris_LIBS = $(LIB_RUNTIME)225 endif226 endif227 228 215 include $(FILE_KBUILD_SUB_FOOTER) 229 216 -
trunk/src/VBox/Additions/solaris/Makefile.kmk
r41704 r41705 34 34 ifeq ($(KBUILD_TARGET),solaris) 35 35 include $(PATH_SUB_CURRENT)/SharedFolders/Makefile.kmk 36 include $(PATH_SUB_CURRENT)/Mouse/Makefile.kmk 36 37 include $(PATH_SUB_CURRENT)/DRM/Makefile.kmk 37 38 endif -
trunk/src/VBox/Additions/solaris/Mouse/testcase/solaris.h
r41679 r41705 5 5 6 6 /* 7 * Copyright (C) 201 1Oracle Corporation7 * Copyright (C) 2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 11 11 * you can redistribute it and/or modify it under the terms of the GNU 12 12 * General Public License (GPL) as published by the Free Software 13 * Foundation, in version 2 as it ddi_info_cmd_tcomes in the "COPYING" file of the13 * Foundation, in version 2 as it comes in the "COPYING" file of the 14 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 * 17 * The contents of this file may alternatively be used under the terms 18 * of the Common Development and Distribution License Version 1.0 19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 20 * VirtualBox OSE distribution, in which case the provisions of the 21 * CDDL are applicable instead of those of the GPL. 22 * 23 * You may elect to license modified versions of this file under the 24 * terms and conditions of either the GPL or the CDDL or both. 16 25 */ 17 26 -
trunk/src/VBox/Additions/solaris/Mouse/testcase/tstVBoxMouse-solaris.c
r41679 r41705 13 13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 14 14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 * 16 * The contents of this file may alternatively be used under the terms 17 * of the Common Development and Distribution License Version 1.0 18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 19 * VirtualBox OSE distribution, in which case the provisions of the 20 * CDDL are applicable instead of those of the GPL. 21 * 22 * You may elect to license modified versions of this file under the 23 * terms and conditions of either the GPL or the CDDL or both. 15 24 */ 16 25 -
trunk/src/VBox/Additions/solaris/Mouse/vboxmouse.c
r41679 r41705 14 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 * 17 * The contents of this file may alternatively be used under the terms 18 * of the Common Development and Distribution License Version 1.0 19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 20 * VirtualBox OSE distribution, in which case the provisions of the 21 * CDDL are applicable instead of those of the GPL. 22 * 23 * You may elect to license modified versions of this file under the 24 * terms and conditions of either the GPL or the CDDL or both. 16 25 */ 17 26 … … 25 34 # include <sys/modctl.h> 26 35 # include <sys/msio.h> 27 # include <sys/mutex.h>28 36 # include <sys/pci.h> 29 37 # include <sys/stat.h> … … 44 52 #endif /* TESTCASE */ 45 53 46 #include "VBoxGuestInternal.h" 54 #include "../../common/VBoxGuestLib/SysHlp.h" 55 #include <VBox/VBoxGuest.h> 56 #include <VBox/VBoxGuestLib.h> 47 57 #include <VBox/log.h> 48 58 #include <VBox/version.h> … … 66 76 67 77 /** The module name. */ 68 #define DEVICE_NAME "vbox guest"78 #define DEVICE_NAME "vboxmouse" 69 79 /** The module description as seen in 'modinfo'. */ 70 #define DEVICE_DESC "VirtualBox GstDrv" 71 /** The maximum number of open device nodes we support. */ 72 #define MAX_OPEN_NODES 4096 80 #define DEVICE_DESC "VirtualBox MouInt" 73 81 74 82 … … 77 85 ******************************************************************************/ 78 86 79 static int vb gr0SolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag,87 static int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, 80 88 int fMode, cred_t *pCred); 81 static int vbgr0SolClose(queue_t *pReadQueue, int fFlag, cred_t *pCred); 82 static int vbgr0SolWPut(queue_t *pWriteQueue, mblk_t *pMBlk); 83 84 static int vbgr0SolGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult); 85 static int vbgr0SolAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd); 86 static int vbgr0SolDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd); 89 static int vbmsSolClose(queue_t *pReadQueue, int fFlag, cred_t *pCred); 90 static int vbmsSolWPut(queue_t *pWriteQueue, mblk_t *pMBlk); 87 91 88 92 … … 96 100 * mod_info: STREAMS module information. 97 101 */ 98 static struct module_info g_vb gr0SolModInfo =102 static struct module_info g_vbmsSolModInfo = 99 103 { 100 104 0x0ffff, /* module id number */ 101 "vbox guest",105 "vboxmouse", 102 106 0, /* minimum packet size */ 103 107 INFPSZ, /* maximum packet size accepted */ … … 111 115 * the put and service procedures. 112 116 */ 113 static struct qinit g_vb gr0SolRInit =117 static struct qinit g_vbmsSolRInit = 114 118 { 115 119 NULL, /* put */ 116 120 NULL, /* service thread procedure */ 117 vb gr0SolOpen,118 vb gr0SolClose,121 vbmsSolOpen, 122 vbmsSolClose, 119 123 NULL, /* reserved */ 120 &g_vb gr0SolModInfo,124 &g_vbmsSolModInfo, 121 125 NULL /* module statistics structure */ 122 126 }; … … 129 133 * hardware pointer drivers to a single virtual pointer. 130 134 */ 131 static struct qinit g_vb gr0SolWInit =132 { 133 vb gr0SolWPut,135 static struct qinit g_vbmsSolWInit = 136 { 137 vbmsSolWPut, 134 138 NULL, /* service thread procedure */ 135 139 NULL, /* open */ 136 140 NULL, /* close */ 137 141 NULL, /* reserved */ 138 &g_vb gr0SolModInfo,142 &g_vbmsSolModInfo, 139 143 NULL /* module statistics structure */ 140 144 }; … … 143 147 * streamtab: for drivers that support char/block entry points. 144 148 */ 145 static struct streamtab g_vb gr0SolStreamTab =146 { 147 &g_vb gr0SolRInit,148 &g_vb gr0SolWInit,149 static struct streamtab g_vbmsSolStreamTab = 150 { 151 &g_vbmsSolRInit, 152 &g_vbmsSolWInit, 149 153 NULL, /* MUX rinit */ 150 154 NULL /* MUX winit */ … … 152 156 153 157 /** 154 * cb_ops: for drivers that support char/block entry points. 155 */ 156 static struct cb_ops g_vbgr0SolCbOps = 157 { 158 nulldev, /* open */ 159 nulldev, /* close */ 160 nulldev, /* b strategy */ 161 nulldev, /* b dump */ 162 nulldev, /* b print */ 163 nulldev, /* c read */ 164 nulldev, /* c write */ 165 nulldev, /* c ioctl */ 166 nulldev, /* c devmap */ 167 nulldev, /* c mmap */ 168 nulldev, /* c segmap */ 169 nochpoll, /* c poll */ 170 ddi_prop_op, /* property ops */ 171 &g_vbgr0SolStreamTab, 172 D_NEW | D_MP, /* compat. flag */ 158 * fmodsw: loadable module wrapper for streams drivers. 159 */ 160 static struct fmodsw g_vbmsSolStrWrapper = { 161 "vboxmouse", 162 &g_vbmsSolStreamTab, 163 D_MP | D_MTPERMOD 173 164 }; 174 165 175 166 /** 176 * dev_ops: for driver device operations. 177 */ 178 static struct dev_ops g_vbgr0SolDevOps = 179 { 180 DEVO_REV, /* driver build revision */ 181 0, /* ref count */ 182 vbgr0SolGetInfo, 183 nulldev, /* identify */ 184 nulldev, /* probe */ 185 vbgr0SolAttach, 186 vbgr0SolDetach, 187 nodev, /* reset */ 188 &g_vbgr0SolCbOps, 189 (struct bus_ops *)0, 190 nodev /* power */ 167 * modlstrmod: export stream modules specifics to the kernel. 168 */ 169 static struct modlstrmod g_vbmsSolModule = 170 { 171 &mod_strmodops, /* extern from kernel */ 172 DEVICE_DESC " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV), 173 &g_vbmsSolStrWrapper 191 174 }; 192 175 193 176 /** 194 * modldrv: export driver specifics to the kernel.195 */196 static struct modldrv g_vbgr0SolModule =197 {198 &mod_driverops, /* extern from kernel */199 DEVICE_DESC " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),200 &g_vbgr0SolDevOps201 };202 203 /**204 177 * modlinkage: export install/remove/info to the kernel. 205 178 */ 206 static struct modlinkage g_vb gr0SolModLinkage =179 static struct modlinkage g_vbmsSolModLinkage = 207 180 { 208 181 MODREV_1, /* loadable module system revision */ 209 &g_vb gr0SolModule,182 &g_vbmsSolModule, 210 183 NULL /* terminate array of linkage structures */ 211 184 }; 212 185 213 186 #else /* TESTCASE */ 214 static void *g_vb gr0SolModLinkage;187 static void *g_vbmsSolModLinkage; 215 188 #endif /* TESTCASE */ 216 189 … … 220 193 typedef struct 221 194 { 222 /** Pointer to the session handle. */223 PVBOXGUESTSESSION pSession;195 /** Pointer to the Guest Library handle for the main driver. */ 196 VBGLDRIVER Driver; 224 197 /** The STREAMS write queue which we need for sending messages up to 225 198 * user-space. */ … … 233 206 */ 234 207 int cMaxScreenY; 235 } VB GR0STATE, *PVBGR0STATE;208 } VBMSSTATE, *PVBMSSTATE; 236 209 237 210 … … 240 213 ******************************************************************************/ 241 214 242 /** Device handle (we support only one instance). */ 243 static dev_info_t *g_pDip = NULL; 244 /** Array of state structures for open device nodes. I don't care about 245 * wasting a few K of memory. */ 246 static VBGR0STATE g_aOpenNodeStates[MAX_OPEN_NODES] /* = { 0 } */; 247 /** Mutex to protect the queue pointers in the node states from being unset 248 * during an IRQ. */ 249 static kmutex_t g_StateMutex; 250 /** Device extention & session data association structure. */ 251 static VBOXGUESTDEVEXT g_DevExt; 252 /** IO port handle. */ 253 static ddi_acc_handle_t g_PciIOHandle; 254 /** MMIO handle. */ 255 static ddi_acc_handle_t g_PciMMIOHandle; 256 /** IO Port. */ 257 static uint16_t g_uIOPortBase; 258 /** Address of the MMIO region.*/ 259 static char *g_pMMIOBase; /* Actually caddr_t. */ 260 /** Size of the MMIO region. */ 261 static off_t g_cbMMIO; 262 /** Pointer to the interrupt handle vector */ 263 static ddi_intr_handle_t *g_pIntr; 264 /** Number of actually allocated interrupt handles */ 265 static size_t g_cIntrAllocated; 266 /** The IRQ Mutex */ 267 static kmutex_t g_IrqMutex; 268 /** Layered device handle for kernel keep-attached opens */ 269 static ldi_handle_t g_LdiHandle = NULL; 270 /** Ref counting for IDCOpen calls */ 271 static uint64_t g_cLdiOpens = 0; 272 /** The Mutex protecting the LDI handle in IDC opens */ 273 static kmutex_t g_LdiMtx; 215 /** Global driver state. Actually this could be allocated dynamically. */ 216 static VBMSSTATE g_OpenNodeState /* = { 0 } */; 274 217 275 218 … … 284 227 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init. 285 228 */ 286 int rc = RTR0Init(0);229 int rc = VbglInit(); 287 230 if (RT_SUCCESS(rc)) 288 231 { 289 PRTLOGGER pRelLogger;290 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;291 modctl_t *pModCtl;292 293 rc = RTLogCreate(&pRelLogger, 0 /* fFlags */, "all",294 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,295 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER296 | RTLOGDEST_USER, NULL);297 if (RT_SUCCESS(rc))298 RTLogRelSetDefaultInstance(pRelLogger);299 else300 cmn_err(CE_NOTE, "failed to initialize driver logging rc=%d!\n", rc);301 302 232 /* 303 233 * Prevent module autounloading. 304 234 */ 305 pModCtl = mod_getctl(&g_vbgr0SolModLinkage);235 modctl_t *pModCtl = mod_getctl(&g_vbmsSolModLinkage); 306 236 if (pModCtl) 307 237 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD; 308 238 else 309 239 LogRel((DEVICE_NAME ":failed to disable autounloading!\n")); 310 rc = mod_install(&g_vb gr0SolModLinkage);240 rc = mod_install(&g_vbmsSolModLinkage); 311 241 } 312 242 else 313 243 { 314 cmn_err(CE_NOTE, "_init: RTR0Init failed. rc=%d\n", rc);244 cmn_err(CE_NOTE, "_init: VbglInit failed. rc=%d\n", rc); 315 245 return EINVAL; 316 246 } … … 337 267 338 268 LogRelFlow((DEVICE_NAME ":_fini\n")); 339 rc = mod_remove(&g_vbgr0SolModLinkage); 340 mutex_destroy(&g_StateMutex); 269 rc = mod_remove(&g_vbmsSolModLinkage); 341 270 342 271 RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); … … 352 281 { 353 282 LogFlow((DEVICE_NAME ":_info\n")); 354 return mod_info(&g_vb gr0SolModLinkage, pModInfo);283 return mod_info(&g_vbmsSolModLinkage, pModInfo); 355 284 } 356 285 … … 362 291 /** Calls the kernel IOCtl to report mouse status to the host on behalf of 363 292 * an open session. */ 364 static int vbgr0SolSetMouseStatus(PVBOXGUESTSESSION pSession, uint32_t fStatus) 365 { 366 return VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &g_DevExt, 367 pSession, &fStatus, sizeof(fStatus), NULL); 368 } 369 370 /** Resets (zeroes) a member in our open node state array in an IRQ-safe way. 371 */ 372 static void vbgr0SolResetSoftState(PVBGR0STATE pState) 373 { 374 mutex_enter(&g_StateMutex); 375 RT_ZERO(*pState); 376 mutex_exit(&g_StateMutex); 377 } 293 static int vbmsSolSetMouseStatus(VBGLDRIVER *pDriver, uint32_t fStatus) 294 { 295 return vbglDriverIOCtl(pDriver, VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &fStatus, 296 sizeof(fStatus)); 297 } 298 378 299 379 300 /****************************************************************************** … … 381 302 ******************************************************************************/ 382 303 304 static void vbmsSolNotify(void *pvState); 305 static void vbmsSolVUIDPutAbsEvent(PVBMSSTATE pState, ushort_t cEvent, 306 int cValue); 307 383 308 /** 384 309 * Open callback for the read queue, which we use as a generic device open 385 310 * handler. 386 311 */ 387 int vb gr0SolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, int fMode,312 int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, int fMode, 388 313 cred_t *pCred) 389 314 { 390 315 int rc; 391 PVBOXGUESTSESSION pSession = NULL; 392 PVBGR0STATE pState = NULL; 393 unsigned cInstance; 316 PVBMSSTATE pState = NULL; 394 317 395 318 NOREF(fFlag); … … 399 322 /* 400 323 * Sanity check on the mode parameter - only open as a driver, not a 401 * module, and we do cloning ourselves. Note that we start at 1, as minor 402 * zero was allocated to the file system device node in vbgr0SolAttach 403 * (see https://blogs.oracle.com/timatworkhomeandinbetween/entry/using_makedevice_in_a_drivers). 324 * module, and we do cloning ourselves. 404 325 */ 405 326 if (fMode) … … 409 330 } 410 331 411 for (cInstance = 1; cInstance < MAX_OPEN_NODES; cInstance++) 412 { 413 if (ASMAtomicCmpXchgPtr(&g_aOpenNodeStates[cInstance].pWriteQueue, 414 WR(pReadQueue), NULL)) 415 { 416 pState = &g_aOpenNodeStates[cInstance]; 417 break; 418 } 419 } 420 if (!pState) 421 { 422 LogRelFlow((DEVICE_NAME "::Open: too many open instances.")); 332 if (!ASMAtomicCmpXchgPtr(&g_OpenNodeState.pWriteQueue, 333 WR(pReadQueue), NULL)) 334 { 335 LogRelFlow((DEVICE_NAME "::Open: only one instance allowed.")); 423 336 return ENXIO; 424 337 } 338 pState = &g_OpenNodeState; 425 339 426 340 /* 427 341 * Create a new session. 428 342 */ 429 rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);343 rc = vbglDriverOpen(&pState->Driver); 430 344 if (RT_SUCCESS(rc)) 431 345 { 432 pState->pSession = pSession;433 *pDev = makedevice(getmajor(*pDev), cInstance); 346 VBoxGuestMouseSetNotifyCallback NotifyCallback; 347 434 348 /* Initialise user data for the queues to our state and vice-versa. */ 435 349 WR(pReadQueue)->q_ptr = (char *)pState; 436 350 pReadQueue->q_ptr = (char *)pState; 351 /* Enable our IRQ handler. */ 352 NotifyCallback.pfnNotify = vbmsSolNotify; 353 NotifyCallback.pvUser = (void *)pState; 354 vbglDriverIOCtl(&pState->Driver, 355 VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK, 356 &NotifyCallback, sizeof(NotifyCallback)); 437 357 qprocson(pReadQueue); 438 LogRel((DEVICE_NAME "::Open : pSession=%p pState=%p pid=%d\n", pSession, pState, (int)RTProcSelf()));358 LogRel((DEVICE_NAME "::Open\n")); 439 359 return 0; 440 360 } 441 361 442 362 /* Failed, clean up. */ 443 vbgr0SolResetSoftState(pState);363 ASMAtomicWriteNullPtr(&pState->pWriteQueue); 444 364 445 365 LogRel((DEVICE_NAME "::Open: VBoxGuestCreateUserSession failed. rc=%d\n", rc)); … … 449 369 450 370 /** 371 * Notification callback, called when the VBoxGuest mouse pointer is moved. 372 * We send a VUID event up to user space. We may send a miscalculated event 373 * if a resolution change is half-way through, but that is pretty much to be 374 * expected, so we won't worry about it. 375 */ 376 void vbmsSolNotify(void *pvState) 377 { 378 PVBMSSTATE pState = (PVBMSSTATE)pvState; 379 VMMDevReqMouseStatus *pReq; 380 int rc; 381 LogFlow((DEVICE_NAME "::NativeISRMousePollEvent:\n")); 382 383 rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), 384 VMMDevReq_GetMouseStatus); 385 if (RT_FAILURE(rc)) 386 return; /* If kernel memory is short a missed event is acceptable! */ 387 pReq->mouseFeatures = 0; 388 pReq->pointerXPos = 0; 389 pReq->pointerYPos = 0; 390 rc = VbglGRPerform(&pReq->header); 391 if (RT_SUCCESS(rc)) 392 { 393 int cMaxScreenX = pState->cMaxScreenX; 394 int cMaxScreenY = pState->cMaxScreenY; 395 396 if (cMaxScreenX && cMaxScreenY) 397 { 398 vbmsSolVUIDPutAbsEvent(pState, LOC_X_ABSOLUTE, 399 pReq->pointerXPos * cMaxScreenX 400 / VMMDEV_MOUSE_RANGE_MAX); 401 vbmsSolVUIDPutAbsEvent(pState, LOC_Y_ABSOLUTE, 402 pReq->pointerYPos * cMaxScreenY 403 / VMMDEV_MOUSE_RANGE_MAX); 404 } 405 } 406 VbglGRFree(&pReq->header); 407 } 408 409 410 void vbmsSolVUIDPutAbsEvent(PVBMSSTATE pState, ushort_t cEvent, 411 int cValue) 412 { 413 queue_t *pReadQueue = RD(pState->pWriteQueue); 414 mblk_t *pMBlk = allocb(sizeof(Firm_event), BPRI_HI); 415 Firm_event *pEvent; 416 AssertReturnVoid(cEvent == LOC_X_ABSOLUTE || cEvent == LOC_Y_ABSOLUTE); 417 if (!pMBlk) 418 return; /* If kernel memory is short a missed event is acceptable! */ 419 pEvent = (Firm_event *)pMBlk->b_wptr; 420 pEvent->id = cEvent; 421 pEvent->pair_type = FE_PAIR_DELTA; 422 pEvent->pair = cEvent == LOC_X_ABSOLUTE ? LOC_X_DELTA : LOC_Y_DELTA; 423 pEvent->value = cValue; 424 uniqtime32(&pEvent->time); 425 pMBlk->b_wptr += sizeof(Firm_event); 426 /* Put the message on the queue immediately if it is not blocked. */ 427 if (canput(pReadQueue->q_next)) 428 putnext(pReadQueue, pMBlk); 429 else 430 putbq(pReadQueue, pMBlk); 431 } 432 433 434 /** 451 435 * Close callback for the read queue, which we use as a generic device close 452 436 * handler. 453 437 */ 454 int vb gr0SolClose(queue_t *pReadQueue, int fFlag, cred_t *pCred)455 { 456 PVB OXGUESTSESSION pSession = NULL;457 PVBGR0STATE pState = (PVBGR0STATE)pReadQueue->q_ptr;458 459 LogFlow((DEVICE_NAME "::Close pid=%d\n", (int)RTProcSelf()));438 int vbmsSolClose(queue_t *pReadQueue, int fFlag, cred_t *pCred) 439 { 440 PVBMSSTATE pState = (PVBMSSTATE)pReadQueue->q_ptr; 441 VBoxGuestMouseSetNotifyCallback NotifyCallback; 442 443 LogFlow((DEVICE_NAME "::Close\n")); 460 444 NOREF(fFlag); 461 445 NOREF(pCred); … … 466 450 return EFAULT; 467 451 } 452 453 /* Disable our IRQ handler. */ 454 RT_ZERO(NotifyCallback); 455 vbglDriverIOCtl(&pState->Driver, 456 VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK, 457 &NotifyCallback, sizeof(NotifyCallback)); 468 458 qprocsoff(pReadQueue); 469 pSession = pState->pSession;470 vbgr0SolResetSoftState(pState);471 pReadQueue->q_ptr = NULL;472 473 Log((DEVICE_NAME "::Close: pSession=%p pState=%p\n", pSession, pState));474 if (!pSession)475 {476 Log((DEVICE_NAME "::Close: failed to get pSession.\n"));477 return EFAULT;478 }479 459 480 460 /* 481 461 * Close the session. 482 462 */ 483 VBoxGuestCloseSession(&g_DevExt, pSession); 463 vbglDriverClose(&pState->Driver); 464 ASMAtomicWriteNullPtr(&pState->pWriteQueue); 465 pReadQueue->q_ptr = NULL; 484 466 return 0; 485 467 } … … 487 469 488 470 #ifdef TESTCASE 489 /** Simple test of vb gr0SolOpen and vbgr0SolClose. */471 /** Simple test of vbmsSolOpen and vbmsSolClose. */ 490 472 static void testOpenClose(RTTEST hTest) 491 473 { 492 queue_t aQueues[ 4];474 queue_t aQueues[2]; 493 475 dev_t device = 0; 494 476 int rc; 495 477 496 RTTestSub(hTest, "Testing vb gr0SolOpen and vbgr0SolClose");497 RT_ZERO(g_ aOpenNodeStates);478 RTTestSub(hTest, "Testing vbmsSolOpen and vbmsSolClose"); 479 RT_ZERO(g_OpenNodeState); 498 480 RT_ZERO(aQueues); 499 481 doInitQueues(&aQueues[0]); 500 doInitQueues(&aQueues[2]); 501 rc = vbgr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL); 482 rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL); 502 483 RTTEST_CHECK(hTest, rc == 0); 503 RTTEST_CHECK(hTest, g_aOpenNodeStates[1].pWriteQueue == WR(&aQueues[0])); 504 rc = vbgr0SolOpen(RD(&aQueues[2]), &device, 0, 0, NULL); 505 RTTEST_CHECK(hTest, rc == 0); 506 RTTEST_CHECK(hTest, g_aOpenNodeStates[2].pWriteQueue == WR(&aQueues[2])); 507 vbgr0SolClose(RD(&aQueues[0]), 0, NULL); 508 vbgr0SolClose(RD(&aQueues[1]), 0, NULL); 484 RTTEST_CHECK(hTest, g_OpenNodeState.pWriteQueue == WR(&aQueues[0])); 485 vbmsSolClose(RD(&aQueues[0]), 0, NULL); 509 486 } 510 487 #endif 511 488 512 489 513 /* Helper for vb gr0SolWPut. */514 static int vb gr0SolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk);490 /* Helper for vbmsSolWPut. */ 491 static int vbmsSolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk); 515 492 516 493 /** … … 518 495 * land in our write queue. 519 496 */ 520 int vb gr0SolWPut(queue_t *pWriteQueue, mblk_t *pMBlk)497 int vbmsSolWPut(queue_t *pWriteQueue, mblk_t *pMBlk) 521 498 { 522 499 LogRelFlowFunc((DEVICE_NAME "::\n")); … … 540 517 case M_IOCDATA: 541 518 { 542 int err = vb gr0SolDispatchIOCtl(pWriteQueue, pMBlk);519 int err = vbmsSolDispatchIOCtl(pWriteQueue, pMBlk); 543 520 if (!err) 544 521 qreply(pWriteQueue, pMBlk); … … 564 541 struct msgb *pMBlk) 565 542 { 566 PVB GR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;543 PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr; 567 544 RTTEST_CHECK_MSG_RET(hTest, pState->cMaxScreenX 568 545 == g_TestResolution.width - 1, … … 623 600 unsigned i; 624 601 625 RTTestSub(hTest, "Testing vb gr0WPut");602 RTTestSub(hTest, "Testing vbmsWPut"); 626 603 for (i = 0; i < RT_ELEMENTS(g_asTestWPut); ++i) 627 604 { … … 656 633 RT_ZERO(aQueues); 657 634 doInitQueues(&aQueues[0]); 658 rc = vb gr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);635 rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL); 659 636 RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc)); 660 RTTEST_CHECK_MSG(hTest, g_ aOpenNodeStates[1].pWriteQueue637 RTTEST_CHECK_MSG(hTest, g_OpenNodeState.pWriteQueue 661 638 == WR(&aQueues[0]), (hTest, "i=%u\n", i)); 662 639 pMBlk->b_datap->db_type = M_IOCTL; … … 667 644 g_asTestWPut[i].cbDataIn); 668 645 pMBlk->b_cont = pMBlkCont; 669 rc = vb gr0SolWPut(WR(&aQueues[0]), pMBlk);646 rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk); 670 647 RTTEST_CHECK_MSG(hTest, pIOCBlk->ioc_error == g_asTestWPut[i].rcExp, 671 648 (hTest, "i=%u, IOCBlk.ioc_error=%d\n", i, … … 687 664 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n", 688 665 __PRETTY_FUNCTION__); 689 vb gr0SolClose(RD(&aQueues[1]), 0, NULL);666 vbmsSolClose(RD(&aQueues[1]), 0, NULL); 690 667 freemsg(pMBlk); 691 668 } … … 712 689 RT_ZERO(aQueues); 713 690 doInitQueues(&aQueues[0]); 714 rc = vb gr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);691 rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL); 715 692 RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc)); 716 RTTEST_CHECK_MSG(hTest, g_ aOpenNodeStates[1].pWriteQueue693 RTTEST_CHECK_MSG(hTest, g_OpenNodeState.pWriteQueue 717 694 == WR(&aQueues[0]), (hTest, "i=%u\n", i)); 718 695 pMBlk->b_datap->db_type = M_IOCTL; … … 721 698 *(void **)pMBlkCont->b_rptr = (void *)USER_ADDRESS; 722 699 pMBlk->b_cont = pMBlkCont; 723 rc = vb gr0SolWPut(WR(&aQueues[0]), pMBlk);700 rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk); 724 701 pCopyReq = (struct copyreq *)pMBlk->b_rptr; 725 702 RTTEST_CHECK_MSG(hTest, ( ( g_asTestWPut[i].cbDataIn … … 767 744 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n", 768 745 __PRETTY_FUNCTION__); 769 vb gr0SolClose(RD(&aQueues[1]), 0, NULL);746 vbmsSolClose(RD(&aQueues[1]), 0, NULL); 770 747 freemsg(pMBlk); 771 748 } … … 793 770 RT_ZERO(aQueues); 794 771 doInitQueues(&aQueues[0]); 795 rc = vb gr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);772 rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL); 796 773 RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc)); 797 RTTEST_CHECK_MSG(hTest, g_ aOpenNodeStates[1].pWriteQueue774 RTTEST_CHECK_MSG(hTest, g_OpenNodeState.pWriteQueue 798 775 == WR(&aQueues[0]), (hTest, "i=%u\n", i)); 799 776 pMBlk->b_datap->db_type = M_IOCDATA; … … 804 781 memcpy(pMBlkCont->b_rptr, g_asTestWPut[i].pvDataIn, g_asTestWPut[i].cbDataIn); 805 782 pMBlk->b_cont = pMBlkCont; 806 rc = vb gr0SolWPut(WR(&aQueues[0]), pMBlk);783 rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk); 807 784 pCopyReq = (struct copyreq *)pMBlk->b_rptr; 808 785 RTTEST_CHECK_MSG(hTest, ( ( g_asTestWPut[i].cbDataOut … … 834 811 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n", 835 812 __PRETTY_FUNCTION__); 836 vb gr0SolClose(RD(&aQueues[1]), 0, NULL);813 vbmsSolClose(RD(&aQueues[1]), 0, NULL); 837 814 freemsg(pMBlk); 838 815 } … … 856 833 RT_ZERO(aQueues); 857 834 doInitQueues(&aQueues[0]); 858 rc = vb gr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);835 rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL); 859 836 RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc)); 860 RTTEST_CHECK_MSG(hTest, g_ aOpenNodeStates[1].pWriteQueue837 RTTEST_CHECK_MSG(hTest, g_OpenNodeState.pWriteQueue 861 838 == WR(&aQueues[0]), (hTest, "i=%u\n", i)); 862 839 pMBlk->b_datap->db_type = M_IOCDATA; 863 840 pCopyResp->cp_cmd = g_asTestWPut[i].iIOCCmd; 864 rc = vb gr0SolWPut(WR(&aQueues[0]), pMBlk);841 rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk); 865 842 RTTEST_CHECK_MSG(hTest, pMBlk->b_datap->db_type == M_IOCACK, 866 843 (hTest, "i=%u, db_type=%u\n", i, … … 869 846 RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first == pMBlk, 870 847 (hTest, "i=%u\n", i)); 871 vb gr0SolClose(RD(&aQueues[1]), 0, NULL);848 vbmsSolClose(RD(&aQueues[1]), 0, NULL); 872 849 freemsg(pMBlk); 873 850 } … … 903 880 * implemention. 904 881 */ 905 typedef int FNVB GR0SOLIOCTL(PVBGR0STATE pState, int iCmd, void *pvData,882 typedef int FNVBMSSOLIOCTL(PVBMSSTATE pState, int iCmd, void *pvData, 906 883 size_t cbBuffer, size_t *pcbData, int *prc); 907 typedef FNVB GR0SOLIOCTL *PFNVBGR0SOLIOCTL;908 909 /* Helpers for vb gr0SolDispatchIOCtl. */910 static int vb gr0SolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,911 PFNVB GR0SOLIOCTL pfnHandler,884 typedef FNVBMSSOLIOCTL *PFNVBMSSOLIOCTL; 885 886 /* Helpers for vbmsSolDispatchIOCtl. */ 887 static int vbmsSolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk, 888 PFNVBMSSOLIOCTL pfnHandler, 912 889 int iCmd, size_t cbTransparent, 913 890 enum IOCTLDIRECTION enmDirection); 914 static int vb gr0SolVUIDIOCtl(PVBGR0STATE pState, int iCmd, void *pvData,891 static int vbmsSolVUIDIOCtl(PVBMSSTATE pState, int iCmd, void *pvData, 915 892 size_t cbBuffer, size_t *pcbData, int *prc); 916 static int vbgr0SolGuestIOCtl(PVBGR0STATE pState, int iCmd, void *pvData,917 size_t cbBuffer, size_t *pcbData, int *prc);918 893 919 894 /** Table of supported VUID IOCtls. */ … … 953 928 * @param pMBlk pointer to the STREAMS message block structure. 954 929 */ 955 static int vb gr0SolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk)930 static int vbmsSolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk) 956 931 { 957 932 struct iocblk *pIOCBlk = (struct iocblk *)pMBlk->b_rptr; … … 974 949 cbBuffer = g_aVUIDIOCtlDescriptions[i].cbBuffer; 975 950 enmDirection = g_aVUIDIOCtlDescriptions[i].enmDirection; 976 return vb gr0SolHandleIOCtl(pWriteQueue, pMBlk,977 vb gr0SolVUIDIOCtl, iCmd,951 return vbmsSolHandleIOCtl(pWriteQueue, pMBlk, 952 vbmsSolVUIDIOCtl, iCmd, 978 953 cbBuffer, enmDirection); 979 954 } 980 955 return EINVAL; 981 956 } 982 case 'V' << 8:983 return ENOTTY;984 return vbgr0SolHandleIOCtl(pWriteQueue, pMBlk, vbgr0SolGuestIOCtl,985 iCmd, 0, UNSPECIFIED);986 957 default: 987 958 return ENOTTY; … … 990 961 991 962 992 /* Helpers for vb gr0SolHandleIOCtl. */993 static int vb gr0SolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk,994 PFNVB GR0SOLIOCTL pfnHandler, int iCmd,963 /* Helpers for vbmsSolHandleIOCtl. */ 964 static int vbmsSolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk, 965 PFNVBMSSOLIOCTL pfnHandler, int iCmd, 995 966 size_t cbTransparent, 996 967 enum IOCTLDIRECTION enmDirection); 997 968 998 static int vb gr0SolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,999 PFNVB GR0SOLIOCTL pfnHandler,969 static int vbmsSolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk, 970 PFNVBMSSOLIOCTL pfnHandler, 1000 971 int iCmd, size_t cbTransparent, 1001 972 enum IOCTLDIRECTION enmDirection); 1002 973 1003 static int vb gr0SolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,1004 PFNVB GR0SOLIOCTL pfnHandler, int iCmd);974 static int vbmsSolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk, 975 PFNVBMSSOLIOCTL pfnHandler, int iCmd); 1005 976 1006 977 /** … … 1025 996 * @param enmDirection data transfer direction of the IOCtl. 1026 997 */ 1027 static int vb gr0SolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,1028 PFNVB GR0SOLIOCTL pfnHandler, int iCmd,998 static int vbmsSolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk, 999 PFNVBMSSOLIOCTL pfnHandler, int iCmd, 1029 1000 size_t cbTransparent, 1030 1001 enum IOCTLDIRECTION enmDirection) … … 1033 1004 1034 1005 if (pMBlk->b_datap->db_type == M_IOCDATA) 1035 return vb gr0SolHandleIOCtlData(pWriteQueue, pMBlk, pfnHandler, iCmd,1006 return vbmsSolHandleIOCtlData(pWriteQueue, pMBlk, pfnHandler, iCmd, 1036 1007 cbTransparent, enmDirection); 1037 1008 else if ( pMBlk->b_datap->db_type == M_IOCTL 1038 1009 && pIOCBlk->ioc_count == TRANSPARENT) 1039 return vb gr0SolHandleTransparentIOCtl(pWriteQueue, pMBlk, pfnHandler,1010 return vbmsSolHandleTransparentIOCtl(pWriteQueue, pMBlk, pfnHandler, 1040 1011 iCmd, cbTransparent, 1041 1012 enmDirection); 1042 1013 else if (pMBlk->b_datap->db_type == M_IOCTL) 1043 return vb gr0SolHandleIStrIOCtl(pWriteQueue, pMBlk, pfnHandler, iCmd);1014 return vbmsSolHandleIStrIOCtl(pWriteQueue, pMBlk, pfnHandler, iCmd); 1044 1015 return EINVAL; 1045 1016 } … … 1047 1018 1048 1019 /** 1049 * Helper for vb gr0SolHandleIOCtl. This rather complicated-looking1020 * Helper for vbmsSolHandleIOCtl. This rather complicated-looking 1050 1021 * code is basically the standard boilerplate for handling any streams IOCtl 1051 1022 * additional data, which we currently only use for transparent IOCtls. 1052 * @copydoc vb gr0SolHandleIOCtl1053 */ 1054 static int vb gr0SolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk,1055 PFNVB GR0SOLIOCTL pfnHandler, int iCmd,1023 * @copydoc vbmsSolHandleIOCtl 1024 */ 1025 static int vbmsSolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk, 1026 PFNVBMSSOLIOCTL pfnHandler, int iCmd, 1056 1027 size_t cbTransparent, 1057 1028 enum IOCTLDIRECTION enmDirection) 1058 1029 { 1059 1030 struct copyresp *pCopyResp = (struct copyresp *)pMBlk->b_rptr; 1060 PVB GR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;1031 PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr; 1061 1032 1062 1033 if (pCopyResp->cp_rval) /* cp_rval is a pointer used as a boolean. */ … … 1092 1063 1093 1064 /** 1094 * Helper for vb gr0SolHandleIOCtl. This rather complicated-looking1065 * Helper for vbmsSolHandleIOCtl. This rather complicated-looking 1095 1066 * code is basically the standard boilerplate for handling transparent IOCtls, 1096 1067 * that is, IOCtls which are not re-packed inside STREAMS IOCtls. 1097 * @copydoc vb gr0SolHandleIOCtl1098 */ 1099 int vb gr0SolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,1100 PFNVB GR0SOLIOCTL pfnHandler, int iCmd,1068 * @copydoc vbmsSolHandleIOCtl 1069 */ 1070 int vbmsSolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk, 1071 PFNVBMSSOLIOCTL pfnHandler, int iCmd, 1101 1072 size_t cbTransparent, 1102 1073 enum IOCTLDIRECTION enmDirection) … … 1104 1075 int err = 0, rc = 0; 1105 1076 size_t cbData = 0; 1106 PVB GR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;1077 PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr; 1107 1078 1108 1079 if ( (enmDirection != NONE && !pMBlk->b_cont) … … 1142 1113 1143 1114 /** 1144 * Helper for vb gr0SolHandleIOCtl. This rather complicated-looking1115 * Helper for vbmsSolHandleIOCtl. This rather complicated-looking 1145 1116 * code is basically the standard boilerplate for handling any streams IOCtl. 1146 * @copydoc vb gr0SolHandleIOCtl1147 */ 1148 static int vb gr0SolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,1149 PFNVB GR0SOLIOCTL pfnHandler, int iCmd)1117 * @copydoc vbmsSolHandleIOCtl 1118 */ 1119 static int vbmsSolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk, 1120 PFNVBMSSOLIOCTL pfnHandler, int iCmd) 1150 1121 { 1151 1122 struct iocblk *pIOCBlk = (struct iocblk *)pMBlk->b_rptr; 1152 PVB GR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;1123 PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr; 1153 1124 uint_t cbBuffer = pIOCBlk->ioc_count; 1154 1125 void *pvData = NULL; … … 1175 1146 /** 1176 1147 * Handle a VUID input device IOCtl. 1177 * @copydoc FNVB GR0SOLIOCTL1178 */ 1179 static int vb gr0SolVUIDIOCtl(PVBGR0STATE pState, int iCmd, void *pvData,1148 * @copydoc FNVBMSSOLIOCTL 1149 */ 1150 static int vbmsSolVUIDIOCtl(PVBMSSTATE pState, int iCmd, void *pvData, 1180 1151 size_t cbBuffer, size_t *pcbData, int *prc) 1181 1152 { … … 1227 1198 pState->cMaxScreenY = pResolution->height - 1; 1228 1199 /* Note: we don't disable this again until session close. */ 1229 rc = vb gr0SolSetMouseStatus(pState->pSession,1230 VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE1231 | VMMDEV_MOUSE_NEW_PROTOCOL);1200 rc = vbmsSolSetMouseStatus(&pState->Driver, 1201 VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE 1202 | VMMDEV_MOUSE_NEW_PROTOCOL); 1232 1203 if (RT_SUCCESS(rc)) 1233 1204 return 0; … … 1266 1237 1267 1238 1268 /**1269 * Handle a VBoxGuest IOCtl.1270 * @copydoc FNVBGR0SOLIOCTL1271 */1272 static int vbgr0SolGuestIOCtl(PVBGR0STATE pState, int iCmd, void *pvData,1273 size_t cbBuffer, size_t *pcbData, int *prc)1274 {1275 int rc = VBoxGuestCommonIOCtl(iCmd, &g_DevExt, pState->pSession, pvData, cbBuffer, pcbData);1276 if (RT_SUCCESS(rc))1277 {1278 *prc = rc;1279 return 0;1280 }1281 else1282 {1283 /*1284 * We Log() instead of LogRel() here because VBOXGUEST_IOCTL_WAITEVENT can return VERR_TIMEOUT,1285 * VBOXGUEST_IOCTL_CANCEL_ALL_EVENTS can return VERR_INTERRUPTED and possibly more in the future;1286 * which are not really failures that require logging.1287 */1288 Log((DEVICE_NAME "::IOCtl: VBoxGuestCommonIOCtl failed. Cmd=%#x rc=%d\n", iCmd, rc));1289 rc = RTErrConvertToErrno(rc);1290 return rc;1291 }1292 }1293 1294 1295 /**1296 * Info entry point, called by solaris kernel for obtaining driver info.1297 *1298 * @param pDip The module structure instance (do not use).1299 * @param enmCmd Information request type.1300 * @param pvArg Type specific argument.1301 * @param ppvResult Where to store the requested info.1302 *1303 * @return corresponding solaris error code.1304 */1305 int vbgr0SolGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg,1306 void **ppvResult)1307 {1308 int rc = DDI_SUCCESS;1309 1310 LogFlow((DEVICE_NAME "::GetInfo\n"));1311 switch (enmCmd)1312 {1313 case DDI_INFO_DEVT2DEVINFO:1314 *ppvResult = (void *)g_pDip;1315 break;1316 1317 case DDI_INFO_DEVT2INSTANCE:1318 *ppvResult = (void *)(uintptr_t)ddi_get_instance(g_pDip);1319 break;1320 1321 default:1322 rc = DDI_FAILURE;1323 break;1324 }1325 1326 NOREF(pvArg);1327 return rc;1328 }1329 1330 1331 /* Helpers for vbgr0SolAttach and vbgr0SolDetach. */1332 static int vbgr0SolAddIRQ(dev_info_t *pDip);1333 static void vbgr0SolRemoveIRQ(dev_info_t *pDip);1334 1335 /**1336 * Attach entry point, to attach a device to the system or resume it.1337 *1338 * @param pDip The module structure instance.1339 * @param enmCmd Attach type (ddi_attach_cmd_t)1340 *1341 * @return corresponding solaris error code.1342 */1343 int vbgr0SolAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)1344 {1345 LogFlow((DEVICE_NAME "::Attach\n"));1346 switch (enmCmd)1347 {1348 case DDI_ATTACH:1349 {1350 int instance, rc;1351 ddi_acc_handle_t PciHandle;1352 1353 if (g_pDip)1354 {1355 LogRel((DEVICE_NAME "::Attach: Only one instance supported.\n"));1356 return DDI_FAILURE;1357 }1358 instance = ddi_get_instance(pDip);1359 1360 /*1361 * Enable resources for PCI access.1362 */1363 rc = pci_config_setup(pDip, &PciHandle);1364 if (rc == DDI_SUCCESS)1365 {1366 /*1367 * Map the register address space.1368 */1369 char *baseAddr; /* Actually caddr_t. */1370 ddi_device_acc_attr_t deviceAttr;1371 deviceAttr.devacc_attr_version = DDI_DEVICE_ATTR_V0;1372 deviceAttr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;1373 deviceAttr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;1374 deviceAttr.devacc_attr_access = DDI_DEFAULT_ACC;1375 rc = ddi_regs_map_setup(pDip, 1, &baseAddr, 0, 0, &deviceAttr, &g_PciIOHandle);1376 if (rc == DDI_SUCCESS)1377 {1378 /*1379 * Read size of the MMIO region.1380 */1381 g_uIOPortBase = (uintptr_t)baseAddr;1382 rc = ddi_dev_regsize(pDip, 2, &g_cbMMIO);1383 if (rc == DDI_SUCCESS)1384 {1385 rc = ddi_regs_map_setup(pDip, 2, &g_pMMIOBase, 0, g_cbMMIO, &deviceAttr,1386 &g_PciMMIOHandle);1387 if (rc == DDI_SUCCESS)1388 {1389 /*1390 * Add IRQ of VMMDev.1391 */1392 rc = vbgr0SolAddIRQ(pDip);1393 if (rc == DDI_SUCCESS)1394 {1395 /*1396 * Call the common device extension initializer.1397 */1398 #if ARCH_BITS == 641399 # define VBOXGUEST_OS_TYPE VBOXOSTYPE_Solaris_x641400 #else1401 # define VBOXGUEST_OS_TYPE VBOXOSTYPE_Solaris1402 #endif1403 rc = VBoxGuestInitDevExt(&g_DevExt,1404 g_uIOPortBase,1405 g_pMMIOBase, g_cbMMIO,1406 VBOXGUEST_OS_TYPE,1407 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);1408 #undef VBOXGUEST_OS_TYPE1409 if (RT_SUCCESS(rc))1410 {1411 rc = ddi_create_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0);1412 if (rc == DDI_SUCCESS)1413 {1414 g_pDip = pDip;1415 pci_config_teardown(&PciHandle);1416 return DDI_SUCCESS;1417 }1418 1419 LogRel((DEVICE_NAME "::Attach: ddi_create_minor_node failed.\n"));1420 VBoxGuestDeleteDevExt(&g_DevExt);1421 }1422 else1423 LogRel((DEVICE_NAME "::Attach: VBoxGuestInitDevExt failed.\n"));1424 vbgr0SolRemoveIRQ(pDip);1425 }1426 else1427 LogRel((DEVICE_NAME "::Attach: vbgr0SolAddIRQ failed.\n"));1428 ddi_regs_map_free(&g_PciMMIOHandle);1429 }1430 else1431 LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for MMIO region failed.\n"));1432 }1433 else1434 LogRel((DEVICE_NAME "::Attach: ddi_dev_regsize for MMIO region failed.\n"));1435 ddi_regs_map_free(&g_PciIOHandle);1436 }1437 else1438 LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for IOport failed.\n"));1439 pci_config_teardown(&PciHandle);1440 }1441 else1442 LogRel((DEVICE_NAME "::Attach: pci_config_setup failed rc=%d.\n", rc));1443 return DDI_FAILURE;1444 }1445 1446 case DDI_RESUME:1447 {1448 /** @todo implement resume for guest driver. */1449 return DDI_SUCCESS;1450 }1451 1452 default:1453 return DDI_FAILURE;1454 }1455 }1456 1457 1458 /**1459 * Detach entry point, to detach a device to the system or suspend it.1460 *1461 * @param pDip The module structure instance.1462 * @param enmCmd Attach type (ddi_attach_cmd_t)1463 *1464 * @return corresponding solaris error code.1465 */1466 int vbgr0SolDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)1467 {1468 LogFlow((DEVICE_NAME "::Detach\n"));1469 switch (enmCmd)1470 {1471 case DDI_DETACH:1472 {1473 vbgr0SolRemoveIRQ(pDip);1474 ddi_regs_map_free(&g_PciIOHandle);1475 ddi_regs_map_free(&g_PciMMIOHandle);1476 ddi_remove_minor_node(pDip, NULL);1477 VBoxGuestDeleteDevExt(&g_DevExt);1478 g_pDip = NULL;1479 return DDI_SUCCESS;1480 }1481 1482 case DDI_SUSPEND:1483 {1484 /** @todo implement suspend for guest driver. */1485 return DDI_SUCCESS;1486 }1487 1488 default:1489 return DDI_FAILURE;1490 }1491 }1492 1493 1494 /* Interrupt service routine installed by vbgr0SolAddIRQ. */1495 static uint_t vbgr0SolISR(char *Arg /* Actually caddr_t. */);1496 1497 /**1498 * Sets IRQ for VMMDev.1499 *1500 * @returns Solaris error code.1501 * @param pDip Pointer to the device info structure.1502 */1503 static int vbgr0SolAddIRQ(dev_info_t *pDip)1504 {1505 int IntrType = 0, rc;1506 1507 LogFlow((DEVICE_NAME "::AddIRQ: pDip=%p\n", pDip));1508 rc = ddi_intr_get_supported_types(pDip, &IntrType);1509 if (rc == DDI_SUCCESS)1510 {1511 /* We won't need to bother about MSIs. */1512 if (IntrType & DDI_INTR_TYPE_FIXED)1513 {1514 int IntrCount = 0;1515 rc = ddi_intr_get_nintrs(pDip, IntrType, &IntrCount);1516 if ( rc == DDI_SUCCESS1517 && IntrCount > 0)1518 {1519 int IntrAvail = 0;1520 rc = ddi_intr_get_navail(pDip, IntrType, &IntrAvail);1521 if ( rc == DDI_SUCCESS1522 && IntrAvail > 0)1523 {1524 /* Allocated kernel memory for the interrupt handles. The allocation size is stored internally. */1525 g_pIntr = RTMemAlloc(IntrCount * sizeof(ddi_intr_handle_t));1526 if (g_pIntr)1527 {1528 int IntrAllocated;1529 unsigned i;1530 rc = ddi_intr_alloc(pDip, g_pIntr, IntrType, 0, IntrCount, &IntrAllocated, DDI_INTR_ALLOC_NORMAL);1531 if ( rc == DDI_SUCCESS1532 && IntrAllocated > 0)1533 {1534 uint_t uIntrPriority;1535 g_cIntrAllocated = IntrAllocated;1536 rc = ddi_intr_get_pri(g_pIntr[0], &uIntrPriority);1537 if (rc == DDI_SUCCESS)1538 {1539 /* Initialize the mutex. */1540 mutex_init(&g_IrqMutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority));1541 1542 /* Initialise the node state mutex. This will1543 * be taken in the ISR. */1544 mutex_init(&g_StateMutex, NULL, MUTEX_DRIVER,1545 DDI_INTR_PRI(uIntrPriority));1546 /* Assign interrupt handler functions and enable interrupts. */1547 for (i = 0; i < IntrAllocated; i++)1548 {1549 rc = ddi_intr_add_handler(g_pIntr[i], (ddi_intr_handler_t *)vbgr0SolISR,1550 NULL /* No Private Data */, NULL);1551 if (rc == DDI_SUCCESS)1552 rc = ddi_intr_enable(g_pIntr[i]);1553 if (rc != DDI_SUCCESS)1554 {1555 /* Changing local IntrAllocated to hold so-far allocated handles for freeing. */1556 IntrAllocated = i;1557 break;1558 }1559 }1560 if (rc == DDI_SUCCESS)1561 return rc;1562 1563 /* Remove any assigned handlers */1564 LogRel((DEVICE_NAME ":failed to assign IRQs allocated=%d\n", IntrAllocated));1565 for (i = 0; i < IntrAllocated; i++)1566 ddi_intr_remove_handler(g_pIntr[i]);1567 }1568 else1569 LogRel((DEVICE_NAME "::AddIRQ: failed to get priority of interrupt. rc=%d\n", rc));1570 1571 /* Remove allocated IRQs, too bad we can free only one handle at a time. */1572 for (i = 0; i < g_cIntrAllocated; i++)1573 ddi_intr_free(g_pIntr[i]);1574 }1575 else1576 LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount));1577 RTMemFree(g_pIntr);1578 }1579 else1580 LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount));1581 }1582 else1583 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient available IRQs. rc=%d IntrAvail=%d\n", rc, IntrAvail));1584 }1585 else1586 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d IntrCount=%d\n", rc, IntrCount));1587 }1588 else1589 LogRel((DEVICE_NAME "::AddIRQ: invalid irq type. IntrType=%#x\n", IntrType));1590 }1591 else1592 LogRel((DEVICE_NAME "::AddIRQ: failed to get supported interrupt types\n"));1593 return rc;1594 }1595 1596 1597 /**1598 * Removes IRQ for VMMDev.1599 *1600 * @param pDip Pointer to the device info structure.1601 */1602 static void vbgr0SolRemoveIRQ(dev_info_t *pDip)1603 {1604 unsigned i;1605 1606 LogFlow((DEVICE_NAME "::RemoveIRQ:\n"));1607 for (i = 0; i < g_cIntrAllocated; i++)1608 {1609 int rc = ddi_intr_disable(g_pIntr[i]);1610 if (rc == DDI_SUCCESS)1611 {1612 rc = ddi_intr_remove_handler(g_pIntr[i]);1613 if (rc == DDI_SUCCESS)1614 ddi_intr_free(g_pIntr[i]);1615 }1616 }1617 RTMemFree(g_pIntr);1618 mutex_destroy(&g_IrqMutex);1619 }1620 1621 1622 /**1623 * Interrupt Service Routine for VMMDev.1624 *1625 * @param Arg Private data (unused, will be NULL).1626 * @returns DDI_INTR_CLAIMED if it's our interrupt, DDI_INTR_UNCLAIMED if it isn't.1627 */1628 static uint_t vbgr0SolISR(char *Arg /* Actually caddr_t. */)1629 {1630 bool fOurIRQ;1631 1632 LogFlow((DEVICE_NAME "::ISR:\n"));1633 mutex_enter(&g_IrqMutex);1634 fOurIRQ = VBoxGuestCommonISR(&g_DevExt);1635 mutex_exit(&g_IrqMutex);1636 return fOurIRQ ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED;1637 }1638 1639 1640 /* Helper for VBoxGuestNativeISRMousePollEvent. */1641 static void vbgr0SolVUIDPutAbsEvent(PVBGR0STATE pState, ushort_t cEvent,1642 int cValue);1643 1644 /**1645 * Native part of the IRQ service routine, called when the VBoxGuest mouse1646 * pointer is moved. We send a VUID event up to user space.1647 */1648 void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)1649 {1650 VMMDevReqMouseStatus *pReq;1651 int rc;1652 LogFlow((DEVICE_NAME "::NativeISRMousePollEvent:\n"));1653 1654 rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq),1655 VMMDevReq_GetMouseStatus);1656 if (RT_FAILURE(rc))1657 return; /* If kernel memory is short a missed event is acceptable! */1658 pReq->mouseFeatures = 0;1659 pReq->pointerXPos = 0;1660 pReq->pointerYPos = 0;1661 rc = VbglGRPerform(&pReq->header);1662 if (RT_SUCCESS(rc))1663 {1664 unsigned i;1665 1666 mutex_enter(&g_StateMutex);1667 for (i = 1; i < MAX_OPEN_NODES; ++i)1668 {1669 int cMaxScreenX = g_aOpenNodeStates[i].cMaxScreenX;1670 int cMaxScreenY = g_aOpenNodeStates[i].cMaxScreenY;1671 1672 if (!cMaxScreenX || !cMaxScreenY)1673 continue;1674 vbgr0SolVUIDPutAbsEvent(&g_aOpenNodeStates[i], LOC_X_ABSOLUTE,1675 pReq->pointerXPos * cMaxScreenX1676 / VMMDEV_MOUSE_RANGE_MAX);1677 vbgr0SolVUIDPutAbsEvent(&g_aOpenNodeStates[i], LOC_Y_ABSOLUTE,1678 pReq->pointerYPos * cMaxScreenY1679 / VMMDEV_MOUSE_RANGE_MAX);1680 }1681 mutex_exit(&g_StateMutex);1682 }1683 VbglGRFree(&pReq->header);1684 }1685 1686 1687 void vbgr0SolVUIDPutAbsEvent(PVBGR0STATE pState, ushort_t cEvent,1688 int cValue)1689 {1690 queue_t *pReadQueue = RD(pState->pWriteQueue);1691 mblk_t *pMBlk = allocb(sizeof(Firm_event), BPRI_HI);1692 Firm_event *pEvent;1693 AssertReturnVoid(cEvent == LOC_X_ABSOLUTE || cEvent == LOC_Y_ABSOLUTE);1694 if (!pMBlk)1695 return; /* If kernel memory is short a missed event is acceptable! */1696 pEvent = (Firm_event *)pMBlk->b_wptr;1697 pEvent->id = cEvent;1698 pEvent->pair_type = FE_PAIR_DELTA;1699 pEvent->pair = cEvent == LOC_X_ABSOLUTE ? LOC_X_DELTA : LOC_Y_DELTA;1700 pEvent->value = cValue;1701 uniqtime32(&pEvent->time);1702 pMBlk->b_wptr += sizeof(Firm_event);1703 /* Put the message on the queue immediately if it is not blocked. */1704 if (canput(pReadQueue->q_next))1705 putnext(pReadQueue, pMBlk);1706 else1707 putbq(pReadQueue, pMBlk);1708 }1709 1710 1711 /* Common code that depends on g_DevExt. */1712 #ifndef TESTCASE1713 # include "VBoxGuestIDC-unix.c.h"1714 #endif1715 1716 1239 #ifdef TESTCASE 1717 1240 int main(void)
Note:
See TracChangeset
for help on using the changeset viewer.

