VirtualBox

Changeset 41705 in vbox


Ignore:
Timestamp:
Jun 14, 2012 11:41:34 AM (12 years ago)
Author:
vboxsync
Message:

Additions/solaris: separate kernel mouse driver code again.

Location:
trunk/src/VBox/Additions
Files:
4 added
1 deleted
2 edited
2 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/Makefile.kmk

    r41683 r41705  
    213213endif
    214214
    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-solaris
    219   tstVBoxGuest-solaris_TEMPLATE = VBOXR3TSTEXE
    220   tstVBoxGuest-solaris_SOURCES  = \
    221         VBoxGuest-solaris-streams.c \
    222         testcase/tstVBoxGuest-solaris.c
    223   tstVBoxGuest-solaris_DEFS     = TESTCASE
    224   tstVBoxGuest-solaris_LIBS     = $(LIB_RUNTIME)
    225  endif
    226 endif
    227 
    228215include $(FILE_KBUILD_SUB_FOOTER)
    229216
  • trunk/src/VBox/Additions/solaris/Makefile.kmk

    r41704 r41705  
    3434ifeq ($(KBUILD_TARGET),solaris)
    3535 include $(PATH_SUB_CURRENT)/SharedFolders/Makefile.kmk
     36 include $(PATH_SUB_CURRENT)/Mouse/Makefile.kmk
    3637 include $(PATH_SUB_CURRENT)/DRM/Makefile.kmk
    3738endif
  • trunk/src/VBox/Additions/solaris/Mouse/testcase/solaris.h

    r41679 r41705  
    55
    66/*
    7  * Copyright (C) 2011 Oracle Corporation
     7 * Copyright (C) 2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1111 * you can redistribute it and/or modify it under the terms of the GNU
    1212 * 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 the
     13 * Foundation, in version 2 as it comes in the "COPYING" file of the
    1414 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1515 * 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.
    1625 */
    1726
  • trunk/src/VBox/Additions/solaris/Mouse/testcase/tstVBoxMouse-solaris.c

    r41679 r41705  
    1313 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1414 * 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.
    1524 */
    1625 
  • trunk/src/VBox/Additions/solaris/Mouse/vboxmouse.c

    r41679 r41705  
    1414 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1515 * 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.
    1625 */
    1726
     
    2534# include <sys/modctl.h>
    2635# include <sys/msio.h>
    27 # include <sys/mutex.h>
    2836# include <sys/pci.h>
    2937# include <sys/stat.h>
     
    4452#endif  /* TESTCASE */
    4553
    46 #include "VBoxGuestInternal.h"
     54#include "../../common/VBoxGuestLib/SysHlp.h"
     55#include <VBox/VBoxGuest.h>
     56#include <VBox/VBoxGuestLib.h>
    4757#include <VBox/log.h>
    4858#include <VBox/version.h>
     
    6676
    6777/** The module name. */
    68 #define DEVICE_NAME              "vboxguest"
     78#define DEVICE_NAME              "vboxmouse"
    6979/** 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"
    7381
    7482
     
    7785******************************************************************************/
    7886
    79 static int vbgr0SolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag,
     87static int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag,
    8088                                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);
     89static int vbmsSolClose(queue_t *pReadQueue, int fFlag, cred_t *pCred);
     90static int vbmsSolWPut(queue_t *pWriteQueue, mblk_t *pMBlk);
    8791
    8892
     
    96100 * mod_info: STREAMS module information.
    97101 */
    98 static struct module_info g_vbgr0SolModInfo =
     102static struct module_info g_vbmsSolModInfo =
    99103{
    100104    0x0ffff,                /* module id number */
    101     "vboxguest",
     105    "vboxmouse",
    102106    0,                      /* minimum packet size */
    103107    INFPSZ,                 /* maximum packet size accepted */
     
    111115 * the put and service procedures.
    112116 */
    113 static struct qinit g_vbgr0SolRInit =
     117static struct qinit g_vbmsSolRInit =
    114118{
    115119    NULL,                /* put */
    116120    NULL,                /* service thread procedure */
    117     vbgr0SolOpen,
    118     vbgr0SolClose,
     121    vbmsSolOpen,
     122    vbmsSolClose,
    119123    NULL,                /* reserved */
    120     &g_vbgr0SolModInfo,
     124    &g_vbmsSolModInfo,
    121125    NULL                 /* module statistics structure */
    122126};
     
    129133 * hardware pointer drivers to a single virtual pointer.
    130134 */
    131 static struct qinit g_vbgr0SolWInit =
    132 {
    133     vbgr0SolWPut,
     135static struct qinit g_vbmsSolWInit =
     136{
     137    vbmsSolWPut,
    134138    NULL,                   /* service thread procedure */
    135139    NULL,                   /* open */
    136140    NULL,                   /* close */
    137141    NULL,                   /* reserved */
    138     &g_vbgr0SolModInfo,
     142    &g_vbmsSolModInfo,
    139143    NULL                    /* module statistics structure */
    140144};
     
    143147 * streamtab: for drivers that support char/block entry points.
    144148 */
    145 static struct streamtab g_vbgr0SolStreamTab =
    146 {
    147     &g_vbgr0SolRInit,
    148     &g_vbgr0SolWInit,
     149static struct streamtab g_vbmsSolStreamTab =
     150{
     151    &g_vbmsSolRInit,
     152    &g_vbmsSolWInit,
    149153    NULL,                   /* MUX rinit */
    150154    NULL                    /* MUX winit */
     
    152156
    153157/**
    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 */
     160static struct fmodsw g_vbmsSolStrWrapper = {
     161    "vboxmouse",
     162    &g_vbmsSolStreamTab,
     163    D_MP | D_MTPERMOD
    173164};
    174165
    175166/**
    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 */
     169static 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
    191174};
    192175
    193176/**
    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_vbgr0SolDevOps
    201 };
    202 
    203 /**
    204177 * modlinkage: export install/remove/info to the kernel.
    205178 */
    206 static struct modlinkage g_vbgr0SolModLinkage =
     179static struct modlinkage g_vbmsSolModLinkage =
    207180{
    208181    MODREV_1,               /* loadable module system revision */
    209     &g_vbgr0SolModule,
     182    &g_vbmsSolModule,
    210183    NULL                    /* terminate array of linkage structures */
    211184};
    212185
    213186#else  /* TESTCASE */
    214 static void *g_vbgr0SolModLinkage;
     187static void *g_vbmsSolModLinkage;
    215188#endif  /* TESTCASE */
    216189
     
    220193typedef struct
    221194{
    222     /** Pointer to the session handle. */
    223     PVBOXGUESTSESSION  pSession;
     195    /** Pointer to the Guest Library handle for the main driver. */
     196    VBGLDRIVER         Driver;
    224197    /** The STREAMS write queue which we need for sending messages up to
    225198     * user-space. */
     
    233206     */
    234207    int                cMaxScreenY;
    235 } VBGR0STATE, *PVBGR0STATE;
     208} VBMSSTATE, *PVBMSSTATE;
    236209
    237210
     
    240213******************************************************************************/
    241214
    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. */
     216static VBMSSTATE            g_OpenNodeState /* = { 0 } */;
    274217
    275218
     
    284227     * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
    285228     */
    286     int rc = RTR0Init(0);
     229    int rc = VbglInit();
    287230    if (RT_SUCCESS(rc))
    288231    {
    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_DEBUGGER
    296                          | RTLOGDEST_USER, NULL);
    297         if (RT_SUCCESS(rc))
    298             RTLogRelSetDefaultInstance(pRelLogger);
    299         else
    300             cmn_err(CE_NOTE, "failed to initialize driver logging rc=%d!\n", rc);
    301 
    302232        /*
    303233         * Prevent module autounloading.
    304234         */
    305         pModCtl = mod_getctl(&g_vbgr0SolModLinkage);
     235        modctl_t *pModCtl = mod_getctl(&g_vbmsSolModLinkage);
    306236        if (pModCtl)
    307237            pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    308238        else
    309239            LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
    310         rc = mod_install(&g_vbgr0SolModLinkage);
     240        rc = mod_install(&g_vbmsSolModLinkage);
    311241    }
    312242    else
    313243    {
    314         cmn_err(CE_NOTE, "_init: RTR0Init failed. rc=%d\n", rc);
     244        cmn_err(CE_NOTE, "_init: VbglInit failed. rc=%d\n", rc);
    315245        return EINVAL;
    316246    }
     
    337267
    338268    LogRelFlow((DEVICE_NAME ":_fini\n"));
    339     rc = mod_remove(&g_vbgr0SolModLinkage);
    340     mutex_destroy(&g_StateMutex);
     269    rc = mod_remove(&g_vbmsSolModLinkage);
    341270
    342271    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
     
    352281{
    353282    LogFlow((DEVICE_NAME ":_info\n"));
    354     return mod_info(&g_vbgr0SolModLinkage, pModInfo);
     283    return mod_info(&g_vbmsSolModLinkage, pModInfo);
    355284}
    356285
     
    362291/** Calls the kernel IOCtl to report mouse status to the host on behalf of
    363292 * 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 }
     293static int vbmsSolSetMouseStatus(VBGLDRIVER *pDriver, uint32_t fStatus)
     294{
     295    return vbglDriverIOCtl(pDriver, VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &fStatus,
     296                           sizeof(fStatus));
     297}
     298
    378299
    379300/******************************************************************************
     
    381302******************************************************************************/
    382303
     304static void vbmsSolNotify(void *pvState);
     305static void vbmsSolVUIDPutAbsEvent(PVBMSSTATE pState, ushort_t cEvent,
     306                                   int cValue);
     307
    383308/**
    384309 * Open callback for the read queue, which we use as a generic device open
    385310 * handler.
    386311 */
    387 int vbgr0SolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, int fMode,
     312int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, int fMode,
    388313                 cred_t *pCred)
    389314{
    390315    int                 rc;
    391     PVBOXGUESTSESSION   pSession = NULL;
    392     PVBGR0STATE pState = NULL;
    393     unsigned cInstance;
     316    PVBMSSTATE pState = NULL;
    394317
    395318    NOREF(fFlag);
     
    399322    /*
    400323     * 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.
    404325     */
    405326    if (fMode)
     
    409330    }
    410331
    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."));
    423336        return ENXIO;
    424337    }
     338    pState = &g_OpenNodeState;
    425339
    426340    /*
    427341     * Create a new session.
    428342     */
    429     rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);
     343    rc = vbglDriverOpen(&pState->Driver);
    430344    if (RT_SUCCESS(rc))
    431345    {
    432         pState->pSession = pSession;
    433         *pDev = makedevice(getmajor(*pDev), cInstance);
     346        VBoxGuestMouseSetNotifyCallback NotifyCallback;
     347
    434348        /* Initialise user data for the queues to our state and vice-versa. */
    435349        WR(pReadQueue)->q_ptr = (char *)pState;
    436350        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));
    437357        qprocson(pReadQueue);
    438         LogRel((DEVICE_NAME "::Open: pSession=%p pState=%p pid=%d\n", pSession, pState, (int)RTProcSelf()));
     358        LogRel((DEVICE_NAME "::Open\n"));
    439359        return 0;
    440360    }
    441361
    442362    /* Failed, clean up. */
    443     vbgr0SolResetSoftState(pState);
     363    ASMAtomicWriteNullPtr(&pState->pWriteQueue);
    444364
    445365    LogRel((DEVICE_NAME "::Open: VBoxGuestCreateUserSession failed. rc=%d\n", rc));
     
    449369
    450370/**
     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 */
     376void 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
     410void 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/**
    451435 * Close callback for the read queue, which we use as a generic device close
    452436 * handler.
    453437 */
    454 int vbgr0SolClose(queue_t *pReadQueue, int fFlag, cred_t *pCred)
    455 {
    456     PVBOXGUESTSESSION pSession = NULL;
    457     PVBGR0STATE pState = (PVBGR0STATE)pReadQueue->q_ptr;
    458 
    459     LogFlow((DEVICE_NAME "::Close pid=%d\n", (int)RTProcSelf()));
     438int 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"));
    460444    NOREF(fFlag);
    461445    NOREF(pCred);
     
    466450        return EFAULT;
    467451    }
     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));
    468458    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     }
    479459
    480460    /*
    481461     * Close the session.
    482462     */
    483     VBoxGuestCloseSession(&g_DevExt, pSession);
     463    vbglDriverClose(&pState->Driver);
     464    ASMAtomicWriteNullPtr(&pState->pWriteQueue);
     465    pReadQueue->q_ptr = NULL;
    484466    return 0;
    485467}
     
    487469
    488470#ifdef TESTCASE
    489 /** Simple test of vbgr0SolOpen and vbgr0SolClose. */
     471/** Simple test of vbmsSolOpen and vbmsSolClose. */
    490472static void testOpenClose(RTTEST hTest)
    491473{
    492     queue_t aQueues[4];
     474    queue_t aQueues[2];
    493475    dev_t device = 0;
    494476    int rc;
    495477
    496     RTTestSub(hTest, "Testing vbgr0SolOpen and vbgr0SolClose");
    497     RT_ZERO(g_aOpenNodeStates);
     478    RTTestSub(hTest, "Testing vbmsSolOpen and vbmsSolClose");
     479    RT_ZERO(g_OpenNodeState);
    498480    RT_ZERO(aQueues);
    499481    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);
    502483    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);
    509486}
    510487#endif
    511488
    512489
    513 /* Helper for vbgr0SolWPut. */
    514 static int vbgr0SolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk);
     490/* Helper for vbmsSolWPut. */
     491static int vbmsSolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk);
    515492
    516493/**
     
    518495 * land in our write queue.
    519496 */
    520 int vbgr0SolWPut(queue_t *pWriteQueue, mblk_t *pMBlk)
     497int vbmsSolWPut(queue_t *pWriteQueue, mblk_t *pMBlk)
    521498{
    522499    LogRelFlowFunc((DEVICE_NAME "::\n"));
     
    540517        case M_IOCDATA:
    541518        {
    542             int err = vbgr0SolDispatchIOCtl(pWriteQueue, pMBlk);
     519            int err = vbmsSolDispatchIOCtl(pWriteQueue, pMBlk);
    543520            if (!err)
    544521                qreply(pWriteQueue, pMBlk);
     
    564541                                     struct msgb *pMBlk)
    565542{
    566     PVBGR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;
     543    PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr;
    567544    RTTEST_CHECK_MSG_RET(hTest,    pState->cMaxScreenX
    568545                               == g_TestResolution.width - 1,
     
    623600    unsigned i;
    624601
    625     RTTestSub(hTest, "Testing vbgr0WPut");
     602    RTTestSub(hTest, "Testing vbmsWPut");
    626603    for (i = 0; i < RT_ELEMENTS(g_asTestWPut); ++i)
    627604    {
     
    656633    RT_ZERO(aQueues);
    657634    doInitQueues(&aQueues[0]);
    658     rc = vbgr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
     635    rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
    659636    RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc));
    660     RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
     637    RTTEST_CHECK_MSG(hTest,    g_OpenNodeState.pWriteQueue
    661638                            == WR(&aQueues[0]), (hTest, "i=%u\n", i));
    662639    pMBlk->b_datap->db_type = M_IOCTL;
     
    667644           g_asTestWPut[i].cbDataIn);
    668645    pMBlk->b_cont = pMBlkCont;
    669     rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
     646    rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk);
    670647    RTTEST_CHECK_MSG(hTest, pIOCBlk->ioc_error == g_asTestWPut[i].rcExp,
    671648                     (hTest, "i=%u, IOCBlk.ioc_error=%d\n", i,
     
    687664            RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n",
    688665                         __PRETTY_FUNCTION__);
    689     vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
     666    vbmsSolClose(RD(&aQueues[1]), 0, NULL);
    690667    freemsg(pMBlk);
    691668}
     
    712689    RT_ZERO(aQueues);
    713690    doInitQueues(&aQueues[0]);
    714     rc = vbgr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
     691    rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
    715692    RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc));
    716     RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
     693    RTTEST_CHECK_MSG(hTest,    g_OpenNodeState.pWriteQueue
    717694                            == WR(&aQueues[0]), (hTest, "i=%u\n", i));
    718695    pMBlk->b_datap->db_type = M_IOCTL;
     
    721698    *(void **)pMBlkCont->b_rptr = (void *)USER_ADDRESS;
    722699    pMBlk->b_cont = pMBlkCont;
    723     rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
     700    rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk);
    724701    pCopyReq = (struct copyreq *)pMBlk->b_rptr;
    725702    RTTEST_CHECK_MSG(hTest, (   (   g_asTestWPut[i].cbDataIn
     
    767744            RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n",
    768745                         __PRETTY_FUNCTION__);
    769     vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
     746    vbmsSolClose(RD(&aQueues[1]), 0, NULL);
    770747    freemsg(pMBlk);
    771748}
     
    793770    RT_ZERO(aQueues);
    794771    doInitQueues(&aQueues[0]);
    795     rc = vbgr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
     772    rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
    796773    RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc));
    797     RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
     774    RTTEST_CHECK_MSG(hTest,    g_OpenNodeState.pWriteQueue
    798775                            == WR(&aQueues[0]), (hTest, "i=%u\n", i));
    799776    pMBlk->b_datap->db_type = M_IOCDATA;
     
    804781    memcpy(pMBlkCont->b_rptr, g_asTestWPut[i].pvDataIn, g_asTestWPut[i].cbDataIn);
    805782    pMBlk->b_cont = pMBlkCont;
    806     rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
     783    rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk);
    807784    pCopyReq = (struct copyreq *)pMBlk->b_rptr;
    808785    RTTEST_CHECK_MSG(hTest, (   (   g_asTestWPut[i].cbDataOut
     
    834811            RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n",
    835812                         __PRETTY_FUNCTION__);
    836     vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
     813    vbmsSolClose(RD(&aQueues[1]), 0, NULL);
    837814    freemsg(pMBlk);
    838815}
     
    856833    RT_ZERO(aQueues);
    857834    doInitQueues(&aQueues[0]);
    858     rc = vbgr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
     835    rc = vbmsSolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
    859836    RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc));
    860     RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
     837    RTTEST_CHECK_MSG(hTest,    g_OpenNodeState.pWriteQueue
    861838                            == WR(&aQueues[0]), (hTest, "i=%u\n", i));
    862839    pMBlk->b_datap->db_type = M_IOCDATA;
    863840    pCopyResp->cp_cmd = g_asTestWPut[i].iIOCCmd;
    864     rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
     841    rc = vbmsSolWPut(WR(&aQueues[0]), pMBlk);
    865842    RTTEST_CHECK_MSG(hTest, pMBlk->b_datap->db_type == M_IOCACK,
    866843                     (hTest, "i=%u, db_type=%u\n", i,
     
    869846        RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first == pMBlk,
    870847                         (hTest, "i=%u\n", i));
    871     vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
     848    vbmsSolClose(RD(&aQueues[1]), 0, NULL);
    872849    freemsg(pMBlk);
    873850}
     
    903880 *                  implemention.
    904881 */
    905 typedef int FNVBGR0SOLIOCTL(PVBGR0STATE pState, int iCmd, void *pvData,
     882typedef int FNVBMSSOLIOCTL(PVBMSSTATE pState, int iCmd, void *pvData,
    906883                            size_t cbBuffer, size_t *pcbData, int *prc);
    907 typedef FNVBGR0SOLIOCTL *PFNVBGR0SOLIOCTL;
    908 
    909 /* Helpers for vbgr0SolDispatchIOCtl. */
    910 static int vbgr0SolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
    911                                PFNVBGR0SOLIOCTL pfnHandler,
     884typedef FNVBMSSOLIOCTL *PFNVBMSSOLIOCTL;
     885
     886/* Helpers for vbmsSolDispatchIOCtl. */
     887static int vbmsSolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
     888                               PFNVBMSSOLIOCTL pfnHandler,
    912889                               int iCmd, size_t cbTransparent,
    913890                               enum IOCTLDIRECTION enmDirection);
    914 static int vbgr0SolVUIDIOCtl(PVBGR0STATE pState, int iCmd, void *pvData,
     891static int vbmsSolVUIDIOCtl(PVBMSSTATE pState, int iCmd, void *pvData,
    915892                             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);
    918893
    919894/** Table of supported VUID IOCtls. */
     
    953928 * @param  pMBlk        pointer to the STREAMS message block structure.
    954929 */
    955 static int vbgr0SolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk)
     930static int vbmsSolDispatchIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk)
    956931{
    957932    struct iocblk *pIOCBlk = (struct iocblk *)pMBlk->b_rptr;
     
    974949                    cbBuffer     = g_aVUIDIOCtlDescriptions[i].cbBuffer;
    975950                    enmDirection = g_aVUIDIOCtlDescriptions[i].enmDirection;
    976                     return vbgr0SolHandleIOCtl(pWriteQueue, pMBlk,
    977                                                vbgr0SolVUIDIOCtl, iCmd,
     951                    return vbmsSolHandleIOCtl(pWriteQueue, pMBlk,
     952                                               vbmsSolVUIDIOCtl, iCmd,
    978953                                               cbBuffer, enmDirection);
    979954                }
    980955            return EINVAL;
    981956        }
    982         case 'V' << 8:
    983             return ENOTTY;
    984             return vbgr0SolHandleIOCtl(pWriteQueue, pMBlk, vbgr0SolGuestIOCtl,
    985                                        iCmd, 0, UNSPECIFIED);
    986957        default:
    987958            return ENOTTY;
     
    990961
    991962
    992 /* Helpers for vbgr0SolHandleIOCtl. */
    993 static int vbgr0SolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk,
    994                                    PFNVBGR0SOLIOCTL pfnHandler, int iCmd,
     963/* Helpers for vbmsSolHandleIOCtl. */
     964static int vbmsSolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk,
     965                                   PFNVBMSSOLIOCTL pfnHandler, int iCmd,
    995966                                   size_t cbTransparent,
    996967                                   enum IOCTLDIRECTION enmDirection);
    997968
    998 static int vbgr0SolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
    999                                           PFNVBGR0SOLIOCTL pfnHandler,
     969static int vbmsSolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
     970                                          PFNVBMSSOLIOCTL pfnHandler,
    1000971                                          int iCmd, size_t cbTransparent,
    1001972                                          enum IOCTLDIRECTION enmDirection);
    1002973
    1003 static int vbgr0SolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
    1004                                    PFNVBGR0SOLIOCTL pfnHandler, int iCmd);
     974static int vbmsSolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
     975                                   PFNVBMSSOLIOCTL pfnHandler, int iCmd);
    1005976
    1006977/**
     
    1025996 * @param  enmDirection   data transfer direction of the IOCtl.
    1026997 */
    1027 static int vbgr0SolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
    1028                                PFNVBGR0SOLIOCTL pfnHandler, int iCmd,
     998static int vbmsSolHandleIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
     999                               PFNVBMSSOLIOCTL pfnHandler, int iCmd,
    10291000                               size_t cbTransparent,
    10301001                               enum IOCTLDIRECTION enmDirection)
     
    10331004
    10341005    if (pMBlk->b_datap->db_type == M_IOCDATA)
    1035         return vbgr0SolHandleIOCtlData(pWriteQueue, pMBlk, pfnHandler, iCmd,
     1006        return vbmsSolHandleIOCtlData(pWriteQueue, pMBlk, pfnHandler, iCmd,
    10361007                                       cbTransparent, enmDirection);
    10371008    else if (   pMBlk->b_datap->db_type == M_IOCTL
    10381009             && pIOCBlk->ioc_count == TRANSPARENT)
    1039         return vbgr0SolHandleTransparentIOCtl(pWriteQueue, pMBlk, pfnHandler,
     1010        return vbmsSolHandleTransparentIOCtl(pWriteQueue, pMBlk, pfnHandler,
    10401011                                              iCmd, cbTransparent,
    10411012                                              enmDirection);
    10421013    else if (pMBlk->b_datap->db_type == M_IOCTL)
    1043         return vbgr0SolHandleIStrIOCtl(pWriteQueue, pMBlk, pfnHandler, iCmd);
     1014        return vbmsSolHandleIStrIOCtl(pWriteQueue, pMBlk, pfnHandler, iCmd);
    10441015    return EINVAL;
    10451016}
     
    10471018
    10481019/**
    1049  * Helper for vbgr0SolHandleIOCtl.  This rather complicated-looking
     1020 * Helper for vbmsSolHandleIOCtl.  This rather complicated-looking
    10501021 * code is basically the standard boilerplate for handling any streams IOCtl
    10511022 * additional data, which we currently only use for transparent IOCtls.
    1052  * @copydoc vbgr0SolHandleIOCtl
    1053  */
    1054 static int vbgr0SolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk,
    1055                                    PFNVBGR0SOLIOCTL pfnHandler, int iCmd,
     1023 * @copydoc vbmsSolHandleIOCtl
     1024 */
     1025static int vbmsSolHandleIOCtlData(queue_t *pWriteQueue, mblk_t *pMBlk,
     1026                                   PFNVBMSSOLIOCTL pfnHandler, int iCmd,
    10561027                                   size_t cbTransparent,
    10571028                                   enum IOCTLDIRECTION enmDirection)
    10581029{
    10591030    struct copyresp *pCopyResp = (struct copyresp *)pMBlk->b_rptr;
    1060     PVBGR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;
     1031    PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr;
    10611032
    10621033    if (pCopyResp->cp_rval)  /* cp_rval is a pointer used as a boolean. */
     
    10921063
    10931064/**
    1094  * Helper for vbgr0SolHandleIOCtl.  This rather complicated-looking
     1065 * Helper for vbmsSolHandleIOCtl.  This rather complicated-looking
    10951066 * code is basically the standard boilerplate for handling transparent IOCtls,
    10961067 * that is, IOCtls which are not re-packed inside STREAMS IOCtls.
    1097  * @copydoc vbgr0SolHandleIOCtl
    1098  */
    1099 int vbgr0SolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
    1100                                    PFNVBGR0SOLIOCTL pfnHandler, int iCmd,
     1068 * @copydoc vbmsSolHandleIOCtl
     1069 */
     1070int vbmsSolHandleTransparentIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
     1071                                   PFNVBMSSOLIOCTL pfnHandler, int iCmd,
    11011072                                   size_t cbTransparent,
    11021073                                   enum IOCTLDIRECTION enmDirection)
     
    11041075    int err = 0, rc = 0;
    11051076    size_t cbData = 0;
    1106     PVBGR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;
     1077    PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr;
    11071078
    11081079    if (   (enmDirection != NONE && !pMBlk->b_cont)
     
    11421113                 
    11431114/**
    1144  * Helper for vbgr0SolHandleIOCtl.  This rather complicated-looking
     1115 * Helper for vbmsSolHandleIOCtl.  This rather complicated-looking
    11451116 * code is basically the standard boilerplate for handling any streams IOCtl.
    1146  * @copydoc vbgr0SolHandleIOCtl
    1147  */
    1148 static int vbgr0SolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
    1149                                    PFNVBGR0SOLIOCTL pfnHandler, int iCmd)
     1117 * @copydoc vbmsSolHandleIOCtl
     1118 */
     1119static int vbmsSolHandleIStrIOCtl(queue_t *pWriteQueue, mblk_t *pMBlk,
     1120                                   PFNVBMSSOLIOCTL pfnHandler, int iCmd)
    11501121{
    11511122    struct iocblk *pIOCBlk = (struct iocblk *)pMBlk->b_rptr;
    1152     PVBGR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;
     1123    PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr;
    11531124    uint_t cbBuffer = pIOCBlk->ioc_count;
    11541125    void *pvData = NULL;
     
    11751146/**
    11761147 * Handle a VUID input device IOCtl.
    1177  * @copydoc FNVBGR0SOLIOCTL
    1178  */
    1179 static int vbgr0SolVUIDIOCtl(PVBGR0STATE pState, int iCmd, void *pvData,
     1148 * @copydoc FNVBMSSOLIOCTL
     1149 */
     1150static int vbmsSolVUIDIOCtl(PVBMSSTATE pState, int iCmd, void *pvData,
    11801151                             size_t cbBuffer, size_t *pcbData, int *prc)
    11811152{
     
    12271198            pState->cMaxScreenY = pResolution->height - 1;
    12281199            /* Note: we don't disable this again until session close. */
    1229             rc = vbgr0SolSetMouseStatus(pState->pSession,
    1230                                           VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
    1231                                         | VMMDEV_MOUSE_NEW_PROTOCOL);
     1200            rc = vbmsSolSetMouseStatus(&pState->Driver,
     1201                                         VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
     1202                                       | VMMDEV_MOUSE_NEW_PROTOCOL);
    12321203            if (RT_SUCCESS(rc))
    12331204                return 0;
     
    12661237
    12671238
    1268 /**
    1269  * Handle a VBoxGuest IOCtl.
    1270  * @copydoc FNVBGR0SOLIOCTL
    1271  */
    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     else
    1282     {
    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 == 64
    1399 # define VBOXGUEST_OS_TYPE VBOXOSTYPE_Solaris_x64
    1400 #else
    1401 # define VBOXGUEST_OS_TYPE VBOXOSTYPE_Solaris
    1402 #endif
    1403                                 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_TYPE
    1409                                 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                                 else
    1423                                     LogRel((DEVICE_NAME "::Attach: VBoxGuestInitDevExt failed.\n"));
    1424                                 vbgr0SolRemoveIRQ(pDip);
    1425                             }
    1426                             else
    1427                                 LogRel((DEVICE_NAME "::Attach: vbgr0SolAddIRQ failed.\n"));
    1428                             ddi_regs_map_free(&g_PciMMIOHandle);
    1429                         }
    1430                         else
    1431                             LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for MMIO region failed.\n"));
    1432                     }
    1433                     else
    1434                         LogRel((DEVICE_NAME "::Attach: ddi_dev_regsize for MMIO region failed.\n"));
    1435                     ddi_regs_map_free(&g_PciIOHandle);
    1436                 }
    1437                 else
    1438                     LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for IOport failed.\n"));
    1439                 pci_config_teardown(&PciHandle);
    1440             }
    1441             else
    1442                 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_SUCCESS
    1517                 && IntrCount > 0)
    1518             {
    1519                 int IntrAvail = 0;
    1520                 rc = ddi_intr_get_navail(pDip, IntrType, &IntrAvail);
    1521                 if (   rc == DDI_SUCCESS
    1522                     && 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_SUCCESS
    1532                             && 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 will
    1543                                  * 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                             else
    1569                                 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                         else
    1576                             LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount));
    1577                         RTMemFree(g_pIntr);
    1578                     }
    1579                     else
    1580                         LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount));
    1581                 }
    1582                 else
    1583                     LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient available IRQs. rc=%d IntrAvail=%d\n", rc, IntrAvail));
    1584             }
    1585             else
    1586                 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d IntrCount=%d\n", rc, IntrCount));
    1587         }
    1588         else
    1589             LogRel((DEVICE_NAME "::AddIRQ: invalid irq type. IntrType=%#x\n", IntrType));
    1590     }
    1591     else
    1592         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 mouse
    1646  * 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 * cMaxScreenX
    1676                                      / VMMDEV_MOUSE_RANGE_MAX);
    1677             vbgr0SolVUIDPutAbsEvent(&g_aOpenNodeStates[i], LOC_Y_ABSOLUTE,
    1678                                        pReq->pointerYPos * cMaxScreenY
    1679                                      / 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     else
    1707         putbq(pReadQueue, pMBlk);
    1708 }
    1709 
    1710 
    1711 /* Common code that depends on g_DevExt. */
    1712 #ifndef TESTCASE
    1713 # include "VBoxGuestIDC-unix.c.h"
    1714 #endif
    1715 
    17161239#ifdef TESTCASE
    17171240int main(void)
Note: See TracChangeset for help on using the changeset viewer.

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