SUPDrv-os2.cpp revision 36200fc93ca319528d532c4b082b2935b151a131
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* $Id$ */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VBoxDrv - OS/2 specifics.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Permission is hereby granted, free of charge, to any person
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * obtaining a copy of this software and associated documentation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * files (the "Software"), to deal in the Software without
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * restriction, including without limitation the rights to use,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * copies of the Software, and to permit persons to whom the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Software is furnished to do so, subject to the following
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * conditions:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The above copyright notice and this permission notice shall be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * included in all copies or substantial portions of the Software.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * OTHER DEALINGS IN THE SOFTWARE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Header Files *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <os2ddk/bsekee.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#undef RT_MAX
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "SUPDRV.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/version.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/initterm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/string.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/spinlock.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/process.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/assert.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/log.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Global Variables *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Device extention & session data association structure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic SUPDRVDEVEXT g_DevExt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Spinlock protecting g_apSessionHashTab. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Hash table */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic PSUPDRVSESSION g_apSessionHashTab[19];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Calculates the index into g_apSessionHashTab.*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync__BEGIN_DECLS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Defined in SUPDrvA-os2.asm */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern uint16_t g_offLogHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern uint16_t volatile g_offLogTail;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern uint16_t const g_cchLogMax;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern char g_szLog[];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* (init only:) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern char g_szInitText[];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern uint16_t g_cchInitText;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern uint16_t g_cchInitTextMax;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync__END_DECLS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Internal Functions *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 32-bit Ring-0 initialization.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns 0 on success, non-zero on failure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pszArgs Pointer to the device arguments.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLASM(int) VBoxDrvInit(const char *pszArgs)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dprintf(("VBoxDrvInit: pszArgs=%s\n", pszArgs));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Initialize the runtime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTR0Init(0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Initialize the device extension.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = supdrvInitDevExt(&g_DevExt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Initialize the session hash table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTSpinlockCreate(&g_Spinlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Process the commandline. Later.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool fVerbose = true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fVerbose)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strcpy(&g_szInitText[0],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "\r\n"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "VirtualBox.org Support Driver for OS/2 version " VBOX_VERSION_STRING "\r\n"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Copyright (C) 2007 Knut St. Osmundsen\r\n"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Copyright (C) 2007 InnoTek Systemberatung GmbH\r\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync g_cchInitText = strlen(&g_szInitText[0]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTSpinlockCreate failed, rc=%Vrc\n", rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync supdrvDeleteDevExt(&g_DevExt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: supdrvInitDevExt failed, rc=%Vrc\n", rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTR0Term();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTR0Init failed, rc=%Vrc\n", rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLASM(int) VBoxDrvOpen(uint16_t sfn)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSUPDRVSESSION pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Create a new session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = supdrvCreateSession(&g_DevExt, &pSession);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession->Process = RTProcSelf();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession->R0Process = RTR0ProcHandleSelf();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession->sfn = sfn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Insert it into the hash table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync unsigned iHash = SESSION_HASH(sfn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession->pNextHash = g_apSessionHashTab[iHash];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync g_apSessionHashTab[iHash] = pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dprintf(("VBoxDrvOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLASM(int) VBoxDrvClose(uint16_t sfn)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dprintf(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Remove from the hash table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSUPDRVSESSION pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const RTPROCESS Process = RTProcSelf();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const unsigned iHash = SESSION_HASH(sfn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession = g_apSessionHashTab[iHash];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pSession)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( pSession->sfn == sfn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pSession->Process == Process)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync g_apSessionHashTab[iHash] = pSession->pNextHash;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession->pNextHash = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSUPDRVSESSION pPrev = pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession = pSession->pNextHash;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (pSession)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( pSession->sfn == sfn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pSession->Process == Process)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pPrev->pNextHash = pSession->pNextHash;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession->pNextHash = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* next */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pPrev = pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession = pSession->pNextHash;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pSession)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Close the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync supdrvCloseSession(&g_DevExt, pSession);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction, int32_t *prc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Find the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const RTPROCESS Process = RTProcSelf();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const unsigned iHash = SESSION_HASH(sfn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSUPDRVSESSION pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession = g_apSessionHashTab[iHash];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pSession && pSession->Process != Process)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do pSession = pSession->pNextHash;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ( pSession
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && ( pSession->sfn != sfn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync || pSession->Process != Process));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_UNLIKELY(!pSession))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Dispatch the fast IOCtl.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *prc = supdrvIOCtlFast(iFunction, &g_DevExt, pSession);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Find the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const RTPROCESS Process = RTProcSelf();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const unsigned iHash = SESSION_HASH(sfn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSUPDRVSESSION pSession;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSession = g_apSessionHashTab[iHash];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pSession && pSession->Process != Process)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do pSession = pSession->pNextHash;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ( pSession
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && ( pSession->sfn != sfn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync || pSession->Process != Process));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pSession)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Verify the category and dispatch the IOCtl.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_LIKELY(iCat == SUP_CTL_CATEGORY))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dprintf(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pvParm);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(!pvData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Lock the buffers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSUPDRVIOCTLDATA pArgs = (PSUPDRVIOCTLDATA)pvParm;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertReturn(*pcbParm == sizeof(*pArgs), VERR_INVALID_PARAMETER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KernVMLock_t ParmLock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = KernVMLock(VMDHL_WRITE, pvParm, *pcbParm, &ParmLock, (KernPageList_t *)-1, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pvParm, *pcbParm, &ParmLock, rc), VERR_LOCK_FAILED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* lock the in and out buffers. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KernVMLock_t InLock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool fInLocked = pArgs->pvIn && pArgs->cbIn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fInLocked)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = KernVMLock(VMDHL_WRITE, pArgs->pvIn, pArgs->cbIn, &InLock, (KernPageList_t *)-1, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (rc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pArgs->pvIn, pArgs->cbIn, &InLock, rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KernVMUnlock(&ParmLock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_LOCK_FAILED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KernVMLock_t OutLock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool fOutLocked = pArgs->pvOut && pArgs->cbOut;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fOutLocked)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = KernVMLock(VMDHL_WRITE, pArgs->pvOut, pArgs->cbOut, &OutLock, (KernPageList_t *)-1, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (rc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pArgs->pvOut, pArgs->cbOut, &OutLock, rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KernVMUnlock(&ParmLock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fInLocked)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KernVMUnlock(&InLock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_LOCK_FAILED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Process the IOCtl.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync unsigned cbReturned = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pArgs->rc = rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pArgs->pvIn, pArgs->cbIn, pArgs->pvOut, pArgs->cbOut, &cbReturned);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Unlock the buffers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fOutLocked)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc2 = KernVMUnlock(&OutLock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsg(!rc2, ("rc2=%d\n", rc2));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fInLocked)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc2 = KernVMUnlock(&InLock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsg(!rc2, ("rc2=%d\n", rc2));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc2 = KernVMUnlock(&ParmLock);
AssertMsg(!rc2, ("rc2=%d\n", rc2));
dprintf2(("VBoxDrvIOCtl: returns VINF_SUCCESS / %d\n", rc));
return VINF_SUCCESS;
}
return VERR_NOT_SUPPORTED;
}
void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
{
NOREF(pObj);
NOREF(pSession);
}
bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
{
NOREF(pObj);
NOREF(pSession);
NOREF(pszObjName);
NOREF(prc);
return false;
}
/**
* Callback for writing to the log buffer.
*
* @returns number of bytes written.
* @param pvArg Unused.
* @param pachChars Pointer to an array of utf-8 characters.
* @param cbChars Number of bytes in the character array pointed to by pachChars.
*/
static DECLCALLBACK(size_t) VBoxDrvLogOutput(void *pvArg, const char *pachChars, size_t cbChars)
{
size_t cchWritten = 0;
while (cbChars-- > 0)
{
const uint16_t offLogHead = g_offLogHead;
const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
if (offLogHeadNext == g_offLogTail)
break; /* no */
g_szLog[offLogHead] = *pachChars++;
g_offLogHead = offLogHeadNext;
cchWritten++;
}
return cchWritten;
}
SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
{
va_list va;
#if 0 //def DEBUG_bird
va_start(va, pszFormat);
RTLogComPrintfV(pszFormat, va);
va_end(va);
#endif
va_start(va, pszFormat);
int cch = RTLogFormatV(VBoxDrvLogOutput, NULL, pszFormat, va);
va_end(va);
return cch;
}