DrvHostParallel.cpp revision 7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4c
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington/* $Id$ */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * VirtualBox Host Parallel Port Driver.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Contributed by: Alexander Eichner
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (C) 2006-2010 Oracle Corporation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This file is part of VirtualBox Open Source Edition (OSE), as
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * available from http://www.virtualbox.org. This file is free software;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * you can redistribute it and/or modify it under the terms of the GNU
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * General Public License (GPL) as published by the Free Software
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Foundation, in version 2 as it comes in the "COPYING" file of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster* Header Files *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster*******************************************************************************/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define LOG_GROUP LOG_GROUP_DRV_HOST_PARALLEL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <VBox/vmm/pdmdrv.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <VBox/vmm/pdmthread.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <iprt/asm.h>
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington#include <iprt/assert.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <iprt/file.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <iprt/pipe.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <iprt/semaphore.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <iprt/stream.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <iprt/uuid.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef RT_OS_LINUX
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <sys/ioctl.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <sys/types.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <sys/stat.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <sys/poll.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <fcntl.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <unistd.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <linux/ppdev.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <linux/parport.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include <errno.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "VBoxDD.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster* Structures and Typedefs *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster*******************************************************************************/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Host parallel port driver instance data.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @implements PDMIHOSTPARALLELCONNECTOR
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef struct DRVHOSTPARALLEL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington /** Pointer to the driver instance structure. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PPDMDRVINS pDrvIns;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Pointer to the char port interface of the driver/device above us. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PPDMIHOSTPARALLELPORT pDrvHostParallelPort;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Our host device interface. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDMIHOSTPARALLELCONNECTOR IHostParallelConnector;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Device Path */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char *pszDevicePath;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Device Handle */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster RTFILE hFileDevice;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Thread waiting for interrupts. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PPDMTHREAD pMonitorThread;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Wakeup pipe read end. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster RTPIPE hWakeupPipeR;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Wakeup pipe write end. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster RTPIPE hWakeupPipeW;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Current mode the parallel port is in. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDMPARALLELPORTMODE enmModeCur;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster} DRVHOSTPARALLEL, *PDRVHOSTPARALLEL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Converts a pointer to DRVHOSTPARALLEL::IHostDeviceConnector to a PDRHOSTPARALLEL. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostParallelConnector)) )
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Changes the current mode of the host parallel port.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns VBox status code.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pThis The host parallel port instance data.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param enmMode The mode to change the port to.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int drvHostParallelSetMode(PDRVHOSTPARALLEL pThis, PDMPARALLELPORTMODE enmMode)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int iMode = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: mode=%d\n", __FUNCTION__, enmMode));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (pThis->enmModeCur != enmMode)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster switch (enmMode)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case PDM_PARALLEL_PORT_MODE_SPP:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster iMode = IEEE1284_MODE_COMPAT;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case PDM_PARALLEL_PORT_MODE_EPP_DATA:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster iMode = IEEE1284_MODE_EPP | IEEE1284_DATA;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case PDM_PARALLEL_PORT_MODE_EPP_ADDR:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster iMode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case PDM_PARALLEL_PORT_MODE_ECP:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case PDM_PARALLEL_PORT_MODE_INVALID:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster default:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return VERR_NOT_SUPPORTED;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPSETMODE, &iMode);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->enmModeCur = enmMode;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* -=-=-=-=- IBase -=-=-=-=- */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @interface_method_impl{PDMIBASE,pfnQueryInterface}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(void *) drvHostParallelQueryInterface(PPDMIBASE pInterface, const char *pszIID)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTPARALLELCONNECTOR, &pThis->IHostParallelConnector);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* -=-=-=-=- IHostDeviceConnector -=-=-=-=- */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @copydoc PDMICHARCONNECTOR::pfnWrite */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf, size_t cbWrite, PDMPARALLELPORTMODE enmMode)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = drvHostParallelSetMode(pThis, enmMode);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_FAILURE(rc))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (enmMode == PDM_PARALLEL_PORT_MODE_SPP)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Set the data lines directly. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWDATA, pvBuf);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Use write interface. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = write(RTFileToNative(pThis->hFileDevice), pvBuf, cbWrite);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf, size_t cbRead, PDMPARALLELPORTMODE enmMode)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: pvBuf=%#p cbRead=%d\n", __FUNCTION__, pvBuf, cbRead));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = drvHostParallelSetMode(pThis, enmMode);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_FAILURE(rc))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (enmMode == PDM_PARALLEL_PORT_MODE_SPP)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Set the data lines directly. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWDATA, pvBuf);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Use write interface. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = read(RTFileToNative(pThis->hFileDevice), pvBuf, cbRead);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelSetPortDirection(PPDMIHOSTPARALLELCONNECTOR pInterface, bool fForward)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int iMode = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!fForward)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster iMode = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPDATADIR, &iMode);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelWriteControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t fReg)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: fReg=%d\n", __FUNCTION__, fReg));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWCONTROL, &fReg);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelReadControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint8_t fReg = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPRCONTROL, &fReg);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: fReg=%d\n", __FUNCTION__, fReg));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *pfReg = fReg;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelReadStatus(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rcLnx = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint8_t fReg = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPRSTATUS, &fReg);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_UNLIKELY(rcLnx < 0))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: fReg=%d\n", __FUNCTION__, fReg));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *pfReg = fReg;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelMonitorThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct pollfd aFDs[2];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * We can wait for interrupts using poll on linux hosts.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (pThread->enmState == PDMTHREADSTATE_RUNNING)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster aFDs[0].fd = RTFileToNative(pThis->hFileDevice);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster aFDs[0].events = POLLIN;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington aFDs[0].revents = 0;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington aFDs[1].fd = RTPipeToNative(pThis->hWakeupPipeR);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster aFDs[1].events = POLLIN | POLLERR | POLLHUP;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster aFDs[1].revents = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = poll(aFDs, RT_ELEMENTS(aFDs), -1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc < 0)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AssertMsgFailed(("poll failed with rc=%d\n", RTErrConvertFromErrno(errno)));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return RTErrConvertFromErrno(errno);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (pThread->enmState != PDMTHREADSTATE_RUNNING)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc > 0 && aFDs[1].revents)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (aFDs[1].revents & (POLLHUP | POLLERR | POLLNVAL))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* notification to terminate -- drain the pipe */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char ch;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster size_t cbRead;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster RTPipeRead(pThis->hWakeupPipeR, &ch, 1, &cbRead);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster continue;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Interrupt occurred. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = pThis->pDrvHostParallelPort->pfnNotifyInterrupt(pThis->pDrvHostParallelPort);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AssertRC(rc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return VINF_SUCCESS;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Unblock the monitor thread so it can respond to a state change.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns a VBox status code.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pDrvIns The driver instance.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pThread The send thread.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelWakeupMonitorThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster size_t cbIgnored;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return RTPipeWrite(pThis->hWakeupPipeW, "", 1, &cbIgnored);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Destruct a host parallel driver instance.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Most VM resources are freed by the VM. This callback is provided so that
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * any non-VM resources can be freed correctly.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pDrvIns The driver instance data.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(void) drvHostParallelDestruct(PPDMDRVINS pDrvIns)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (pThis->hFileDevice != NIL_RTFILE)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ioctl(RTFileToNative(pThis->hFileDevice), PPRELEASE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTPipeClose(pThis->hWakeupPipeW); AssertRC(rc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->hWakeupPipeW = NIL_RTPIPE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTPipeClose(pThis->hWakeupPipeR); AssertRC(rc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->hWakeupPipeR = NIL_RTPIPE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTFileClose(pThis->hFileDevice); AssertRC(rc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->hFileDevice = NIL_RTFILE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (pThis->pszDevicePath)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster MMR3HeapFree(pThis->pszDevicePath);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->pszDevicePath = NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Construct a host parallel driver instance.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @copydoc FNPDMDRVCONSTRUCT
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) drvHostParallelConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Init basic data members and interfaces.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Must be done before returning any failure because we've got a destructor.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->hFileDevice = NIL_RTFILE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->hWakeupPipeR = NIL_RTPIPE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->hWakeupPipeW = NIL_RTPIPE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* IBase. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pDrvIns->IBase.pfnQueryInterface = drvHostParallelQueryInterface;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* IHostParallelConnector. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->IHostParallelConnector.pfnWrite = drvHostParallelWrite;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->IHostParallelConnector.pfnRead = drvHostParallelRead;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->IHostParallelConnector.pfnSetPortDirection = drvHostParallelSetPortDirection;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->IHostParallelConnector.pfnWriteControl = drvHostParallelWriteControl;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->IHostParallelConnector.pfnReadControl = drvHostParallelReadControl;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->IHostParallelConnector.pfnReadStatus = drvHostParallelReadStatus;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Validate the config.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!CFGMR3AreValuesValid(pCfg, "DevicePath\0"))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster N_("Unknown host parallel configuration option, only supports DevicePath"));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Query configuration.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Device */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc = CFGMR3QueryStringAlloc(pCfg, "DevicePath", &pThis->pszDevicePath);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_FAILURE(rc))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AssertMsgFailed(("Configuration error: query for \"DevicePath\" string returned %Rra.\n", rc));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Open the device
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = RTFileOpen(&pThis->hFileDevice, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (RT_FAILURE(rc))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Parallel#%d could not open '%s'"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pDrvIns->iInstance, pThis->pszDevicePath);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Try to get exclusive access to parallel port
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = ioctl(RTFileToNative(pThis->hFileDevice), PPEXCL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc < 0)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster N_("Parallel#%d could not get exclusive access for parallel port '%s'"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "Be sure that no other process or driver accesses this port"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pDrvIns->iInstance, pThis->pszDevicePath);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Claim the parallel port
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = ioctl(RTFileToNative(pThis->hFileDevice), PPCLAIM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc < 0)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster N_("Parallel#%d could not claim parallel port '%s'"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "Be sure that no other process or driver accesses this port"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pDrvIns->iInstance, pThis->pszDevicePath);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Get the IHostParallelPort interface of the above driver/device.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
pThis->pDrvHostParallelPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHOSTPARALLELPORT);
if (!pThis->pDrvHostParallelPort)
return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"),
pDrvIns->iInstance);
/*
* Create wakeup pipe.
*/
rc = RTPipeCreate(&pThis->hWakeupPipeR, &pThis->hWakeupPipeW, 0 /*fFlags*/);
AssertRCReturn(rc, rc);
/*
* Start in SPP mode.
*/
pThis->enmModeCur = PDM_PARALLEL_PORT_MODE_INVALID;
rc = drvHostParallelSetMode(pThis, PDM_PARALLEL_PORT_MODE_SPP);
if (RT_FAILURE(rc))
return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot change mode of parallel mode to SPP"), pDrvIns->iInstance);
/*
* Start waiting for interrupts.
*/
rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0,
RTTHREADTYPE_IO, "ParMon");
if (RT_FAILURE(rc))
return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot create monitor thread"), pDrvIns->iInstance);
return VINF_SUCCESS;
}
/**
* Char driver registration record.
*/
const PDMDRVREG g_DrvHostParallel =
{
/* u32Version */
PDM_DRVREG_VERSION,
/* szName */
"HostParallel",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"Parallel host driver.",
/* fFlags */
PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
/* fClass. */
PDM_DRVREG_CLASS_CHAR,
/* cMaxInstances */
~0,
/* cbInstance */
sizeof(DRVHOSTPARALLEL),
/* pfnConstruct */
drvHostParallelConstruct,
/* pfnDestruct */
drvHostParallelDestruct,
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
PDM_DRVREG_VERSION
};