c74832c7184337c330041742d88e6dacaa07b378vboxsync/* $Id$ */
c74832c7184337c330041742d88e6dacaa07b378vboxsync/** @file
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync * DevParallel - Parallel (Port) Device Emulation.
d192cc72774b02a0df2fdd46350d418236ac09aevboxsync *
d192cc72774b02a0df2fdd46350d418236ac09aevboxsync * Contributed by: Alexander Eichner
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync * Based on DevSerial.cpp
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
c74832c7184337c330041742d88e6dacaa07b378vboxsync *
c74832c7184337c330041742d88e6dacaa07b378vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c74832c7184337c330041742d88e6dacaa07b378vboxsync * available from http://www.virtualbox.org. This file is free software;
c74832c7184337c330041742d88e6dacaa07b378vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/*******************************************************************************
c74832c7184337c330041742d88e6dacaa07b378vboxsync* Header Files *
c74832c7184337c330041742d88e6dacaa07b378vboxsync*******************************************************************************/
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LOG_GROUP LOG_GROUP_DEV_PARALLEL
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdmdev.h>
c74832c7184337c330041742d88e6dacaa07b378vboxsync#include <iprt/assert.h>
c74832c7184337c330041742d88e6dacaa07b378vboxsync#include <iprt/uuid.h>
c74832c7184337c330041742d88e6dacaa07b378vboxsync#include <iprt/string.h>
c74832c7184337c330041742d88e6dacaa07b378vboxsync#include <iprt/semaphore.h>
c74832c7184337c330041742d88e6dacaa07b378vboxsync
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync#include "VBoxDD.h"
c74832c7184337c330041742d88e6dacaa07b378vboxsync
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync/*******************************************************************************
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync* Defined Constants And Macros *
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync*******************************************************************************/
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define PARALLEL_SAVED_STATE_VERSION 1
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/* defines for accessing the register bits */
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_BUSY 0x80
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_ACK 0x40
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_PAPER_OUT 0x20
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_SELECT_IN 0x10
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_ERROR 0x08
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_IRQ 0x04
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_STATUS_BIT1 0x02 /* reserved (only for completeness) */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_STATUS_EPP_TIMEOUT 0x01
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_BIT7 0x80 /* reserved (only for completeness) */
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_BIT6 0x40 /* reserved (only for completeness) */
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_ENABLE_BIDIRECT 0x20
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_ENABLE_IRQ_VIA_ACK 0x10
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_SELECT_PRINTER 0x08
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_RESET 0x04
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_AUTO_LINEFEED 0x02
c74832c7184337c330041742d88e6dacaa07b378vboxsync#define LPT_CONTROL_STROBE 0x01
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync/** mode defines for the extended control register */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_MASK 0xe0
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_GET_BITS(reg) ((reg) >> 5)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_SET_BITS(val) ((val) << 5)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_CONFIGURATION 0x07
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_FIFO_TEST 0x06
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_RESERVED 0x05
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_EPP 0x04
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_ECP_FIFO 0x03
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_PP_FIFO 0x02
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_BYTE 0x01
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_CHIPMODE_COMPAT 0x00
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync/** FIFO status bits in extended control register */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_FIFO_MASK 0x03
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_FIFO_SOME_DATA 0x00
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_FIFO_FULL 0x02
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_ECR_FIFO_EMPTY 0x01
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_CONFIGA_FIFO_WITDH_MASK 0x70
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_GET_BITS(reg) ((reg) >> 4)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_SET_BITS(val) ((val) << 4)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_16 0x00
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_32 0x20
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_8 0x10
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#define LPT_ECP_FIFO_DEPTH 2
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync/*******************************************************************************
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync* Structures and Typedefs *
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync*******************************************************************************/
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/**
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * Parallel device state.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync *
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements PDMIBASE
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements PDMIHOSTPARALLELPORT
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsynctypedef struct PARALLELPORT
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /** Pointer to the device instance - R3 Ptr */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PPDMDEVINSR3 pDevInsR3;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /** Pointer to the device instance - R0 Ptr */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PPDMDEVINSR0 pDevInsR0;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /** Pointer to the device instance - RC Ptr */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PPDMDEVINSRC pDevInsRC;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Alignment. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync RTRCPTR Alignment0;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /** LUN\#0: The base interface. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PDMIBASE IBase;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /** LUN\#0: The host device port interface. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PDMIHOSTPARALLELPORT IHostParallelPort;
c74832c7184337c330041742d88e6dacaa07b378vboxsync /** Pointer to the attached base driver. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync R3PTRTYPE(PPDMIBASE) pDrvBase;
c74832c7184337c330041742d88e6dacaa07b378vboxsync /** Pointer to the attached host device. */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync R3PTRTYPE(PPDMIHOSTPARALLELCONNECTOR) pDrvHostParallelConnector;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Flag whether the device has its RC component enabled. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync bool fGCEnabled;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Flag whether the device has its R0 component enabled. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync bool fR0Enabled;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Flag whether an EPP timeout occurred (error handling). */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync bool fEppTimeout;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Base I/O port of the parallel port. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync RTIOPORT IOBase;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** IRQ number assigned ot the parallel port. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync int iIrq;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Data register. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t regData;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Status register. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t regStatus;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** Control register. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t regControl;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** EPP address register. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t regEppAddr;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** EPP data register. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t regEppData;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync /** More alignment. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint32_t u32Alignment;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#if 0 /* Data for ECP implementation, currently unused. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t reg_ecp_ecr;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t reg_ecp_base_plus_400h; /* has different meanings */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync uint8_t reg_ecp_config_b;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync /** The ECP FIFO implementation*/
4fbca3751fe239da5934c23a783c3422618336e8vboxsync uint8_t ecp_fifo[LPT_ECP_FIFO_DEPTH];
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync uint8_t abAlignemnt[2];
4fbca3751fe239da5934c23a783c3422618336e8vboxsync int act_fifo_pos_write;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync int act_fifo_pos_read;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync} PARALLELPORT, *PPARALLELPORT;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync#ifndef VBOX_DEVICE_STRUCT_TESTCASE
c74832c7184337c330041742d88e6dacaa07b378vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#define PDMIHOSTPARALLELPORT_2_PARALLELPORT(pInstance) ( (PARALLELPORT *)((uintptr_t)(pInterface) - RT_OFFSETOF(PARALLELPORT, IHostParallelPort)) )
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#define PDMIHOSTDEVICEPORT_2_PARALLELPORT(pInstance) ( (PARALLELPORT *)((uintptr_t)(pInterface) - RT_OFFSETOF(PARALLELPORT, IHostDevicePort)) )
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#define PDMIBASE_2_PARALLELPORT(pInstance) ( (PARALLELPORT *)((uintptr_t)(pInterface) - RT_OFFSETOF(PARALLELPORT, IBase)) )
c74832c7184337c330041742d88e6dacaa07b378vboxsync
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync/*******************************************************************************
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync* Internal Functions *
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync*******************************************************************************/
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_BEGIN
c74832c7184337c330041742d88e6dacaa07b378vboxsyncPDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
c74832c7184337c330041742d88e6dacaa07b378vboxsyncPDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#if 0
4fbca3751fe239da5934c23a783c3422618336e8vboxsyncPDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
4fbca3751fe239da5934c23a783c3422618336e8vboxsyncPDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#endif
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_END
c74832c7184337c330041742d88e6dacaa07b378vboxsync
a6e58d30b4d856cf924fda15cd743fed386fff93vboxsync
509c0d9c2c05b40f3f07f79e44c06c9395c1b293vboxsync#ifdef IN_RING3
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic void parallelR3IrqSet(PARALLELPORT *pThis)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync if (pThis->regControl & LPT_CONTROL_ENABLE_IRQ_VIA_ACK)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync {
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync LogFlowFunc(("%d 1\n", pThis->iIrq));
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->iIrq, 1);
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic void parallelR3IrqClear(PARALLELPORT *pThis)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync LogFlowFunc(("%d 0\n", pThis->iIrq));
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->iIrq, 0);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync}
509c0d9c2c05b40f3f07f79e44c06c9395c1b293vboxsync#endif
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#if 0
4fbca3751fe239da5934c23a783c3422618336e8vboxsyncstatic int parallel_ioport_write_ecp(void *opaque, uint32_t addr, uint32_t val)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *s = (PARALLELPORT *)opaque;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync unsigned char ch;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync addr &= 7;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync LogFlow(("parallel: write ecp addr=0x%02x val=0x%02x\n", addr, val));
4fbca3751fe239da5934c23a783c3422618336e8vboxsync ch = val;
b93e90414950e3ac532b5198c56676696b56fed6vboxsync switch (addr) {
4fbca3751fe239da5934c23a783c3422618336e8vboxsync default:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 0:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->ecp_fifo[s->act_fifo_pos_write] = ch;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->act_fifo_pos_write++;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (s->act_fifo_pos_write < LPT_ECP_FIFO_DEPTH) {
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* FIFO has some data (clear both FIFO bits) */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync } else {
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* FIFO is full */
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Clear FIFO empty bit */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_EMPTY;
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Set FIFO full bit */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_FULL;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->act_fifo_pos_write = 0;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync } else {
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_base_plus_400h = ch;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 1:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_config_b = ch;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 2:
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* If we change the mode clear FIFO */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if ((ch & LPT_ECP_ECR_CHIPMODE_MASK) != (s->reg_ecp_ecr & LPT_ECP_ECR_CHIPMODE_MASK)) {
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* reset the fifo */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->act_fifo_pos_write = 0;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->act_fifo_pos_read = 0;
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Set FIFO empty bit */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_EMPTY;
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Clear FIFO full bit */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_FULL;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Set new mode */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_CHIPMODE_SET_BITS(LPT_ECP_ECR_CHIPMODE_GET_BITS(ch));
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 3:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 4:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 5:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 6:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 7:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync return VINF_SUCCESS;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsyncstatic uint32_t parallel_ioport_read_ecp(void *opaque, uint32_t addr, int *pRC)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *s = (PARALLELPORT *)opaque;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync uint32_t ret = ~0U;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync *pRC = VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync addr &= 7;
b93e90414950e3ac532b5198c56676696b56fed6vboxsync switch (addr) {
4fbca3751fe239da5934c23a783c3422618336e8vboxsync default:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 0:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
4fbca3751fe239da5934c23a783c3422618336e8vboxsync ret = s->ecp_fifo[s->act_fifo_pos_read];
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->act_fifo_pos_read++;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (s->act_fifo_pos_read == LPT_ECP_FIFO_DEPTH)
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync s->act_fifo_pos_read = 0; /* end of FIFO, start at beginning */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (s->act_fifo_pos_read == s->act_fifo_pos_write) {
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* FIFO is empty */
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Set FIFO empty bit */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_EMPTY;
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Clear FIFO full bit */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_FULL;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync } else {
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* FIFO has some data (clear all FIFO bits) */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync } else {
4fbca3751fe239da5934c23a783c3422618336e8vboxsync ret = s->reg_ecp_base_plus_400h;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 1:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync ret = s->reg_ecp_config_b;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 2:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync ret = s->reg_ecp_ecr;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 3:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 4:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 5:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 6:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync case 7:
4fbca3751fe239da5934c23a783c3422618336e8vboxsync break;
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync LogFlow(("parallel: read ecp addr=0x%02x val=0x%02x\n", addr, ret));
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return ret;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync}
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#endif
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#ifdef IN_RING3
b93e90414950e3ac532b5198c56676696b56fed6vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @interface_methods_impl{PDMIHOSTPARALLELPORT,pfnNotifyInterrupt}
b93e90414950e3ac532b5198c56676696b56fed6vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(int) parallelR3NotifyInterrupt(PPDMIHOSTPARALLELPORT pInterface)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMIHOSTPARALLELPORT_2_PARALLELPORT(pInterface);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync PDMCritSectEnter(pThis->pDevInsR3->pCritSectRoR3, VINF_SUCCESS);
b93e90414950e3ac532b5198c56676696b56fed6vboxsync parallelR3IrqSet(pThis);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync PDMCritSectLeave(pThis->pDevInsR3->pCritSectRoR3);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync#endif /* IN_RING3 */
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNIOMIOPORTOUT}
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncPDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PPARALLELPORT);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync int rc = VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync if (cb == 1)
c74832c7184337c330041742d88e6dacaa07b378vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync uint8_t u8 = u32;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, u32));
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Port &= 7;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync switch (Port)
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 0:
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync NOREF(u8);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_WRITE;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync pThis->regData = u8;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync LogFlowFunc(("Set data lines 0x%X\n", u8));
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnWrite(pThis->pDrvHostParallelConnector, &u8, 1, PDM_PARALLEL_PORT_MODE_SPP);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 1:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 2:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync /* Set the reserved bits to one */
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync u8 |= (LPT_CONTROL_BIT6 | LPT_CONTROL_BIT7);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (u8 != pThis->regControl)
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync return VINF_IOM_R3_IOPORT_WRITE;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync /* Set data direction. */
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (u8 & LPT_CONTROL_ENABLE_BIDIRECT)
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnSetPortDirection(pThis->pDrvHostParallelConnector, false /* fForward */);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnSetPortDirection(pThis->pDrvHostParallelConnector, true /* fForward */);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync u8 &= ~LPT_CONTROL_ENABLE_BIDIRECT; /* Clear bit. */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnWriteControl(pThis->pDrvHostParallelConnector, u8);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync pThis->regControl = u8;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 3:
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync NOREF(u8);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_WRITE;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync pThis->regEppAddr = u8;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync LogFlowFunc(("Write EPP address 0x%X\n", u8));
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnWrite(pThis->pDrvHostParallelConnector, &u8, 1, PDM_PARALLEL_PORT_MODE_EPP_ADDR);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 4:
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync NOREF(u8);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_WRITE;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync pThis->regEppData = u8;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync LogFlowFunc(("Write EPP data 0x%X\n", u8));
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnWrite(pThis->pDrvHostParallelConnector, &u8, 1, PDM_PARALLEL_PORT_MODE_EPP_DATA);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 5:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 6:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 7:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync default:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync else
c74832c7184337c330041742d88e6dacaa07b378vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync return rc;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNIOMIOPORTIN}
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncPDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync int rc = VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync if (cb == 1)
c74832c7184337c330041742d88e6dacaa07b378vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Port &= 7;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync switch (Port)
c74832c7184337c330041742d88e6dacaa07b378vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 0:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (!(pThis->regControl & LPT_CONTROL_ENABLE_BIDIRECT))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = pThis->regData;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
648b0a0e189323afe4d836f1848f82c7dded0e58vboxsync rc = VINF_IOM_R3_IOPORT_READ;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnRead(pThis->pDrvHostParallelConnector, &pThis->regData,
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync 1, PDM_PARALLEL_PORT_MODE_SPP);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Log(("Read data lines 0x%X\n", pThis->regData));
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync AssertRC(rc);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync }
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = pThis->regData;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 1:
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_READ;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnReadStatus(pThis->pDrvHostParallelConnector, &pThis->regStatus);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = pThis->regStatus;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync parallelR3IrqClear(pThis);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 2:
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_READ;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnReadControl(pThis->pDrvHostParallelConnector, &pThis->regControl);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync pThis->regControl |= LPT_CONTROL_BIT6 | LPT_CONTROL_BIT7;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = pThis->regControl;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 3:
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_READ;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnRead(pThis->pDrvHostParallelConnector, &pThis->regEppAddr,
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync 1, PDM_PARALLEL_PORT_MODE_EPP_ADDR);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Log(("Read EPP address 0x%X\n", pThis->regEppAddr));
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = pThis->regEppAddr;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 4:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync#ifndef IN_RING3
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = VINF_IOM_R3_IOPORT_READ;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync#else
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync if (RT_LIKELY(pThis->pDrvHostParallelConnector))
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = pThis->pDrvHostParallelConnector->pfnRead(pThis->pDrvHostParallelConnector, &pThis->regEppData,
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync 1, PDM_PARALLEL_PORT_MODE_EPP_DATA);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Log(("Read EPP data 0x%X\n", pThis->regEppData));
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync AssertRC(rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync }
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = pThis->regEppData;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync#endif
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 5:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 6:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync case 7:
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync break;
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync else
c74832c7184337c330041742d88e6dacaa07b378vboxsync rc = VERR_IOM_IOPORT_UNUSED;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync return rc;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#if 0
4fbca3751fe239da5934c23a783c3422618336e8vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNIOMIOPORTOUT, ECP registers.}
4fbca3751fe239da5934c23a783c3422618336e8vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncPDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync int rc = VINF_SUCCESS;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (cb == 1)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Log2(("%s: ecp port %#06x val %#04x\n", __FUNCTION__, Port, u32));
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync rc = parallel_ioport_write_ecp (pThis, Port, u32);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync else
4fbca3751fe239da5934c23a783c3422618336e8vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync}
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNIOMIOPORTOUT, ECP registers.}
4fbca3751fe239da5934c23a783c3422618336e8vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncPDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
b93e90414950e3ac532b5198c56676696b56fed6vboxsync int rc = VINF_SUCCESS;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync if (cb == 1)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync {
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync *pu32 = parallel_ioport_read_ecp (pThis, Port, &rc);
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync Log2(("%s: ecp port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
4fbca3751fe239da5934c23a783c3422618336e8vboxsync else
4fbca3751fe239da5934c23a783c3422618336e8vboxsync rc = VERR_IOM_IOPORT_UNUSED;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync}
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#endif
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync#ifdef IN_RING3
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNSSMDEVLIVEEXEC}
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(int) parallelR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3PutS32(pSSM, pThis->iIrq);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3PutU32(pSSM, pThis->IOBase);
e7925b345f17e5bd9f0c1cf3540b7d8573ec274fvboxsync SSMR3PutU32(pSSM, ~0); /* sanity/terminator */
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync return VINF_SSM_DONT_CALL_AGAIN;
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync}
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNSSMDEVSAVEEXEC}
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(int) parallelR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3PutU8(pSSM, pThis->regData);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3PutU8(pSSM, pThis->regStatus);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3PutU8(pSSM, pThis->regControl);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync parallelR3LiveExec(pDevIns, pSSM, 0);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync return VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @callback_method_impl{FNSSMDEVLOADEXEC}
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(int) parallelR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b5d837811bf21f30a31748bbbcb28ee562bb2355vboxsync AssertMsgReturn(uVersion == PARALLEL_SAVED_STATE_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
6dea6d87ed79bc0994d314fed1c90431091e8820vboxsync Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync if (uPass == SSM_PASS_FINAL)
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync {
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3GetU8(pSSM, &pThis->regData);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3GetU8(pSSM, &pThis->regStatus);
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync SSMR3GetU8(pSSM, &pThis->regControl);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync /* the config */
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync int32_t iIrq;
e7925b345f17e5bd9f0c1cf3540b7d8573ec274fvboxsync SSMR3GetS32(pSSM, &iIrq);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync uint32_t uIoBase;
e7925b345f17e5bd9f0c1cf3540b7d8573ec274fvboxsync SSMR3GetU32(pSSM, &uIoBase);
b5d837811bf21f30a31748bbbcb28ee562bb2355vboxsync uint32_t u32;
e7925b345f17e5bd9f0c1cf3540b7d8573ec274fvboxsync int rc = SSMR3GetU32(pSSM, &u32);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
c74832c7184337c330041742d88e6dacaa07b378vboxsync return rc;
b5d837811bf21f30a31748bbbcb28ee562bb2355vboxsync AssertMsgReturn(u32 == ~0U, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync if (pThis->iIrq != iIrq)
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("IRQ changed: config=%#x state=%#x"), pThis->iIrq, iIrq);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync if (pThis->IOBase != uIoBase)
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("IOBase changed: config=%#x state=%#x"), pThis->IOBase, uIoBase);
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /* not necessary... but it doesn't harm. */
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->pDevInsR3 = pDevIns;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
c74832c7184337c330041742d88e6dacaa07b378vboxsync return VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/**
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(void *) parallelR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMIBASE_2_PARALLELPORT(pInterface);
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTPARALLELPORT, &pThis->IHostParallelPort);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync return NULL;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
b93e90414950e3ac532b5198c56676696b56fed6vboxsync * @copydoc FNPDMDEVRELOCATE
b93e90414950e3ac532b5198c56676696b56fed6vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(void) parallelR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
b93e90414950e3ac532b5198c56676696b56fed6vboxsync{
b93e90414950e3ac532b5198c56676696b56fed6vboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT *);
b93e90414950e3ac532b5198c56676696b56fed6vboxsync pThis->pDevInsRC += offDelta;
b93e90414950e3ac532b5198c56676696b56fed6vboxsync}
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
b93e90414950e3ac532b5198c56676696b56fed6vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
cad8876b46f9e366c4a1007a40c27ca1df078950vboxsync * @interface_method_impl{PDMDEVREG,pfnConstruct}
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
b93e90414950e3ac532b5198c56676696b56fed6vboxsyncstatic DECLCALLBACK(int) parallelR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
c74832c7184337c330041742d88e6dacaa07b378vboxsync int rc;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PARALLELPORT*);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync Assert(iInstance < 4);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync /*
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync * Init the data.
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->pDevInsR3 = pDevIns;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* IBase */
b93e90414950e3ac532b5198c56676696b56fed6vboxsync pThis->IBase.pfnQueryInterface = parallelR3QueryInterface;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync /* IHostParallelPort */
b93e90414950e3ac532b5198c56676696b56fed6vboxsync pThis->IHostParallelPort.pfnNotifyInterrupt = parallelR3NotifyInterrupt;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /* Init parallel state */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync pThis->regData = 0;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#if 0 /* ECP implementation not complete. */
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->reg_ecp_ecr = LPT_ECP_ECR_CHIPMODE_COMPAT | LPT_ECP_ECR_FIFO_EMPTY;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->act_fifo_pos_read = 0;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync pThis->act_fifo_pos_write = 0;
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync#endif
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync /*
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync * Validate and read the configuration.
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync if (!CFGMR3AreValuesValid(pCfg, "IRQ\0" "IOBase\0" "GCEnabled\0" "R0Enabled\0"))
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync N_("Configuration error: Unknown config key"));
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &pThis->fGCEnabled, false);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync N_("Configuration error: Failed to get the \"GCEnabled\" value"));
c74832c7184337c330041742d88e6dacaa07b378vboxsync
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, false);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync if (RT_FAILURE(rc))
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync N_("Configuration error: Failed to get the \"R0Enabled\" value"));
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = CFGMR3QueryS32Def(pCfg, "IRQ", &pThis->iIrq, 7);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
4fbca3751fe239da5934c23a783c3422618336e8vboxsync N_("Configuration error: Failed to get the \"IRQ\" value"));
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = CFGMR3QueryU16Def(pCfg, "IOBase", &pThis->IOBase, 0x378);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
4fbca3751fe239da5934c23a783c3422618336e8vboxsync N_("Configuration error: Failed to get the \"IOBase\" value"));
c74832c7184337c330041742d88e6dacaa07b378vboxsync
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /*
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync * Register the I/O ports and saved state.
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = PDMDevHlpIOPortRegister(pDevIns, pThis->IOBase, 8, 0,
c74832c7184337c330041742d88e6dacaa07b378vboxsync parallelIOPortWrite, parallelIOPortRead,
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync NULL, NULL, "Parallel");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
c74832c7184337c330041742d88e6dacaa07b378vboxsync return rc;
c74832c7184337c330041742d88e6dacaa07b378vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#if 0
4fbca3751fe239da5934c23a783c3422618336e8vboxsync /* register ecp registers */
4fbca3751fe239da5934c23a783c3422618336e8vboxsync rc = PDMDevHlpIOPortRegister(pDevIns, io_base+0x400, 8, 0,
4fbca3751fe239da5934c23a783c3422618336e8vboxsync parallelIOPortWriteECP, parallelIOPortReadECP,
4fbca3751fe239da5934c23a783c3422618336e8vboxsync NULL, NULL, "PARALLEL ECP");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#endif
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (pThis->fGCEnabled)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync {
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->IOBase, 8, 0, "parallelIOPortWrite",
cacef7e2fcfb6f833efdb3d4d347aafe97ee8f6cvboxsync "parallelIOPortRead", NULL, NULL, "Parallel");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#if 0
4fbca3751fe239da5934c23a783c3422618336e8vboxsync rc = PDMDevHlpIOPortRegisterGC(pDevIns, io_base+0x400, 8, 0, "parallelIOPortWriteECP",
cacef7e2fcfb6f833efdb3d4d347aafe97ee8f6cvboxsync "parallelIOPortReadECP", NULL, NULL, "Parallel Ecp");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#endif
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (pThis->fR0Enabled)
4fbca3751fe239da5934c23a783c3422618336e8vboxsync {
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->IOBase, 8, 0, "parallelIOPortWrite",
cacef7e2fcfb6f833efdb3d4d347aafe97ee8f6cvboxsync "parallelIOPortRead", NULL, NULL, "Parallel");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#if 0
4fbca3751fe239da5934c23a783c3422618336e8vboxsync rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base+0x400, 8, 0, "parallelIOPortWriteECP",
cacef7e2fcfb6f833efdb3d4d347aafe97ee8f6cvboxsync "parallelIOPortReadECP", NULL, NULL, "Parallel Ecp");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_FAILURE(rc))
4fbca3751fe239da5934c23a783c3422618336e8vboxsync return rc;
4fbca3751fe239da5934c23a783c3422618336e8vboxsync#endif
4fbca3751fe239da5934c23a783c3422618336e8vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync
6b98f92a0c2c5dd90d8496ee553e5763c4debd49vboxsync rc = PDMDevHlpSSMRegister3(pDevIns, PARALLEL_SAVED_STATE_VERSION, sizeof(*pThis),
b93e90414950e3ac532b5198c56676696b56fed6vboxsync parallelR3LiveExec, parallelR3SaveExec, parallelR3LoadExec);
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync if (RT_FAILURE(rc))
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync return rc;
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync /*
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync * Attach the parallel port driver and get the interfaces.
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync * For now no run-time changes are supported.
120ee2736ed70b5ce8b0b4dd73cc4f8b4b9416c1vboxsync */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Parallel Host");
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (RT_SUCCESS(rc))
c74832c7184337c330041742d88e6dacaa07b378vboxsync {
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync pThis->pDrvHostParallelConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIHOSTPARALLELCONNECTOR);
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync AssertMsgReturn(pThis->pDrvHostParallelConnector,
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync ("Configuration error: instance %d has no host parallel interface!\n", iInstance),
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync VERR_PDM_MISSING_INTERFACE);
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
c74832c7184337c330041742d88e6dacaa07b378vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pThis->pDrvBase = NULL;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pThis->pDrvHostParallelConnector = NULL;
c74832c7184337c330041742d88e6dacaa07b378vboxsync LogRel(("Parallel%d: no unit\n", iInstance));
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync else
c74832c7184337c330041742d88e6dacaa07b378vboxsync {
fe813b3594039ba864493438e78ee0e7132bc445vboxsync AssertMsgFailed(("Parallel%d: Failed to attach to host driver. rc=%Rrc\n", iInstance, rc));
c74832c7184337c330041742d88e6dacaa07b378vboxsync return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
a40c05ca69e15a5efdd0796ef52e26ec0b1bc4d2vboxsync N_("Parallel device %d cannot attach to host driver"), iInstance);
c74832c7184337c330041742d88e6dacaa07b378vboxsync }
c74832c7184337c330041742d88e6dacaa07b378vboxsync
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Set compatibility mode */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync //pThis->pDrvHostParallelConnector->pfnSetMode(pThis->pDrvHostParallelConnector, PDM_PARALLEL_PORT_MODE_COMPAT);
6f8a1ec7a08590986f176ea072ad499630fe5b6evboxsync /* Get status of control register */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync pThis->pDrvHostParallelConnector->pfnReadControl(pThis->pDrvHostParallelConnector, &pThis->regControl);
4fbca3751fe239da5934c23a783c3422618336e8vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync return VINF_SUCCESS;
c74832c7184337c330041742d88e6dacaa07b378vboxsync}
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync/**
c74832c7184337c330041742d88e6dacaa07b378vboxsync * The device registration structure.
c74832c7184337c330041742d88e6dacaa07b378vboxsync */
c74832c7184337c330041742d88e6dacaa07b378vboxsyncconst PDMDEVREG g_DeviceParallelPort =
c74832c7184337c330041742d88e6dacaa07b378vboxsync{
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* u32Version */
c74832c7184337c330041742d88e6dacaa07b378vboxsync PDM_DEVREG_VERSION,
2c8ee291fb75c4a6f05df160f5d67f4e9ef1cabcvboxsync /* szName */
c74832c7184337c330041742d88e6dacaa07b378vboxsync "parallel",
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync /* szRCMod */
c74832c7184337c330041742d88e6dacaa07b378vboxsync "VBoxDDGC.gc",
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* szR0Mod */
c74832c7184337c330041742d88e6dacaa07b378vboxsync "VBoxDDR0.r0",
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pszDescription */
c74832c7184337c330041742d88e6dacaa07b378vboxsync "Parallel Communication Port",
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* fFlags */
3cf2cf6eea0401233eece976db8cf31909f1f955vboxsync PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* fClass */
c74832c7184337c330041742d88e6dacaa07b378vboxsync PDM_DEVREG_CLASS_PARALLEL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* cMaxInstances */
c74832c7184337c330041742d88e6dacaa07b378vboxsync 1,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* cbInstance */
7ed5f07f9d3ccc156a9331c304b36bb9fe4ebd4cvboxsync sizeof(PARALLELPORT),
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnConstruct */
b93e90414950e3ac532b5198c56676696b56fed6vboxsync parallelR3Construct,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnDestruct */
2baebf3c405f63a7583b6331b0f2802dba7f0529vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnRelocate */
b93e90414950e3ac532b5198c56676696b56fed6vboxsync parallelR3Relocate,
24ca3d27f14cf8a03b8448f6d0898110e915d46avboxsync /* pfnMemSetup */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnPowerOn */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnReset */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnSuspend */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnResume */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnAttach */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnDetach */
c74832c7184337c330041742d88e6dacaa07b378vboxsync NULL,
c74832c7184337c330041742d88e6dacaa07b378vboxsync /* pfnQueryInterface. */
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync NULL,
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync /* pfnInitComplete */
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync NULL,
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync /* pfnPowerOff */
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync NULL,
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync /* pfnSoftReset */
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync NULL,
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync /* u32VersionEnd */
f01175bdcb5e36a1a89fca88f45d7ee7fb034ed6vboxsync PDM_DEVREG_VERSION
c74832c7184337c330041742d88e6dacaa07b378vboxsync};
c74832c7184337c330041742d88e6dacaa07b378vboxsync#endif /* IN_RING3 */
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync
c74832c7184337c330041742d88e6dacaa07b378vboxsync#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */