DevParallel.cpp revision f5e53763b0a581b0299e98028c6c52192eb06785
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * DevParallel - Parallel (Port) Device Emulation.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Contributed by: Alexander Eichner
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Copyright (C) 2006-2007 Oracle Corporation
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * available from http://www.virtualbox.org. This file is free software;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * you can redistribute it and/or modify it under the terms of the GNU
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * General Public License (GPL) as published by the Free Software
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Header Files *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Defined Constants And Macros *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/* defines for accessing the register bits */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_STATUS_BIT1 0x02 /* reserved (only for completeness) */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_CONTROL_BIT7 0x80 /* reserved (only for completeness) */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_CONTROL_BIT6 0x40 /* reserved (only for completeness) */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** mode defines for the extended control register */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_ECP_ECR_CHIPMODE_GET_BITS(reg) ((reg) >> 5)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_ECP_ECR_CHIPMODE_SET_BITS(val) ((val) << 5)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** FIFO status bits in extended control register */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_GET_BITS(reg) ((reg) >> 4)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define LPT_ECP_CONFIGA_FIFO_WIDTH_SET_BITS(val) ((val) << 4)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Structures and Typedefs *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * Parallel device state.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @implements PDMIBASE
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @implements PDMIHOSTPARALLELPORT
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Access critical section. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the device instance - R3 Ptr */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the device instance - R0 Ptr */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the device instance - RC Ptr */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** LUN\#0: The base interface. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** LUN\#0: The host device port interface. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the attached base driver. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Pointer to the attached host device. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync R3PTRTYPE(PPDMIHOSTPARALLELCONNECTOR) pDrvHostParallelConnector;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** Unused event semaphore... */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync uint8_t reg_ecp_base_plus_400h; /* has different meanings */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** The ECP FIFO implementation*/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define PDMIHOSTPARALLELPORT_2_PARALLELSTATE(pInstance) ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostParallelPort)) )
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define PDMIHOSTDEVICEPORT_2_PARALLELSTATE(pInstance) ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostDevicePort)) )
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define PDMIBASE_2_PARALLELSTATE(pInstance) ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IBase)) )
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Internal Functions *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncPDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncPDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncPDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncPDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (s->reg_control & LPT_CONTROL_ENABLE_IRQ_VIA_ACK)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 1);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 0);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic int parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync unsigned char ch;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync LogFlow(("parallel: write addr=0x%02x val=0x%02x\n", addr, val));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = s->pDrvHostParallelConnector->pfnWrite(s->pDrvHostParallelConnector, &ch, &cbWrite);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Set the reserved bits to one */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = s->pDrvHostParallelConnector->pfnWriteControl(s->pDrvHostParallelConnector, ch);
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic uint32_t parallel_ioport_read(void *opaque, uint32_t addr, int *pRC)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (!(s->reg_control & LPT_CONTROL_ENABLE_BIDIRECT))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = s->pDrvHostParallelConnector->pfnRead(s->pDrvHostParallelConnector, &s->reg_data, &cbRead);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync Log(("parallel_io_port_read: read 0x%X\n", s->reg_data));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = s->pDrvHostParallelConnector->pfnReadStatus(s->pDrvHostParallelConnector, &s->reg_status);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync LogFlow(("parallel: read addr=0x%02x val=0x%02x\n", addr, ret));
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic int parallel_ioport_write_ecp(void *opaque, uint32_t addr, uint32_t val)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync unsigned char ch;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync LogFlow(("parallel: write ecp addr=0x%02x val=0x%02x\n", addr, val));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* FIFO has some data (clear both FIFO bits) */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* FIFO is full */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Clear FIFO empty bit */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Set FIFO full bit */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* If we change the mode clear FIFO */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if ((ch & LPT_ECP_ECR_CHIPMODE_MASK) != (s->reg_ecp_ecr & LPT_ECP_ECR_CHIPMODE_MASK)) {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* reset the fifo */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Set FIFO empty bit */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Clear FIFO full bit */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Set new mode */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync s->reg_ecp_ecr |= LPT_ECP_ECR_CHIPMODE_SET_BITS(LPT_ECP_ECR_CHIPMODE_GET_BITS(ch));
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic uint32_t parallel_ioport_read_ecp(void *opaque, uint32_t addr, int *pRC)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync s->act_fifo_pos_read = 0; /* end of FIFO, start at beginning */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (s->act_fifo_pos_read == s->act_fifo_pos_write) {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* FIFO is empty */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Set FIFO empty bit */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* Clear FIFO full bit */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /* FIFO has some data (clear all FIFO bits) */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync LogFlow(("parallel: read ecp addr=0x%02x val=0x%02x\n", addr, ret));
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic DECLCALLBACK(int) parallelNotifyInterrupt(PPDMIHOSTPARALLELPORT pInterface)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync ParallelState *pThis = PDMIHOSTPARALLELPORT_2_PARALLELSTATE(pInterface);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#endif /* IN_RING3 */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Port I/O Handler for OUT operations.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @returns VBox status code.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pDevIns The device instance.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pvUser User argument.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param Port Port number used for the IN operation.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param u32 The value to output.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param cb The value size in bytes.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncPDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_HC_IOPORT_WRITE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, u32));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Port I/O Handler for IN operations.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @returns VBox status code.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pDevIns The device instance.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pvUser User argument.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param Port Port number used for the IN operation.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pu32 Where to return the read value.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param cb The value size in bytes.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncPDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser,
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync ParallelState *pThis = PDMINS_2_DATA(pDevIns, ParallelState *);
return rc;
return rc;
return rc;
#ifdef IN_RING3
return VINF_SSM_DONT_CALL_AGAIN;
return VINF_SUCCESS;
AssertMsgReturn(uVersion == PARALLEL_SAVED_STATE_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
return rc;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("IRQ changed: config=%#x state=%#x"), pThis->irq, iIrq);
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("IOBase changed: config=%#x state=%#x"), pThis->base, uIoBase);
return VINF_SUCCESS;
return NULL;
return VINF_SUCCESS;
int iInstance,
int rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
pThis->pDrvHostParallelConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIHOSTPARALLELCONNECTOR);
pThis->pDrvHostParallelConnector->pfnSetMode(pThis->pDrvHostParallelConnector, PDM_PARALLEL_PORT_MODE_COMPAT);
pThis->pDrvHostParallelConnector->pfnReadControl(pThis->pDrvHostParallelConnector, &pThis->reg_control);
return VINF_SUCCESS;
sizeof(ParallelState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,