DevParallel.cpp revision a6e58d30b4d856cf924fda15cd743fed386fff93
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/* $Id$ */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/** @file
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * DevParallel - Parallel (Port) Device Emulation.
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync *
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * Contributed by: Alexander Eichner
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Based on DevSerial.cpp
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync/*
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync *
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * available from http://www.virtualbox.org. This file is free software;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * you can redistribute it and/or modify it under the terms of the GNU
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync * General Public License (GPL) as published by the Free Software
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * additional information or have any questions.
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/*******************************************************************************
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync* Header Files *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync*******************************************************************************/
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync#define LOG_GROUP LOG_GROUP_DEV_PARALLEL
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include <VBox/pdmdev.h>
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include <iprt/assert.h>
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include <iprt/uuid.h>
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include <iprt/string.h>
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include <iprt/semaphore.h>
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include <iprt/critsect.h>
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#include "../Builtins.h"
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/*******************************************************************************
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync* Defined Constants And Macros *
444f91a8285333437cdc9da6bf750121b52f208dvboxsync*******************************************************************************/
444f91a8285333437cdc9da6bf750121b52f208dvboxsync#define PARALLEL_SAVED_STATE_VERSION 1
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync/* defines for accessing the register bits */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync#define LPT_STATUS_BUSY 0x80
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync#define LPT_STATUS_ACK 0x40
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync#define LPT_STATUS_PAPER_OUT 0x20
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync#define LPT_STATUS_SELECT_IN 0x10
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync#define LPT_STATUS_ERROR 0x08
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_STATUS_IRQ 0x04
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_STATUS_BIT1 0x02 /* reserved (only for completeness) */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_STATUS_EPP_TIMEOUT 0x01
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_CONTROL_BIT7 0x80 /* reserved (only for completeness) */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_CONTROL_BIT6 0x40 /* reserved (only for completeness) */
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#define LPT_CONTROL_ENABLE_BIDIRECT 0x20
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#define LPT_CONTROL_ENABLE_IRQ_VIA_ACK 0x10
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#define LPT_CONTROL_SELECT_PRINTER 0x08
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_CONTROL_RESET 0x04
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_CONTROL_AUTO_LINEFEED 0x02
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_CONTROL_STROBE 0x01
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/** mode defines for the extended control register */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_MASK 0xe0
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_GET_BITS(reg) ((reg) >> 5)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_SET_BITS(val) ((val) << 5)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_CONFIGURATION 0x07
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_FIFO_TEST 0x06
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_RESERVED 0x05
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_EPP 0x04
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_ECP_FIFO 0x03
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_PP_FIFO 0x02
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_BYTE 0x01
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_CHIPMODE_COMPAT 0x00
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/** FIFO status bits in extended control register */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_FIFO_MASK 0x03
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_FIFO_SOME_DATA 0x00
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_FIFO_FULL 0x02
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_ECR_FIFO_EMPTY 0x01
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_CONFIGA_FIFO_WITDH_MASK 0x70
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_GET_BITS(reg) ((reg) >> 4)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_SET_BITS(val) ((val) << 4)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_16 0x00
6812cd058fa50aaa6be6d17c291fcf82da713732vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_32 0x20
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_8 0x10
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#define LPT_ECP_FIFO_DEPTH 2
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/*******************************************************************************
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync* Structures and Typedefs *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync*******************************************************************************/
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsynctypedef struct ParallelState
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Access critical section. */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCRITSECT CritSect;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Pointer to the device instance - R3 Ptr */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PPDMDEVINSR3 pDevInsR3;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Pointer to the device instance - R0 Ptr */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PPDMDEVINSR0 pDevInsR0;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Pointer to the device instance - RC Ptr */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PPDMDEVINSRC pDevInsRC;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync RTRCPTR Alignment0; /**< Alignment. */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** The base interface. */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMIBASE IBase;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** The host device port interface. */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMIHOSTPARALLELPORT IHostParallelPort;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Pointer to the attached base driver. */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync R3PTRTYPE(PPDMIBASE) pDrvBase;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Pointer to the attached host device. */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync R3PTRTYPE(PPDMIHOSTPARALLELCONNECTOR) pDrvHostParallelConnector;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /** Unused event semaphore... */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync RTSEMEVENT ReceiveSem;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync uint8_t reg_data;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync uint8_t reg_status;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t reg_control;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t reg_epp_addr;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t reg_epp_data;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t reg_ecp_ecr;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t reg_ecp_base_plus_400h; /* has different meanings */
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t reg_ecp_config_b;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync /** The ECP FIFO implementation*/
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t ecp_fifo[LPT_ECP_FIFO_DEPTH];
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t abAlignemnt[2];
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync int act_fifo_pos_write;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync int act_fifo_pos_read;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync int irq;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint8_t epp_timeout;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync bool fGCEnabled;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync bool fR0Enabled;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync bool afAlignment[1];
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync uint32_t base;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync} DEVPARALLELSTATE, *PDEVPARALLELSTATE;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsynctypedef DEVPARALLELSTATE ParallelState;
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#ifndef VBOX_DEVICE_STRUCT_TESTCASE
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#define PDMIHOSTPARALLELPORT_2_PARALLELSTATE(pInstance) ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostParallelPort)) )
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#define PDMIHOSTDEVICEPORT_2_PARALLELSTATE(pInstance) ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostDevicePort)) )
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync#define PDMIBASE_2_PARALLELSTATE(pInstance) ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IBase)) )
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/*******************************************************************************
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync* Internal Functions *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync*******************************************************************************/
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync__BEGIN_DECLS
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#if 0
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync__END_DECLS
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#ifdef IN_RING3
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncstatic void parallel_set_irq(ParallelState *s)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (s->reg_control & LPT_CONTROL_ENABLE_IRQ_VIA_ACK)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log(("parallel_update_irq %d 1\n", s->irq));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 1);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncstatic void parallel_clear_irq(ParallelState *s)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log(("parallel_update_irq %d 0\n", s->irq));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 0);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
3d0c9ab568ff32132049431e7dc45ea82cda6089vboxsyncstatic int parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *s = (ParallelState *)opaque;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync unsigned char ch;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync addr &= 7;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync LogFlow(("parallel: write addr=0x%02x val=0x%02x\n", addr, val));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ch = val;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync switch(addr) {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync default:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 0:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#ifndef IN_RING3
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync NOREF(ch);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return VINF_IOM_HC_IOPORT_WRITE;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_data = ch;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_LIKELY(s->pDrvHostParallelConnector))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log(("parallel_io_port_write: write 0x%X\n", ch));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync size_t cbWrite = 1;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = s->pDrvHostParallelConnector->pfnWrite(s->pDrvHostParallelConnector, &ch, &cbWrite);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync AssertRC(rc);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 1:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 2:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* Set the reserved bits to one */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ch |= (LPT_CONTROL_BIT6 | LPT_CONTROL_BIT7);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (ch != s->reg_control) {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#ifndef IN_RING3
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return VINF_IOM_HC_IOPORT_WRITE;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = s->pDrvHostParallelConnector->pfnWriteControl(s->pDrvHostParallelConnector, ch);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync AssertRC(rc);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_control = val;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 3:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_epp_addr = val;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 4:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_epp_data = val;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 5:
e1d4cfd32955e4e0f3499b487b46aa33cdd35ceavboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 6:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync case 7:
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync break;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync }
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync return VINF_SUCCESS;
b8ad53d2d49c52c499af516c2c54faa1b50de6e7vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncstatic uint32_t parallel_ioport_read(void *opaque, uint32_t addr, int *pRC)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *s = (ParallelState *)opaque;
444f91a8285333437cdc9da6bf750121b52f208dvboxsync uint32_t ret = ~0U;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *pRC = VINF_SUCCESS;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync addr &= 7;
444f91a8285333437cdc9da6bf750121b52f208dvboxsync switch(addr) {
444f91a8285333437cdc9da6bf750121b52f208dvboxsync default:
444f91a8285333437cdc9da6bf750121b52f208dvboxsync case 0:
444f91a8285333437cdc9da6bf750121b52f208dvboxsync if (!(s->reg_control & LPT_CONTROL_ENABLE_BIDIRECT))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ret = s->reg_data;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#ifndef IN_RING3
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *pRC = VINF_IOM_HC_IOPORT_READ;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_LIKELY(s->pDrvHostParallelConnector))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync size_t cbRead;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = s->pDrvHostParallelConnector->pfnRead(s->pDrvHostParallelConnector, &s->reg_data, &cbRead);
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync Log(("parallel_io_port_read: read 0x%X\n", s->reg_data));
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync AssertRC(rc);
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ret = s->reg_data;
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync#endif
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 1:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#ifndef IN_RING3
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *pRC = VINF_IOM_HC_IOPORT_READ;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_LIKELY(s->pDrvHostParallelConnector))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = s->pDrvHostParallelConnector->pfnReadStatus(s->pDrvHostParallelConnector, &s->reg_status);
444f91a8285333437cdc9da6bf750121b52f208dvboxsync AssertRC(rc);
444f91a8285333437cdc9da6bf750121b52f208dvboxsync }
444f91a8285333437cdc9da6bf750121b52f208dvboxsync ret = s->reg_status;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync parallel_clear_irq(s);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif
444f91a8285333437cdc9da6bf750121b52f208dvboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 2:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ret = s->reg_control;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 3:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ret = s->reg_epp_addr;
444f91a8285333437cdc9da6bf750121b52f208dvboxsync break;
444f91a8285333437cdc9da6bf750121b52f208dvboxsync case 4:
444f91a8285333437cdc9da6bf750121b52f208dvboxsync ret = s->reg_epp_data;
444f91a8285333437cdc9da6bf750121b52f208dvboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 5:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 6:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 7:
444f91a8285333437cdc9da6bf750121b52f208dvboxsync break;
444f91a8285333437cdc9da6bf750121b52f208dvboxsync }
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync LogFlow(("parallel: read addr=0x%02x val=0x%02x\n", addr, ret));
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync return ret;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync#if 0
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncstatic int parallel_ioport_write_ecp(void *opaque, uint32_t addr, uint32_t val)
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync{
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync ParallelState *s = (ParallelState *)opaque;
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync unsigned char ch;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync addr &= 7;
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync LogFlow(("parallel: write ecp addr=0x%02x val=0x%02x\n", addr, val));
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync ch = val;
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync switch(addr) {
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync default:
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync case 0:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync s->ecp_fifo[s->act_fifo_pos_write] = ch;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->act_fifo_pos_write++;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (s->act_fifo_pos_write < LPT_ECP_FIFO_DEPTH) {
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync /* FIFO has some data (clear both FIFO bits) */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync } else {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* FIFO is full */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* Clear FIFO empty bit */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_EMPTY;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* Set FIFO full bit */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_FULL;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->act_fifo_pos_write = 0;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync } else {
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync s->reg_ecp_base_plus_400h = ch;
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync }
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 1:
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync s->reg_ecp_config_b = ch;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 2:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* If we change the mode clear FIFO */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if ((ch & LPT_ECP_ECR_CHIPMODE_MASK) != (s->reg_ecp_ecr & LPT_ECP_ECR_CHIPMODE_MASK)) {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* reset the fifo */
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync s->act_fifo_pos_write = 0;
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync s->act_fifo_pos_read = 0;
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync /* Set FIFO empty bit */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_EMPTY;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* Clear FIFO full bit */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_FULL;
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* Set new mode */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_CHIPMODE_SET_BITS(LPT_ECP_ECR_CHIPMODE_GET_BITS(ch));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync case 3:
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync break;
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync case 4:
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync break;
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync case 5:
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync break;
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync case 6:
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync break;
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync case 7:
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync break;
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync }
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync return VINF_SUCCESS;
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync}
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsyncstatic uint32_t parallel_ioport_read_ecp(void *opaque, uint32_t addr, int *pRC)
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync{
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync ParallelState *s = (ParallelState *)opaque;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync uint32_t ret = ~0U;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync *pRC = VINF_SUCCESS;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync addr &= 7;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync switch(addr) {
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync default:
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync case 0:
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync ret = s->ecp_fifo[s->act_fifo_pos_read];
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync s->act_fifo_pos_read++;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync if (s->act_fifo_pos_read == LPT_ECP_FIFO_DEPTH)
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync s->act_fifo_pos_read = 0; /* end of FIFO, start at beginning */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync if (s->act_fifo_pos_read == s->act_fifo_pos_write) {
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync /* FIFO is empty */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync /* Set FIFO empty bit */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_EMPTY;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync /* Clear FIFO full bit */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_FULL;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync } else {
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync /* FIFO has some data (clear all FIFO bits) */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync }
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync } else {
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync ret = s->reg_ecp_base_plus_400h;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync }
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync break;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync case 1:
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync ret = s->reg_ecp_config_b;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync break;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync case 2:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ret = s->reg_ecp_ecr;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 3:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 4:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 5:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 6:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync case 7:
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync break;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync LogFlow(("parallel: read ecp addr=0x%02x val=0x%02x\n", addr, ret));
b6baf56a3d86bf6846cf312df344bbfe5b2fb01cvboxsync return ret;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
ae20b83f0c94402a3e3ac021c3d4e5f827e4905cvboxsync#endif
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync#ifdef IN_RING3
e5da5dbb49b995e6e7d20a79a6cac76307549b15vboxsyncstatic DECLCALLBACK(int) parallelNotifyInterrupt(PPDMIHOSTPARALLELPORT pInterface)
e5da5dbb49b995e6e7d20a79a6cac76307549b15vboxsync{
e5da5dbb49b995e6e7d20a79a6cac76307549b15vboxsync ParallelState *pThis = PDMIHOSTPARALLELPORT_2_PARALLELSTATE(pInterface);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCritSectEnter(&pThis->CritSect, VINF_SUCCESS);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync parallel_set_irq(pThis);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCritSectLeave(&pThis->CritSect);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return VINF_SUCCESS;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif /* IN_RING3 */
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/**
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Port I/O Handler for OUT operations.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @returns VBox status code.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pDevIns The device instance.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pvUser User argument.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param Port Port number used for the IN operation.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param u32 The value to output.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param cb The value size in bytes.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync RTIOPORT Port, uint32_t u32, unsigned cb)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = VINF_SUCCESS;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (cb == 1)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_HC_IOPORT_WRITE);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (rc == VINF_SUCCESS)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, u32));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = parallel_ioport_write (pThis, Port, u32);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCritSectLeave(&pThis->CritSect);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return rc;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync
76c5ade78ff18423f4a3aed5cf7fcc84b1c0933bvboxsync/**
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Port I/O Handler for IN operations.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @returns VBox status code.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pDevIns The device instance.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pvUser User argument.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param Port Port number used for the IN operation.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param u32 The value to output.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param cb The value size in bytes.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync RTIOPORT Port, uint32_t *pu32, unsigned cb)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = VINF_SUCCESS;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (cb == 1)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_HC_IOPORT_READ);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (rc == VINF_SUCCESS)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *pu32 = parallel_ioport_read (pThis, Port, &rc);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCritSectLeave(&pThis->CritSect);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
5a1e3fdfddd9fb23f043efc077dae781b9691c23vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = VERR_IOM_IOPORT_UNUSED;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return rc;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#if 0
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/**
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Port I/O Handler for OUT operations on ECP registers.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @returns VBox status code.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pDevIns The device instance.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pvUser User argument.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param Port Port number used for the IN operation.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param u32 The value to output.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param cb The value size in bytes.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync RTIOPORT Port, uint32_t u32, unsigned cb)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = VINF_SUCCESS;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (cb == 1)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_HC_IOPORT_WRITE);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (rc == VINF_SUCCESS)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log2(("%s: ecp port %#06x val %#04x\n", __FUNCTION__, Port, u32));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = parallel_ioport_write_ecp (pThis, Port, u32);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCritSectLeave(&pThis->CritSect);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return rc;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/**
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Port I/O Handler for IN operations on ECP registers.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @returns VBox status code.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pDevIns The device instance.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pvUser User argument.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param Port Port number used for the IN operation.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param u32 The value to output.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param cb The value size in bytes.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncPDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync RTIOPORT Port, uint32_t *pu32, unsigned cb)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc = VINF_SUCCESS;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (cb == 1)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_HC_IOPORT_READ);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (rc == VINF_SUCCESS)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *pu32 = parallel_ioport_read_ecp (pThis, Port, &rc);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log2(("%s: ecp port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PDMCritSectLeave(&pThis->CritSect);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync }
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync else
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = VERR_IOM_IOPORT_UNUSED;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return rc;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#endif
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#ifdef IN_RING3
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/**
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Saves a state of the serial port device.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @returns VBox status code.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pDevIns The device instance.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pSSMHandle The handle to save the state to.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsyncstatic DECLCALLBACK(int) parallelSaveExec(PPDMDEVINS pDevIns,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync PSSMHANDLE pSSMHandle)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync SSMR3PutU8(pSSMHandle, pThis->reg_data);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync SSMR3PutU8(pSSMHandle, pThis->reg_status);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync SSMR3PutU8(pSSMHandle, pThis->reg_control);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync SSMR3PutS32(pSSMHandle, pThis->irq);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync SSMR3PutU32(pSSMHandle, pThis->base);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return SSMR3PutU32(pSSMHandle, ~0); /* sanity/terminator */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync}
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/**
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Loads a saved serial port device state.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync *
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @returns VBox status code.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pDevIns The device instance.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * @param pSSMHandle The handle to the saved state.
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync * @param u32Version The data unit version number.
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsyncstatic DECLCALLBACK(int) parallelLoadExec(PPDMDEVINS pDevIns,
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync PSSMHANDLE pSSMHandle,
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync uint32_t u32Version)
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync{
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync int rc;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync uint32_t u32;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
60d6a38322f01d471dec22b5836e7e450d85c3b1vboxsync if (u32Version != PARALLEL_SAVED_STATE_VERSION)
60d6a38322f01d471dec22b5836e7e450d85c3b1vboxsync {
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync AssertLogRelMsgFailed(("u32Version=%d\n", u32Version));
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync }
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync SSMR3GetU8(pSSMHandle, &pThis->reg_data);
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync SSMR3GetU8(pSSMHandle, &pThis->reg_status);
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync SSMR3GetU8(pSSMHandle, &pThis->reg_control);
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync SSMR3GetS32(pSSMHandle, &pThis->irq);
60d6a38322f01d471dec22b5836e7e450d85c3b1vboxsync SSMR3GetU32(pSSMHandle, &pThis->base);
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync rc = SSMR3GetU32(pSSMHandle, &u32);
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync if (RT_FAILURE(rc))
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync return rc;
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync if (u32 != ~0U)
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync {
0005b7c81d5621b5c6e0b38ce3cbcabf7e883fd3vboxsync AssertLogRelMsgFailed(("u32=%#x expected ~0\n", u32));
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync }
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync /* not necessary... but it doesn't harm. */
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync pThis->pDevInsR3 = pDevIns;
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync return VINF_SUCCESS;
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync}
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync
7ae61147cce23a4efff53b9cdf35541be62a0cb8vboxsync
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync/**
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync * @copydoc FNPDMDEVRELOCATE
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync */
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsyncstatic DECLCALLBACK(void) parallelRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync{
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync pThis->pDevInsRC += offDelta;
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync}
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync/** @copyfrom PIBASE::pfnqueryInterface */
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsyncstatic DECLCALLBACK(void *) parallelQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync{
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync ParallelState *pThis = PDMIBASE_2_PARALLELSTATE(pInterface);
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync switch (enmInterface)
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync {
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync case PDMINTERFACE_BASE:
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync return &pThis->IBase;
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync case PDMINTERFACE_HOST_PARALLEL_PORT:
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync return &pThis->IHostParallelPort;
f4fa1b6b87341bfa5b45bacb7067beec05ca8f96vboxsync default:
d1a46338dc24f48013833a67f3e30b6d43600924vboxsync return NULL;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync }
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync}
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync/**
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync * Destruct a device instance.
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync *
2a2095adf36a009010d72cf36ffabb3c1261ad08vboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync * resources can be freed correctly.
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync *
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync * @returns VBox status.
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync * @param pDevIns The device instance data.
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync */
1f291c5acd315376ba984563c3165bc0edb53f49vboxsyncstatic DECLCALLBACK(int) parallelDestruct(PPDMDEVINS pDevIns)
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync{
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync
5508f48d486b92a88593b6dcc2252969927faed4vboxsync PDMR3CritSectDelete(&pThis->CritSect);
5508f48d486b92a88593b6dcc2252969927faed4vboxsync RTSemEventDestroy(pThis->ReceiveSem);
5508f48d486b92a88593b6dcc2252969927faed4vboxsync
5508f48d486b92a88593b6dcc2252969927faed4vboxsync return VINF_SUCCESS;
5508f48d486b92a88593b6dcc2252969927faed4vboxsync}
5508f48d486b92a88593b6dcc2252969927faed4vboxsync
5508f48d486b92a88593b6dcc2252969927faed4vboxsync
5508f48d486b92a88593b6dcc2252969927faed4vboxsync/**
5508f48d486b92a88593b6dcc2252969927faed4vboxsync * Construct a device instance for a VM.
5508f48d486b92a88593b6dcc2252969927faed4vboxsync *
5508f48d486b92a88593b6dcc2252969927faed4vboxsync * @returns VBox status.
5508f48d486b92a88593b6dcc2252969927faed4vboxsync * @param pDevIns The device instance data.
5508f48d486b92a88593b6dcc2252969927faed4vboxsync * If the registration structure is needed, pDevIns->pDevReg points to it.
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * @param iInstance Instance number. Use this to figure out which registers and such to use.
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * The device number is also found in pDevIns->iInstance, but since it's
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * likely to be freqently used PDM passes it as parameter.
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * of the device instance. It's also found in pDevIns->pCfgHandle, but like
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync * iInstance it's expected to be used a bit in this function.
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync */
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsyncstatic DECLCALLBACK(int) parallelConstruct(PPDMDEVINS pDevIns,
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync int iInstance,
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync PCFGMNODE pCfgHandle)
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync{
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync int rc;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState*);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Assert(iInstance < 4);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /*
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Init the data so parallelDestruct doesn't choke.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->pDevInsR3 = pDevIns;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->ReceiveSem = NIL_RTSEMEVENT;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* IBase */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->IBase.pfnQueryInterface = parallelQueryInterface;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
5508f48d486b92a88593b6dcc2252969927faed4vboxsync /* IHostParallelPort */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->IHostParallelPort.pfnNotifyInterrupt = parallelNotifyInterrupt;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* Init parallel state */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->reg_data = 0;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->reg_ecp_ecr = LPT_ECP_ECR_CHIPMODE_COMPAT | LPT_ECP_ECR_FIFO_EMPTY;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->act_fifo_pos_read = 0;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->act_fifo_pos_write = 0;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /*
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Validate and read the configuration.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0" "IOBase\0" "GCEnabled\0" "R0Enabled\0"))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync N_("Configuration error: Unknown config key"));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = CFGMR3QueryBoolDef(pCfgHandle, "GCEnabled", &pThis->fGCEnabled, true);
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync if (RT_FAILURE(rc))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync N_("Configuration error: Failed to get the \"GCEnabled\" value"));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &pThis->fR0Enabled, true);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_FAILURE(rc))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync N_("Configuration error: Failed to get the \"R0Enabled\" value"));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync uint8_t irq_lvl;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = CFGMR3QueryU8Def(pCfgHandle, "IRQ", &irq_lvl, 7);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_FAILURE(rc))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync N_("Configuration error: Failed to get the \"IRQ\" value"));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync uint16_t io_base;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = CFGMR3QueryU16Def(pCfgHandle, "IOBase", &io_base, 0x378);
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_FAILURE(rc))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync N_("Configuration error: Failed to get the \"IOBase\" value"));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync Log(("parallelConstruct instance %d iobase=%04x irq=%d\n", iInstance, io_base, irq_lvl));
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->irq = irq_lvl;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync pThis->base = io_base;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /*
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * Initialize critical section and event semaphore.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync * This must of course be done before attaching drivers or anything else which can call us back..
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync */
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync char szName[24];
b97d0f715f8fe39ceb7d4138427da4a0030ff65fvboxsync RTStrPrintf(szName, sizeof(szName), "Parallel#%d", iInstance);
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync if (RT_FAILURE(rc))
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync return rc;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync
e2fe5c2c7eeaf4282b1f3d185fc3f379276fae5dvboxsync rc = RTSemEventCreate(&pThis->ReceiveSem);
e2fe5c2c7eeaf4282b1f3d185fc3f379276fae5dvboxsync if (RT_FAILURE(rc))
e2fe5c2c7eeaf4282b1f3d185fc3f379276fae5dvboxsync return rc;
e2fe5c2c7eeaf4282b1f3d185fc3f379276fae5dvboxsync
e2fe5c2c7eeaf4282b1f3d185fc3f379276fae5dvboxsync /*
e2fe5c2c7eeaf4282b1f3d185fc3f379276fae5dvboxsync * Register the I/O ports and saved state.
1f291c5acd315376ba984563c3165bc0edb53f49vboxsync */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = PDMDevHlpIOPortRegister(pDevIns, io_base, 8, 0,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync parallelIOPortWrite, parallelIOPortRead,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync NULL, NULL, "PARALLEL");
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync if (RT_FAILURE(rc))
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync return rc;
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync#if 0
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync /* register ecp registers */
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync rc = PDMDevHlpIOPortRegister(pDevIns, io_base+0x400, 8, 0,
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync parallelIOPortWriteECP, parallelIOPortReadECP,
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync NULL, NULL, "PARALLEL ECP");
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync if (RT_FAILURE(rc))
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync return rc;
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync#endif
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync if (pThis->fGCEnabled)
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync {
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync rc = PDMDevHlpIOPortRegisterGC(pDevIns, io_base, 8, 0, "parallelIOPortWrite",
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync "parallelIOPortRead", NULL, NULL, "Parallel");
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync if (RT_FAILURE(rc))
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync return rc;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync#if 0
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync rc = PDMDevHlpIOPortRegisterGC(pDevIns, io_base+0x400, 8, 0, "parallelIOPortWriteECP",
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync "parallelIOPortReadECP", NULL, NULL, "Parallel Ecp");
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync if (RT_FAILURE(rc))
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync return rc;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync#endif
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync }
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync if (pThis->fR0Enabled)
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync {
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base, 8, 0, "parallelIOPortWrite",
ff62f2ecb95b5892be2edaa7d786d80727d64a2cvboxsync "parallelIOPortRead", NULL, NULL, "Parallel");
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync if (RT_FAILURE(rc))
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync return rc;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync#if 0
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base+0x400, 8, 0, "parallelIOPortWriteECP",
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync "parallelIOPortReadECP", NULL, NULL, "Parallel Ecp");
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync if (RT_FAILURE(rc))
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync return rc;
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync#endif
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync }
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync rc = PDMDevHlpSSMRegister(
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync pDevIns, /* pDevIns */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync pDevIns->pDevReg->szDeviceName, /* pszName */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync iInstance, /* u32Instance */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync PARALLEL_SAVED_STATE_VERSION, /* u32Version */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync sizeof (*pThis), /* cbGuess */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync NULL, /* pfnSavePrep */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync parallelSaveExec, /* pfnSaveExec */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync NULL, /* pfnSaveDone */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync NULL, /* pfnLoadPrep */
1f5edbfd0fc9c890d44edbf915ebc06e75e08943vboxsync parallelLoadExec, /* pfnLoadExec */
ede381e58d677545f69d56df0b26b1959d1b9fbfvboxsync NULL /* pfnLoadDone */
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync );
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync if (RT_FAILURE(rc))
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync return rc;
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync /*
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync * Attach the parallel port driver and get the interfaces.
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync * For now no run-time changes are supported.
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync */
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Parallel Host");
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync if (RT_SUCCESS(rc))
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync {
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync pThis->pDrvHostParallelConnector = (PDMIHOSTPARALLELCONNECTOR *)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase,
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync PDMINTERFACE_HOST_PARALLEL_CONNECTOR);
8b36c1115d96725cbbcbdb50bbe0a90993f7d5c1vboxsync if (!pThis->pDrvHostParallelConnector)
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync {
4338d1606b19c219ef8f200aae7558a8ea7cb796vboxsync AssertMsgFailed(("Configuration error: instance %d has no host parallel interface!\n", iInstance));
return VERR_PDM_MISSING_INTERFACE;
}
/** @todo provide read notification interface!!!! */
}
else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
{
pThis->pDrvBase = NULL;
pThis->pDrvHostParallelConnector = NULL;
LogRel(("Parallel%d: no unit\n", iInstance));
}
else
{
AssertMsgFailed(("Parallel%d: Failed to attach to host driver. rc=%Vrc\n", iInstance, rc));
return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
N_("Parallel device %d cannot attach to host driver"), iInstance);
}
/* Set compatibility mode */
pThis->pDrvHostParallelConnector->pfnSetMode(pThis->pDrvHostParallelConnector, PDM_PARALLEL_PORT_MODE_COMPAT);
/* Get status of control register */
pThis->pDrvHostParallelConnector->pfnReadControl(pThis->pDrvHostParallelConnector, &pThis->reg_control);
return VINF_SUCCESS;
}
/**
* The device registration structure.
*/
const PDMDEVREG g_DeviceParallelPort =
{
/* u32Version */
PDM_DEVREG_VERSION,
/* szDeviceName */
"parallel",
/* szGCMod */
"VBoxDDGC.gc",
/* szR0Mod */
"VBoxDDR0.r0",
/* pszDescription */
"Parallel Communication Port",
/* fFlags */
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0,
/* fClass */
PDM_DEVREG_CLASS_PARALLEL,
/* cMaxInstances */
1,
/* cbInstance */
sizeof(ParallelState),
/* pfnConstruct */
parallelConstruct,
/* pfnDestruct */
parallelDestruct,
/* pfnRelocate */
parallelRelocate,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnQueryInterface. */
NULL
};
#endif /* IN_RING3 */
#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */