VBoxDev-haiku.c revision edc0ced209cf455268870a686b88fd851f3a4188
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/* $Id$ */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/** @file
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * VBoxGuest kernel driver, Haiku Guest Additions, implementation.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Copyright (C) 2012 Oracle Corporation
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * available from http://www.virtualbox.org. This file is free software;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * you can redistribute it and/or modify it under the terms of the GNU
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * General Public License (GPL) as published by the Free Software
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * This code is based on:
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * VirtualBox Guest Additions for Haiku.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Copyright (c) 2011 Mike Smith <mike@scgtrp.net>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Fran�ois Revol <revol@free.fr>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Permission is hereby granted, free of charge, to any person
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * obtaining a copy of this software and associated documentation
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * files (the "Software"), to deal in the Software without
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * restriction, including without limitation the rights to use,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * copies of the Software, and to permit persons to whom the
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Software is furnished to do so, subject to the following
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * conditions:
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * The above copyright notice and this permission notice shall be
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * included in all copies or substantial portions of the Software.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * OTHER DEALINGS IN THE SOFTWARE.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#define LOG_GROUP LOG_GROUP_SUP_DRV
edc0ced209cf455268870a686b88fd851f3a4188vboxsync//#undef LOG_DISABLED
edc0ced209cf455268870a686b88fd851f3a4188vboxsync//#define LOG_ENABLED
edc0ced209cf455268870a686b88fd851f3a4188vboxsync//#define LOG_ENABLE_FLOW
edc0ced209cf455268870a686b88fd851f3a4188vboxsync//#define DO_LOG
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <sys/param.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <sys/types.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <sys/uio.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <OS.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <Drivers.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <KernelExport.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <PCI.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include "VBoxGuest-haiku.h"
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include "VBoxGuestInternal.h"
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <VBox/log.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <iprt/assert.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <iprt/initterm.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <iprt/process.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <iprt/mem.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#include <iprt/asm.h>
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#define DRIVER_NAME "vboxdev"
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#define DEVICE_NAME "misc/vboxguest"
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#define MODULE_NAME "generic/vboxguest"
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuOpen(const char *name, uint32 flags, void **cookie);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuClose(void *cookie);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuFree(void *cookie);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuDeselect(void *cookie, uint8 event, selectsync *sync);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic device_hooks g_VBoxGuestHaikuDeviceHooks =
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuOpen,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuClose,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuFree,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuIOCtl,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuRead,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuWrite,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuSelect,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuDeselect,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync};
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/**
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * File open handler
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuOpen(const char *name, uint32 flags, void **cookie)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync int rc;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogFlow((DRIVER_NAME ":VBoxGuestHaikuOpen\n"));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Create a new session.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_SUCCESS(rc))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ":VBoxGuestHaikuOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n",&g_DevExt, pSession, rc,(int)RTProcSelf()));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync ASMAtomicIncU32(&cUsers);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *cookie = pSession;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogRel((DRIVER_NAME ":VBoxGuestHaikuOpen: failed. rc=%d\n", rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return RTErrConvertToErrno(rc);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/**
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * File close handler
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuClose(void *cookie)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSPINLOCKTMP tmp;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log(("VBoxGuestHaikuClose: pSession=%p\n", pSession));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSpinlockAcquireNoInts(g_DevExt.SessionSpinlock, &tmp);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //XXX: we don't know if it belongs to this session !
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (sState.selectSync)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "close: unblocking select %p %x\n", sState.selectSync, sState.selectEvent);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync notify_select_event(sState.selectSync, sState.selectEvent);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectEvent = (uint8_t)0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectRef = (uint32_t)0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectSync = (void *)NULL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSpinlockReleaseNoInts(g_DevExt.SessionSpinlock, &tmp);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/**
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * File free handler
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuFree(void *cookie)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log(("VBoxGuestHaikuFree: pSession=%p\n", pSession));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Close the session if it's still hanging on to the device...
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (VALID_PTR(pSession))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestCloseSession(&g_DevExt, pSession);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync ASMAtomicDecU32(&cUsers);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync else
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log(("VBoxGuestHaikuFree: si_drv1=%p!\n", pSession));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/**
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * IOCTL handler
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //Log(("VBoxGuestHaikuFree: pSession=%p\n", pSession));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //LogFlow((DRIVER_NAME ":VBoxGuestHaikuIOCtl(, 0x%08x, %p, %d)\n", op, data, len));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl(, 0x%08x, %p, %d)\n", op, data, len));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync int rc = 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Validate the input.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(!VALID_PTR(pSession)))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return EINVAL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Validate the request wrapper.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#if 0
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ": VBoxGuestHaikuIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd), sizeof(VBGLBIGREQ)));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return ENOTTY;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#endif
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(len > _1M * 16))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync dprintf(DRIVER_NAME ": VBoxGuestHaikuIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", len, data, op);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return EINVAL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Read the request.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync void *pvBuf = NULL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_LIKELY(len > 0))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync pvBuf = RTMemTmpAlloc(len);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(!pvBuf))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", len));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return ENOMEM;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = user_memcpy(pvBuf, data, len);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(rc < 0))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTMemTmpFree(pvBuf);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: user_memcpy failed; pvBuf=%p data=%p op=%d. rc=%d\n", pvBuf, data, op, rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return EFAULT;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(!VALID_PTR(pvBuf)))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTMemTmpFree(pvBuf);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: pvBuf invalid pointer %p\n", pvBuf));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return EINVAL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: pSession=%p pid=%d.\n", pSession,(int)RTProcSelf()));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /*
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Process the IOCtl.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync size_t cbDataReturned;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = VBoxGuestCommonIOCtl(op, &g_DevExt, pSession, pvBuf, len, &cbDataReturned);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_SUCCESS(rc))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(cbDataReturned > len))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: too much output data %d expected %d\n", cbDataReturned, len));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync cbDataReturned = len;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (cbDataReturned > 0)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = user_memcpy(data, pvBuf, cbDataReturned);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(rc < 0))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: user_memcpy failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, op, rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = EFAULT;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync else
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: VBoxGuestCommonIOCtl failed. rc=%d\n", rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = EFAULT;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTMemTmpFree(pvBuf);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return rc;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#if 0
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#endif
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSPINLOCKTMP tmp;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync status_t err = B_OK;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "select(,%d,%p)\n", event, sync);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync switch (event)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync case B_SELECT_READ:
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //case B_SELECT_ERROR:
edc0ced209cf455268870a686b88fd851f3a4188vboxsync break;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync default:
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return EINVAL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSpinlockAcquireNoInts(g_DevExt.SessionSpinlock, &tmp);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (pSession->u32MousePosChangedSeq != u32CurSeq)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "select: notifying now: %p %x\n", sync, event);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync pSession->u32MousePosChangedSeq = u32CurSeq;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync notify_select_event(sync, event);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync else if (sState.selectSync == NULL)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "select: caching: %p %x\n", sync, event);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectEvent = (uint8_t)event;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectRef = (uint32_t)ref;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectSync = (void *)sync;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync else
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "select: dropping: %p %x\n", sync, event);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync err = B_WOULD_BLOCK;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSpinlockReleaseNoInts(g_DevExt.SessionSpinlock, &tmp);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return err;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#if 0
edc0ced209cf455268870a686b88fd851f3a4188vboxsync int fEventsProcessed;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogFlow((DRIVER_NAME "::Poll: fEvents=%d\n", fEvents));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (RT_UNLIKELY(!VALID_PTR(pSession)))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log((DRIVER_NAME "::Poll: no state data for %s\n", devtoname(pDev)));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return (fEvents & (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (pSession->u32MousePosChangedSeq != u32CurSeq)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync fEventsProcessed = fEvents & (POLLIN | POLLRDNORM);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync pSession->u32MousePosChangedSeq = u32CurSeq;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync else
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync fEventsProcessed = 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync selrecord(td, &g_SelInfo);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return fEventsProcessed;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync#endif
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuDeselect(void *cookie, uint8 event, selectsync *sync)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSPINLOCKTMP tmp;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync status_t err = B_OK;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSpinlockAcquireNoInts(g_DevExt.SessionSpinlock, &tmp);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (sState.selectSync == sync)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "deselect: dropping: %p %x\n", sState.selectSync, sState.selectEvent);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectEvent = (uint8_t)0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectRef = (uint32_t)0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync sState.selectSync = NULL;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync else
edc0ced209cf455268870a686b88fd851f3a4188vboxsync err = B_OK;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync RTSpinlockReleaseNoInts(g_DevExt.SessionSpinlock, &tmp);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return err;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *numBytes = 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic status_t VBoxGuestHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "read(,,%d)\n", *numBytes);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (*numBytes == 0)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (pSession->u32MousePosChangedSeq != u32CurSeq)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync pSession->u32MousePosChangedSeq = u32CurSeq;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync //dprintf(DRIVER_NAME "read: giving 1 byte\n");
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *numBytes = 1;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync }
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync *numBytes = 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return 0;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncint32 api_version = B_CUR_DRIVER_API_VERSION;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatus_t init_hardware()
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return get_module(MODULE_NAME, (module_info **)&g_VBoxGuest);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatus_t init_driver()
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return B_OK;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncdevice_hooks* find_device(const char *name)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync static device_hooks g_VBoxGuestHaikuDeviceHooks =
edc0ced209cf455268870a686b88fd851f3a4188vboxsync {
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuOpen,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuClose,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuFree,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuIOCtl,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuRead,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuWrite,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuSelect,
edc0ced209cf455268870a686b88fd851f3a4188vboxsync VBoxGuestHaikuDeselect
edc0ced209cf455268870a686b88fd851f3a4188vboxsync };
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return &g_VBoxGuestHaikuDeviceHooks;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncconst char** publish_devices()
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync static const char *devices[] = { DEVICE_NAME, NULL };
edc0ced209cf455268870a686b88fd851f3a4188vboxsync return devices;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncvoid uninit_driver()
edc0ced209cf455268870a686b88fd851f3a4188vboxsync{
edc0ced209cf455268870a686b88fd851f3a4188vboxsync put_module(MODULE_NAME);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync}
edc0ced209cf455268870a686b88fd851f3a4188vboxsync