VirtualBox

Changeset 6222 in vbox for trunk


Ignore:
Timestamp:
Dec 30, 2007 5:06:27 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
27047
Message:

Continue work on the parallel port device:

  1. Removed the host device interface and replaced it with a parallel port specific one
  2. Report interrupts to the device
  3. Added code for ECP (disabled for now)
  4. Added an entry in the ACPI tables to make parallel port detection on Windows guests work
Location:
trunk
Files:
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pdmifs.h

    r6156 r6222  
    145145    PDMINTERFACE_VUSB_DEVICE,
    146146
    147     /** PDMIHOSTDEVICEPORT      - The Host Device port interface.       (Down)   Coupled with PDMINTERFACE_HOST_DEVICE_CONNECTOR. */
    148     PDMINTERFACE_HOST_DEVICE_PORT,
    149     /** PDMIHOSTDEVICECONNECTOR - The Host device connector interface   (Up)     Coupled with PDMINTERFACE_HOST_DEVICE_PORT. */
    150     PDMINTERFACE_HOST_DEVICE_CONNECTOR,
     147    /** PDMIHOSTPARALLELPORT      - The Host Parallel port interface.     (Down)   Coupled with PDMINTERFACE_HOST_PARALLEL_CONNECTOR. */
     148    PDMINTERFACE_HOST_PARALLEL_PORT,
     149    /** PDMIHOSTPARALLELCONNECTOR - The Host Parallel connector interface (Up)     Coupled with PDMINTERFACE_HOST_PARALLEL_PORT. */
     150    PDMINTERFACE_HOST_PARALLEL_CONNECTOR,
    151151
    152152    /** Maximum interface number. */
     
    16601660
    16611661
    1662 /** Pointer to a host device port interface. */
    1663 typedef struct PDMIHOSTDEVICEPORT *PPDMIHOSTDEVICEPORT;
    1664 /**
    1665  * Char port interface.
    1666  * Pair with PDMIHOSTDEVICECONNECTOR.
    1667  */
    1668 typedef struct PDMIHOSTDEVICEPORT
     1662/** Mode of the parallel port */
     1663typedef enum PDMPARALLELPORTMODE
     1664{
     1665    PDM_PARALLEL_PORT_MODE_COMPAT,
     1666    PDM_PARALLEL_PORT_MODE_EPP,
     1667    PDM_PARALLEL_PORT_MODE_ECP
     1668} PDMPARALLELPORTMODE;
     1669 
     1670/** Pointer to a host parallel port interface. */
     1671typedef struct PDMIHOSTPARALLELPORT *PPDMIHOSTPARALLELPORT;
     1672
     1673/**
     1674 * Host parallel port interface.
     1675 * Pair with PDMIHOSTPARALLELCONNECTOR.
     1676 */
     1677typedef struct PDMIHOSTPARALLELPORT
    16691678{
    16701679    /**
     
    16771686     * @thread  Any thread.
    16781687     */
    1679     DECLR3CALLBACKMEMBER(int, pfnNotifyRead,(PPDMIHOSTDEVICEPORT pInterface, const void *pvBuf, size_t *pcbRead));
    1680 } PDMIHOSTDEVICEPORT;
    1681 
    1682 
    1683 /** Pointer to a Host Device connector interface. */
    1684 typedef struct PDMIHOSTDEVICECONNECTOR *PPDMIHOSTDEVICECONNECTOR;
    1685 /**
    1686  * Host device connector interface
    1687  * Pair with PDMIHOSTDEVICEPORT.
    1688  */
    1689 typedef struct PDMIHOSTDEVICECONNECTOR
     1688    DECLR3CALLBACKMEMBER(int, pfnNotifyRead,(PPDMIHOSTPARALLELPORT pInterface, const void *pvBuf, size_t *pcbRead));
     1689
     1690    /**
     1691     * Notify device/driver that an interrupt has occured.
     1692     *
     1693     * @returns VBox status code.
     1694     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1695     * @thread  Any thread.
     1696     */
     1697    DECLR3CALLBACKMEMBER(int, pfnNotifyInterrupt, (PPDMIHOSTPARALLELPORT pInterface));
     1698} PDMIHOSTPARALLELPORT;
     1699
     1700
     1701/** Pointer to a Host Parallel connector interface. */
     1702typedef struct PDMIHOSTPARALLELCONNECTOR *PPDMIHOSTPARALLELCONNECTOR;
     1703
     1704/**
     1705 * Host parallel connector interface
     1706 * Pair with PDMIHOSTPARALLELPORT.
     1707 */
     1708typedef struct PDMIHOSTPARALLELCONNECTOR
    16901709{
    16911710    /**
     
    16981717     * @thread  Any thread.
    16991718     */
    1700     DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIHOSTDEVICECONNECTOR pInterface, const void *pvBuf, size_t *pcbWrite));
     1719    DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf, size_t *pcbWrite));
    17011720
    17021721    /**
     
    17091728     * @thread  Any thread.
    17101729     */
    1711     DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIHOSTDEVICECONNECTOR pInterface, void *pvBuf, size_t *pcbRead));
    1712 
    1713     /**
    1714      * Perform IO control on the host device.
    1715      *
    1716      * @returns VBox status code.
    1717      * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1718      * @param   uCommand        The number of the command to set or get data
    1719      * @param   pvData          Where to store the command data.
    1720      * @thread  Any thread.
    1721      */
    1722     DECLR3CALLBACKMEMBER(int, pfnIOCtl,(PPDMIHOSTDEVICECONNECTOR pInterface, RTUINT uCommand, void *pvData));
    1723 } PDMIHOSTDEVICECONNECTOR;
     1730    DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf, size_t *pcbRead));
     1731
     1732    /**
     1733     * Write control register bits.
     1734     *
     1735     * @returns VBox status code.
     1736     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1737     * @param   val             The new control register value.
     1738     * @thread  Any thread.
     1739     */
     1740    DECLR3CALLBACKMEMBER(int, pfnWriteControl,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t val));
     1741 
     1742    /**
     1743     * Read control register bits.
     1744     *
     1745     * @returns VBox status code.
     1746     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1747     * @param   pvBuf           Where to store the control register bits.
     1748     * @thread  Any thread.
     1749     */
     1750    DECLR3CALLBACKMEMBER(int, pfnReadControl,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pvBuf));
     1751
     1752    /**
     1753     * Read status register bits.
     1754     *
     1755     * @returns VBox status code.
     1756     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1757     * @param   pvBuf           Where to store the status register bits.
     1758     * @thread  Any thread.
     1759     */
     1760    DECLR3CALLBACKMEMBER(int, pfnReadStatus,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pvBuf));
     1761
     1762    /**
     1763     * Set mode of the host parallel port.
     1764     *
     1765     * @returns VBox status code.
     1766     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1767     * @param   mode            The mode of the host parallel port.
     1768     * @thread  Any thread.
     1769     */
     1770    DECLR3CALLBACKMEMBER(int, pfnSetMode,(PPDMIHOSTPARALLELCONNECTOR pInterface, PDMPARALLELPORTMODE mode));
     1771} PDMIHOSTPARALLELCONNECTOR;
    17241772
    17251773
  • trunk/src/VBox/Devices/PC/vbox.dsl

    r4774 r6222  
    414414                    })
    415415                }
     416
     417                // Parallel port
     418                Device (LPT)
     419                {
     420                    Name (_HID, EisaId ("PNP0400"))
     421                    Method (_STA, 0, NotSerialized)
     422                    {
     423                        Return (0x0F)
     424                    }
     425                    Name (_CRS, ResourceTemplate ()
     426                    {
     427                        IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
     428                        IO (Decode16, 0x0778, 0x0778, 0x08, 0x08)
     429                        IRQNoFlags () {7}
     430                    })
     431                }
    416432            }
    417433
  • trunk/src/VBox/Devices/Parallel/DevParallel.cpp

    r5999 r6222  
    3232
    3333#include "Builtins.h"
    34 #include "ParallelIOCtlCmd.h"
    3534
    3635#define PARALLEL_SAVED_STATE_VERSION 1
     
    4443#define LPT_STATUS_IRQ                 0x04
    4544#define LPT_STATUS_BIT1                0x02 /* reserved (only for completeness) */
    46 #define LPT_STATUS_BIT0                0x01 /* reserved (only for completeness) */
     45#define LPT_STATUS_EPP_TIMEOUT         0x01
    4746
    4847#define LPT_CONTROL_BIT7               0x80 /* reserved (only for completeness) */
     
    5554#define LPT_CONTROL_STROBE             0x01
    5655
     56/** mode defines for the extended control register */
     57#define LPT_ECP_ECR_CHIPMODE_MASK      0xe0
     58#define LPT_ECP_ECR_CHIPMODE_GET_BITS(reg) ((reg) >> 5)
     59#define LPT_ECP_ECR_CHIPMODE_SET_BITS(val) ((val) << 5)
     60#define LPT_ECP_ECR_CHIPMODE_CONFIGURATION 0x07
     61#define LPT_ECP_ECR_CHIPMODE_FIFO_TEST 0x06
     62#define LPT_ECP_ECR_CHIPMODE_RESERVED  0x05
     63#define LPT_ECP_ECR_CHIPMODE_EPP       0x04
     64#define LPT_ECP_ECR_CHIPMODE_ECP_FIFO  0x03
     65#define LPT_ECP_ECR_CHIPMODE_PP_FIFO   0x02
     66#define LPT_ECP_ECR_CHIPMODE_BYTE      0x01
     67#define LPT_ECP_ECR_CHIPMODE_COMPAT    0x00
     68
     69/** FIFO status bits in extended control register */
     70#define LPT_ECP_ECR_FIFO_MASK          0x03
     71#define LPT_ECP_ECR_FIFO_SOME_DATA     0x00
     72#define LPT_ECP_ECR_FIFO_FULL          0x02
     73#define LPT_ECP_ECR_FIFO_EMPTY         0x01
     74
     75#define LPT_ECP_CONFIGA_FIFO_WITDH_MASK 0x70
     76#define LPT_ECP_CONFIGA_FIFO_WIDTH_GET_BITS(reg) ((reg) >> 4)
     77#define LPT_ECP_CONFIGA_FIFO_WIDTH_SET_BITS(val) ((val) << 4)
     78#define LPT_ECP_CONFIGA_FIFO_WIDTH_16   0x00
     79#define LPT_ECP_CONFIGA_FIFO_WIDTH_32   0x20
     80#define LPT_ECP_CONFIGA_FIFO_WIDTH_8    0x10
     81
     82#define LPT_ECP_FIFO_DEPTH 2
     83
     84
    5785typedef struct ParallelState
    5886{
     
    7098    R3PTRTYPE(PDMIBASE)                 IBase;
    7199    /** The host device port interface. */
    72     R3PTRTYPE(PDMIHOSTDEVICEPORT)       IHostDevicePort;
     100    R3PTRTYPE(PDMIHOSTPARALLELPORT)     IHostParallelPort;
    73101    /** Pointer to the attached base driver. */
    74102    R3PTRTYPE(PPDMIBASE)                pDrvBase;
    75103    /** Pointer to the attached host device. */
    76     R3PTRTYPE(PPDMIHOSTDEVICECONNECTOR) pDrvHostDeviceConnector;
     104    R3PTRTYPE(PPDMIHOSTPARALLELCONNECTOR) pDrvHostParallelConnector;
    77105
    78106    uint8_t                             reg_data;
    79107    uint8_t                             reg_status;
    80108    uint8_t                             reg_control;
     109    uint8_t                             reg_epp_addr;
     110    uint8_t                             reg_epp_data;
     111    uint8_t                             reg_ecp_ecr;
     112    uint8_t                             reg_ecp_base_plus_400h; /* has different meanings */
     113    uint8_t                             reg_ecp_config_b;
     114
     115    /** The ECP FIFO implementation*/
     116    uint8_t                             ecp_fifo[LPT_ECP_FIFO_DEPTH];
     117    int                                 act_fifo_pos_write;
     118    int                                 act_fifo_pos_read;
    81119
    82120    int                                 irq;
     121    uint8_t                             epp_timeout;
    83122
    84123    bool                                fGCEnabled;
     
    94133#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    95134
     135#define PDMIHOSTPARALLELPORT_2_PARALLELSTATE(pInstance)   ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostParallelPort)) )
     136#define PDMIHOSTDEVICEPORT_2_PARALLELSTATE(pInstance)   ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostDevicePort)) )
    96137#define PDMIBASE_2_PARALLELSTATE(pInstance)       ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IBase)) )
    97 #define PDMIHOSTDEVICEPORT_2_PARALLELSTATE(pInstance)   ( (ParallelState *)((uintptr_t)(pInterface) - RT_OFFSETOF(ParallelState, IHostDevicePort)) )
    98 
    99138
    100139__BEGIN_DECLS
    101140PDMBOTHCBDECL(int) parallelIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
    102141PDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
     142#if 0
     143PDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
     144PDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
     145#endif
    103146__END_DECLS
    104147
    105 
    106 static void parallel_update_irq(ParallelState *s)
    107 {
    108     if (s->reg_control & LPT_CONTROL_ENABLE_IRQ_VIA_ACK) {
     148static void parallel_set_irq(ParallelState *s)
     149{
     150    if (s->reg_control & LPT_CONTROL_ENABLE_IRQ_VIA_ACK)
     151    {
    109152        Log(("parallel_update_irq %d 1\n", s->irq));
    110153        PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 1);
    111     } else {
    112         Log(("parallel_update_irq %d 0\n", s->irq));
    113         PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 0);
    114     }
     154    }
     155}
     156
     157static void parallel_clear_irq(ParallelState *s)
     158{
     159    Log(("parallel_update_irq %d 0\n", s->irq));
     160    PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 0);
    115161}
    116162
     
    122168    addr &= 7;
    123169    LogFlow(("parallel: write addr=0x%02x val=0x%02x\n", addr, val));
     170    ch = val;
     171
    124172    switch(addr) {
    125173    default:
     
    129177        return VINF_IOM_HC_IOPORT_WRITE;
    130178#else
    131         ch = val;
    132179        s->reg_data = ch;
    133         if (RT_LIKELY(s->pDrvHostDeviceConnector))
     180        if (RT_LIKELY(s->pDrvHostParallelConnector))
    134181        {
    135182            Log(("parallel_io_port_write: write 0x%X\n", ch));
    136183            size_t cbWrite = 1;
    137             int rc = s->pDrvHostDeviceConnector->pfnWrite(s->pDrvHostDeviceConnector, &ch, &cbWrite);
     184            int rc = s->pDrvHostParallelConnector->pfnWrite(s->pDrvHostParallelConnector, &ch, &cbWrite);
    138185            AssertRC(rc);
    139186        }
     
    143190        break;
    144191    case 2:
    145         s->reg_control = val;
    146         parallel_update_irq(s);
     192        /** Set the reserved bits to one */
     193        ch |= (LPT_CONTROL_BIT6 | LPT_CONTROL_BIT7);
     194        if (ch != s->reg_control) {
     195#ifndef IN_RING3
     196            NOREF(ch);
     197            return VINF_IOM_HC_IOPORT_WRITE;
     198#else
     199            int rc = s->pDrvHostParallelConnector->pfnWriteControl(s->pDrvHostParallelConnector, ch);
     200            AssertRC(rc);
     201            s->reg_control = val;
     202#endif
     203        }
    147204        break;
    148205    case 3:
     206        s->reg_epp_addr = val;
    149207        break;
    150208    case 4:
     209        s->reg_epp_data = val;
    151210        break;
    152211    case 5:
     
    171230    default:
    172231    case 0:
     232        if (!(s->reg_control & LPT_CONTROL_ENABLE_BIDIRECT))
     233            ret = s->reg_data;
     234        else
     235        {
    173236#ifndef IN_RING3
    174237            *pRC = VINF_IOM_HC_IOPORT_READ;
    175238#else
    176             if (RT_LIKELY(s->pDrvHostDeviceConnector))
     239            if (RT_LIKELY(s->pDrvHostParallelConnector))
    177240            {
    178241                size_t cbRead;
    179                 int rc = s->pDrvHostDeviceConnector->pfnRead(s->pDrvHostDeviceConnector, &s->reg_data, &cbRead);
     242                int rc = s->pDrvHostParallelConnector->pfnRead(s->pDrvHostParallelConnector, &s->reg_data, &cbRead);
    180243                Log(("parallel_io_port_read: read 0x%X\n", s->reg_data));
    181244                AssertRC(rc);
     
    183246            ret = s->reg_data;
    184247#endif
     248        }
    185249        break;
    186250    case 1:
     251#ifndef IN_RING3
     252        *pRC = VINF_IOM_HC_IOPORT_READ;
     253#else
     254        if (RT_LIKELY(s->pDrvHostParallelConnector))
     255        {
     256            int rc = s->pDrvHostParallelConnector->pfnReadStatus(s->pDrvHostParallelConnector, &s->reg_status);
     257            AssertRC(rc);
     258        }
    187259        ret = s->reg_status;
     260        parallel_clear_irq(s);
     261#endif
    188262        break;
    189263    case 2:
     
    191265        break;
    192266    case 3:
     267        ret = s->reg_epp_addr;
    193268        break;
    194269    case 4:
     270        ret = s->reg_epp_data;
    195271        break;
    196272    case 5:
     
    205281}
    206282
     283#if 0
     284static int parallel_ioport_write_ecp(void *opaque, uint32_t addr, uint32_t val)
     285{
     286    ParallelState *s = (ParallelState *)opaque;
     287    unsigned char ch;
     288
     289    addr &= 7;
     290    LogFlow(("parallel: write ecp addr=0x%02x val=0x%02x\n", addr, val));
     291    ch = val;
     292    switch(addr) {
     293    default:
     294    case 0:
     295        if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
     296            s->ecp_fifo[s->act_fifo_pos_write] = ch;
     297            s->act_fifo_pos_write++;
     298            if (s->act_fifo_pos_write < LPT_ECP_FIFO_DEPTH) {
     299                /** FIFO has some data (clear both FIFO bits) */
     300                s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
     301            } else {
     302                /** FIFO is full */
     303                /** Clear FIFO empty bit */
     304                s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_EMPTY;
     305                /** Set FIFO full bit */
     306                s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_FULL;
     307                s->act_fifo_pos_write = 0;
     308            }
     309        } else {
     310            s->reg_ecp_base_plus_400h = ch;
     311        }
     312        break;
     313    case 1:
     314        s->reg_ecp_config_b = ch;
     315        break;
     316    case 2:
     317        /** If we change the mode clear FIFO */
     318        if ((ch & LPT_ECP_ECR_CHIPMODE_MASK) != (s->reg_ecp_ecr & LPT_ECP_ECR_CHIPMODE_MASK)) {
     319            /** reset the fifo */
     320            s->act_fifo_pos_write = 0;
     321            s->act_fifo_pos_read = 0;
     322            /** Set FIFO empty bit */
     323            s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_EMPTY;
     324            /** Clear FIFO full bit */
     325            s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_FULL;
     326        }
     327        /** Set new mode */
     328        s->reg_ecp_ecr |= LPT_ECP_ECR_CHIPMODE_SET_BITS(LPT_ECP_ECR_CHIPMODE_GET_BITS(ch));
     329        break;
     330    case 3:
     331        break;
     332    case 4:
     333        break;
     334    case 5:
     335        break;
     336    case 6:
     337        break;
     338    case 7:
     339        break;
     340    }
     341    return VINF_SUCCESS;
     342}
     343
     344static uint32_t parallel_ioport_read_ecp(void *opaque, uint32_t addr, int *pRC)
     345{
     346    ParallelState *s = (ParallelState *)opaque;
     347    uint32_t ret = ~0U;
     348
     349    *pRC = VINF_SUCCESS;
     350
     351    addr &= 7;
     352    switch(addr) {
     353    default:
     354    case 0:
     355        if (LPT_ECP_ECR_CHIPMODE_GET_BITS(s->reg_ecp_ecr) == LPT_ECP_ECR_CHIPMODE_FIFO_TEST) {
     356            ret = s->ecp_fifo[s->act_fifo_pos_read];
     357            s->act_fifo_pos_read++;
     358            if (s->act_fifo_pos_read == LPT_ECP_FIFO_DEPTH)
     359                s->act_fifo_pos_read = 0; /** end of FIFO, start at beginning */
     360            if (s->act_fifo_pos_read == s->act_fifo_pos_write) {
     361                /** FIFO is empty */
     362                /** Set FIFO empty bit */
     363                s->reg_ecp_ecr |= LPT_ECP_ECR_FIFO_EMPTY;
     364                /** Clear FIFO full bit */
     365                s->reg_ecp_ecr &= ~LPT_ECP_ECR_FIFO_FULL;
     366            } else {
     367                /** FIFO has some data (clear all FIFO bits) */
     368                s->reg_ecp_ecr &= ~(LPT_ECP_ECR_FIFO_EMPTY | LPT_ECP_ECR_FIFO_FULL);
     369            }
     370        } else {
     371            ret = s->reg_ecp_base_plus_400h;
     372        }
     373        break;
     374    case 1:
     375        ret = s->reg_ecp_config_b;
     376        break;
     377    case 2:
     378        ret = s->reg_ecp_ecr;
     379        break;
     380    case 3:
     381        break;
     382    case 4:
     383        break;
     384    case 5:
     385        break;
     386    case 6:
     387        break;
     388    case 7:
     389        break;
     390    }
     391    LogFlow(("parallel: read ecp addr=0x%02x val=0x%02x\n", addr, ret));
     392    return ret;
     393}
     394#endif
     395
    207396#ifdef IN_RING3
    208 static DECLCALLBACK(int) parallelNotifyRead(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead)
    209 {
    210     ParallelState *pData = PDMIHOSTDEVICEPORT_2_PARALLELSTATE(pInterface);
    211     int rc;
    212 
    213     NOREF(pvBuf); NOREF(pcbRead); NOREF(pData); NOREF(rc);
     397static DECLCALLBACK(int) parallelNotifyInterrupt(PPDMIHOSTPARALLELPORT pInterface)
     398{
     399    ParallelState *pData = PDMIHOSTPARALLELPORT_2_PARALLELSTATE(pInterface);
     400
     401    PDMCritSectEnter(&pData->CritSect, VINF_SUCCESS);
     402    parallel_set_irq(pData);
     403    PDMCritSectLeave(&pData->CritSect);
     404
    214405    return VINF_SUCCESS;
    215 #if 0
    216     Assert(*pcbRead != 0);
    217 
    218     PDMCritSectEnter(&pData->CritSect, VERR_PERMISSION_DENIED);
    219     if (pData->lsr & UART_LSR_DR)
    220     {
    221         /* If a character is still in the read queue, then wait for it to be emptied. */
    222         PDMCritSectLeave(&pData->CritSect);
    223         rc = RTSemEventWait(pData->ReceiveSem, 250);
    224         if (VBOX_FAILURE(rc))
    225             return rc;
    226 
    227         PDMCritSectEnter(&pData->CritSect, VERR_PERMISSION_DENIED);
    228     }
    229 
    230     if (!(pData->lsr & UART_LSR_DR))
    231     {
    232         pData->rbr = *(const char *)pvBuf;
    233         pData->lsr |= UART_LSR_DR;
    234         serial_update_irq(pData);
    235         *pcbRead = 1;
    236         rc = VINF_SUCCESS;
    237     }
    238     else
    239         rc = VERR_TIMEOUT;
    240 
    241     PDMCritSectLeave(&pData->CritSect);
    242 
    243     return rc;
    244 #endif
    245406}
    246407#endif /* IN_RING3 */
     
    312473}
    313474
     475#if 0
     476/**
     477 * Port I/O Handler for OUT operations on ECP registers.
     478 *
     479 * @returns VBox status code.
     480 *
     481 * @param   pDevIns     The device instance.
     482 * @param   pvUser      User argument.
     483 * @param   Port        Port number used for the IN operation.
     484 * @param   u32         The value to output.
     485 * @param   cb          The value size in bytes.
     486 */
     487PDMBOTHCBDECL(int) parallelIOPortWriteECP(PPDMDEVINS pDevIns, void *pvUser,
     488                                          RTIOPORT Port, uint32_t u32, unsigned cb)
     489{
     490    ParallelState *pData = PDMINS2DATA(pDevIns, ParallelState *);
     491    int          rc = VINF_SUCCESS;
     492
     493    if (cb == 1)
     494    {
     495        rc = PDMCritSectEnter(&pData->CritSect, VINF_IOM_HC_IOPORT_WRITE);
     496        if (rc == VINF_SUCCESS)
     497        {
     498            Log2(("%s: ecp port %#06x val %#04x\n", __FUNCTION__, Port, u32));
     499            rc = parallel_ioport_write_ecp (pData, Port, u32);
     500            PDMCritSectLeave(&pData->CritSect);
     501        }
     502    }
     503    else
     504        AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
     505
     506    return rc;
     507}
     508
     509/**
     510 * Port I/O Handler for IN operations on ECP registers.
     511 *
     512 * @returns VBox status code.
     513 *
     514 * @param   pDevIns     The device instance.
     515 * @param   pvUser      User argument.
     516 * @param   Port        Port number used for the IN operation.
     517 * @param   u32         The value to output.
     518 * @param   cb          The value size in bytes.
     519 */
     520PDMBOTHCBDECL(int) parallelIOPortReadECP(PPDMDEVINS pDevIns, void *pvUser,
     521                                         RTIOPORT Port, uint32_t *pu32, unsigned cb)
     522{
     523    ParallelState *pData = PDMINS2DATA(pDevIns, ParallelState *);
     524    int          rc = VINF_SUCCESS;
     525
     526    if (cb == 1)
     527    {
     528        rc = PDMCritSectEnter(&pData->CritSect, VINF_IOM_HC_IOPORT_READ);
     529        if (rc == VINF_SUCCESS)
     530        {
     531            *pu32 = parallel_ioport_read_ecp (pData, Port, &rc);
     532            Log2(("%s: ecp port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
     533            PDMCritSectLeave(&pData->CritSect);
     534        }
     535    }
     536    else
     537        rc = VERR_IOM_IOPORT_UNUSED;
     538
     539    return rc;
     540}
     541#endif
     542
    314543#ifdef IN_RING3
    315544/**
     
    384613{
    385614    ParallelState *pData = PDMINS2DATA(pDevIns, ParallelState *);
    386     pData->pDevInsGC   = PDMDEVINS_2_GCPTR(pDevIns);
     615    pData->pDevInsGC     += offDelta;
    387616}
    388617
     
    395624        case PDMINTERFACE_BASE:
    396625            return &pData->IBase;
    397         case PDMINTERFACE_HOST_DEVICE_PORT:
    398             return &pData->IHostDevicePort;
     626        case PDMINTERFACE_HOST_PARALLEL_PORT:
     627            return &pData->IHostParallelPort;
    399628        default:
    400629            return NULL;
     
    415644    ParallelState *pData = PDMINS2DATA(pDevIns, ParallelState *);
    416645
    417     RTSemEventDestroy(pData->ReceiveSem);
    418     pData->ReceiveSem = NIL_RTSEMEVENT;
    419 
    420646    PDMR3CritSectDelete(&pData->CritSect);
     647
    421648    return VINF_SUCCESS;
    422649}
     
    441668{
    442669    int            rc;
    443     ParallelState   *pData = PDMINS2DATA(pDevIns, ParallelState*);
     670    ParallelState  *pData = PDMINS2DATA(pDevIns, ParallelState*);
    444671    uint16_t       io_base;
    445672    uint8_t        irq_lvl;
     
    454681     */
    455682    if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0IOBase\0"))
    456         return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
     683        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
     684                                N_("Configuration error: Unknown config key"));
    457685
    458686    rc = CFGMR3QueryBool(pCfgHandle, "GCEnabled", &pData->fGCEnabled);
     
    473701    pData->IBase.pfnQueryInterface = parallelQueryInterface;
    474702
    475     /* ICharPort */
    476     /* pData->ICharPort.pfnNotifyRead = parallelNotifyRead; */
     703    /* IHostParallelPort */
     704    pData->IHostParallelPort.pfnNotifyInterrupt = parallelNotifyInterrupt;
    477705
    478706    rc = RTSemEventCreate(&pData->ReceiveSem);
     
    489717        return rc;
    490718
    491 /** @todo r=bird: Check for VERR_CFGM_VALUE_NOT_FOUND and provide sensible defaults.
    492  * Also do AssertMsgFailed(("Configuration error:....)) in the failure cases of CFGMR3Query*()
    493  * and CFGR3AreValuesValid() like we're doing in the other devices.  */
    494719    rc = CFGMR3QueryU8(pCfgHandle, "IRQ", &irq_lvl);
    495     if (VBOX_FAILURE(rc))
    496         return rc;
     720    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     721        irq_lvl = 7;
     722    else if (VBOX_FAILURE(rc))
     723        return PDMDEV_SET_ERROR(pDevIns, rc,
     724                                N_("Configuration error: Failed to get the \"IRQ\" value"));
    497725
    498726    rc = CFGMR3QueryU16(pCfgHandle, "IOBase", &io_base);
    499     if (VBOX_FAILURE(rc))
    500         return rc;
     727    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     728        io_base = 0x378;
     729    else if (VBOX_FAILURE(rc))
     730        return PDMDEV_SET_ERROR(pDevIns, rc,
     731                                N_("Configuration error: Failed to get the \"IOBase\" value"));
    501732
    502733    Log(("parallelConstruct instance %d iobase=%04x irq=%d\n", iInstance, io_base, irq_lvl));
    503734
    504735    pData->irq = irq_lvl;
    505     pData->reg_status = LPT_STATUS_BUSY | LPT_STATUS_IRQ;
    506     pData->reg_control = LPT_CONTROL_STROBE | LPT_CONTROL_AUTO_LINEFEED | LPT_CONTROL_SELECT_PRINTER;
    507736    pData->base = io_base;
     737   
     738    /* Init parallel state */
     739    pData->reg_data = 0;
     740    pData->reg_ecp_ecr = LPT_ECP_ECR_CHIPMODE_COMPAT | LPT_ECP_ECR_FIFO_EMPTY;
     741    pData->act_fifo_pos_read = 0;
     742    pData->act_fifo_pos_write = 0;
     743
    508744    rc = PDMDevHlpIOPortRegister(pDevIns, io_base, 8, 0,
    509745                                 parallelIOPortWrite, parallelIOPortRead,
    510746                                 NULL, NULL, "PARALLEL");
    511     if (VBOX_FAILURE (rc))
     747    if (VBOX_FAILURE(rc))
    512748        return rc;
    513749
     750#if 0
     751    /* register ecp registers */
     752    rc = PDMDevHlpIOPortRegister(pDevIns, io_base+0x400, 8, 0,
     753                                 parallelIOPortWriteECP, parallelIOPortReadECP,
     754                                 NULL, NULL, "PARALLEL ECP");
     755    if (VBOX_FAILURE(rc))
     756        return rc;
     757#endif
     758
    514759    if (pData->fGCEnabled)
     760    {
    515761        rc = PDMDevHlpIOPortRegisterGC(pDevIns, io_base, 8, 0, "parallelIOPortWrite",
    516762                                      "parallelIOPortRead", NULL, NULL, "Parallel");
     763        if (VBOX_FAILURE(rc))
     764            return rc;
     765
     766#if 0
     767        rc = PDMDevHlpIOPortRegisterGC(pDevIns, io_base+0x400, 8, 0, "parallelIOPortWriteECP",
     768                                      "parallelIOPortReadECP", NULL, NULL, "Parallel Ecp");
     769        if (VBOX_FAILURE(rc))
     770            return rc;
     771#endif
     772    }
    517773
    518774    if (pData->fR0Enabled)
     775    {
    519776        rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base, 8, 0, "parallelIOPortWrite",
    520777                                      "parallelIOPortRead", NULL, NULL, "Parallel");
    521 
    522     /* Attach the char driver and get the interfaces. For now no run-time
     778        if (VBOX_FAILURE(rc))
     779            return rc;
     780
     781#if 0
     782        rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base+0x400, 8, 0, "parallelIOPortWriteECP",
     783                                      "parallelIOPortReadECP", NULL, NULL, "Parallel Ecp");
     784        if (VBOX_FAILURE(rc))
     785            return rc;
     786#endif
     787    }
     788
     789    /* Attach the parallel port driver and get the interfaces. For now no run-time
    523790     * changes are supported. */
    524791    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pData->IBase, &pData->pDrvBase, "Parallel Host");
    525792    if (VBOX_SUCCESS(rc))
    526793    {
    527         pData->pDrvHostDeviceConnector = (PDMIHOSTDEVICECONNECTOR *)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_HOST_DEVICE_CONNECTOR);
    528         if (!pData->pDrvHostDeviceConnector)
     794        pData->pDrvHostParallelConnector = (PDMIHOSTPARALLELCONNECTOR *)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase,
     795                                                                                                           PDMINTERFACE_HOST_PARALLEL_CONNECTOR);
     796        if (!pData->pDrvHostParallelConnector)
    529797        {
    530             AssertMsgFailed(("Configuration error: instance %d has no char interface!\n", iInstance));
     798            AssertMsgFailed(("Configuration error: instance %d has no host parallel interface!\n", iInstance));
    531799            return VERR_PDM_MISSING_INTERFACE;
    532800        }
     
    536804    {
    537805        pData->pDrvBase = NULL;
    538         pData->pDrvHostDeviceConnector = NULL;
     806        pData->pDrvHostParallelConnector = NULL;
    539807        LogRel(("Parallel%d: no unit\n", iInstance));
    540808    }
     
    545813                                   N_("Parallel device %d cannot attach to host driver\n"), iInstance);
    546814    }
     815
     816    /** Set compatibility mode */
     817    pData->pDrvHostParallelConnector->pfnSetMode(pData->pDrvHostParallelConnector, PDM_PARALLEL_PORT_MODE_COMPAT);
     818    /** Get status of control register */
     819    pData->pDrvHostParallelConnector->pfnReadControl(pData->pDrvHostParallelConnector, &pData->reg_control);
    547820
    548821    rc = PDMDevHlpSSMRegister(
  • trunk/src/VBox/Devices/Parallel/DrvHostParallel.cpp

    r5999 r6222  
    2323#define LOG_GROUP LOG_GROUP_DRV_HOST_PARALLEL
    2424#include <VBox/pdmdrv.h>
     25#include <VBox/pdmthread.h>
    2526#include <iprt/asm.h>
    2627#include <iprt/assert.h>
    2728#include <iprt/stream.h>
    2829#include <iprt/semaphore.h>
     30#include <iprt/file.h>
    2931
    3032#ifdef RT_OS_LINUX
     
    3638# include <linux/ppdev.h>
    3739# include <linux/parport.h>
     40# include <errno.h>
    3841#endif
    3942
    4043#include "Builtins.h"
    41 #include "ParallelIOCtlCmd.h"
    42 
    4344
    4445/*******************************************************************************
     
    5152{
    5253    /** Pointer to the driver instance structure. */
    53     PPDMDRVINS                  pDrvIns;
     54    PPDMDRVINS                    pDrvIns;
    5455    /** Pointer to the char port interface of the driver/device above us. */
    55     PPDMIHOSTDEVICEPORT         pDrvHostDevicePort;
     56    PPDMIHOSTPARALLELPORT         pDrvHostParallelPort;
    5657    /** Our host device interface. */
    57     PDMIHOSTDEVICECONNECTOR     IHostDeviceConnector;
     58    PDMIHOSTPARALLELCONNECTOR     IHostParallelConnector;
    5859    /** Our host device port interface. */
    59     PDMIHOSTDEVICEPORT          IHostDevicePort;
     60    PDMIHOSTPARALLELPORT          IHostParallelPort;
    6061    /** Device Path */
    61     char                        *pszDevicePath;
     62    char                          *pszDevicePath;
    6263    /** Device Handle */
    63     RTFILE                      FileDevice;
    64     /** Flag to notify the receive thread it should terminate. */
    65     volatile bool               fShutdown;
    66     /** Receive thread ID. */
    67     RTTHREAD                    ReceiveThread;
    68     /** Send thread ID. */
    69     RTTHREAD                    SendThread;
    70     /** Send event semephore */
    71     RTSEMEVENT                  SendSem;
    72 
     64    RTFILE                        FileDevice;
     65    /** Thread waiting for interrupts. */
     66    PPDMTHREAD                    pMonitorThread;
     67    /** Wakeup pipe read end. */
     68    RTFILE                        WakeupPipeR;
     69    /** Wakeup pipe write end. */
     70    RTFILE                        WakeupPipeW;
    7371} DRVHOSTPARALLEL, *PDRVHOSTPARALLEL;
    7472
    7573/** Converts a pointer to DRVHOSTPARALLEL::IHostDeviceConnector to a PDRHOSTPARALLEL. */
    76 #define PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostDeviceConnector)) )
     74#define PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostParallelConnector)) )
    7775/** Converts a pointer to DRVHOSTPARALLEL::IHostDevicePort to a PDRHOSTPARALLEL. */
    78 #define PDMIHOSTDEVICEPORT_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostDevicePort)) )
     76#define PDMIHOSTPARALLELPORT_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostParallelPort)) )
    7977
    8078/* -=-=-=-=- IBase -=-=-=-=- */
     
    9694        case PDMINTERFACE_BASE:
    9795            return &pDrvIns->IBase;
    98         case PDMINTERFACE_HOST_DEVICE_CONNECTOR:
    99             return &pData->IHostDeviceConnector;
     96        case PDMINTERFACE_HOST_PARALLEL_CONNECTOR:
     97            return &pData->IHostParallelConnector;
    10098        default:
    10199            return NULL;
     
    106104
    107105/** @copydoc PDMICHAR::pfnWrite */
    108 static DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTDEVICECONNECTOR pInterface, const void *pvBuf, size_t *cbWrite)
    109 {
    110     PDRVHOSTPARALLEL pData = PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface);
     106static DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf, size_t *cbWrite)
     107{
     108    PDRVHOSTPARALLEL pData = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
    111109    const unsigned char *pBuffer = (const unsigned char *)pvBuf;
    112110
     
    114112
    115113    ioctl(pData->FileDevice, PPWDATA, pBuffer);
    116 
    117     RTSemEventSignal(pData->SendSem);
    118     return VINF_SUCCESS;
    119 }
    120 
    121 static DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTDEVICECONNECTOR pInterface, void *pvBuf, size_t *cbRead)
    122 {
    123     PDRVHOSTPARALLEL pData = PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface);
     114    *cbWrite = 1;
     115
     116    return VINF_SUCCESS;
     117}
     118
     119static DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf, size_t *cbRead)
     120{
     121    PDRVHOSTPARALLEL pData = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
    124122    unsigned char *pBuffer = (unsigned char *)pvBuf;
    125123
     
    132130}
    133131
    134 static DECLCALLBACK(int) drvHostParallelIOCtl(PPDMIHOSTDEVICECONNECTOR pInterface, RTUINT uCommand,
    135                                               void *pvData)
    136 {
    137     PDRVHOSTPARALLEL pData = PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface);
    138     unsigned long ioctlCommand;
    139 
    140     LogFlow(("%s: uCommand=%d pvData=%#p\n", __FUNCTION__, uCommand, pvData));
    141 
    142     switch (uCommand) {
    143         case LPT_IOCTL_COMMAND_SET_CONTROL:
    144             ioctlCommand = PPWCONTROL;
     132static DECLCALLBACK(int) drvHostParallelSetMode(PPDMIHOSTPARALLELCONNECTOR pInterface, PDMPARALLELPORTMODE mode)
     133{
     134    PDRVHOSTPARALLEL pData = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
     135    int ppdev_mode;
     136
     137    LogFlow(("%s: mode=%d\n", __FUNCTION__, mode));
     138
     139    switch (mode) {
     140        case PDM_PARALLEL_PORT_MODE_COMPAT:
     141            ppdev_mode = IEEE1284_MODE_COMPAT;
    145142            break;
    146         case LPT_IOCTL_COMMAND_GET_CONTROL:
    147             ioctlCommand = PPRCONTROL;
     143        case PDM_PARALLEL_PORT_MODE_EPP:
     144            ppdev_mode = IEEE1284_MODE_EPP;
    148145            break;
    149         default:
    150             AssertMsgFailed(("uCommand = %d?\n"));
    151             return VERR_INVALID_PARAMETER;
    152     }
    153 
    154     ioctl(pData->FileDevice, ioctlCommand, pvData);
    155 
    156     return VINF_SUCCESS;
     146        case PDM_PARALLEL_PORT_MODE_ECP:
     147            //ppdev_mode = IEEE1284_MODE_ECP;
     148            break;
     149    }
     150 
     151    ioctl(pData->FileDevice, PPSETMODE, &ppdev_mode);
     152
     153    return VINF_SUCCESS;
     154}
     155
     156static DECLCALLBACK(int) drvHostParallelWriteControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t val)
     157{
     158    PDRVHOSTPARALLEL pData = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
     159
     160    LogFlow(("%s: val=%d\n", __FUNCTION__, val));
     161
     162    ioctl(pData->FileDevice, PPWCONTROL, &val);
     163
     164    return VINF_SUCCESS;
     165}
     166
     167static DECLCALLBACK(int) drvHostParallelReadControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pvBuf)
     168{
     169    PDRVHOSTPARALLEL pData = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
     170    uint8_t val;
     171
     172    ioctl(pData->FileDevice, PPRCONTROL, &val);
     173
     174    LogFlow(("%s: val=%d\n", __FUNCTION__, val));
     175
     176    *pvBuf = val;
     177
     178    return VINF_SUCCESS;
     179}
     180
     181static DECLCALLBACK(int) drvHostParallelReadStatus(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pvBuf)
     182{
     183    PDRVHOSTPARALLEL pData = PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface);
     184    uint8_t val;
     185
     186    ioctl(pData->FileDevice, PPRSTATUS, &val);
     187
     188    LogFlow(("%s: val=%d\n", __FUNCTION__, val));
     189
     190    *pvBuf = val;
     191
     192    return VINF_SUCCESS;
     193}
     194
     195static DECLCALLBACK(int) drvHostParallelMonitorThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     196{
     197    PDRVHOSTPARALLEL pData = PDMINS2DATA(pDrvIns, PDRVHOSTPARALLEL);
     198    fd_set readfds;
     199
     200    /*
     201     * We can wait for interrupts using the select call on linux hosts.
     202     */
     203
     204    /*
     205     * Setup the file descriptor set.
     206     */
     207    FD_ZERO(&readfds);
     208    FD_SET(pData->FileDevice, &readfds);
     209    FD_SET(pData->WakeupPipeR, &readfds);
     210
     211    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     212    {
     213        int rc;
     214
     215        rc = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
     216        if (rc < 0)
     217        {
     218            AssertMsgFailed(("select failed with rc=%d\n", RTErrConvertFromErrno(errno)));
     219            return RTErrConvertFromErrno(errno);
     220        }
     221
     222        if (FD_ISSET(pData->WakeupPipeR, &readfds))
     223        {
     224            /* notification to terminate -- drain the pipe */
     225            char ch;
     226            size_t cbRead;
     227            RTFileRead(pData->WakeupPipeR, &ch, 1, &cbRead);
     228            continue;
     229        }
     230
     231        /* Interrupt occured. */
     232        rc = pData->pDrvHostParallelPort->pfnNotifyInterrupt(pData->pDrvHostParallelPort);
     233        AssertRC(rc);
     234    }
     235
     236    return VINF_SUCCESS;
     237}
     238
     239/**
     240 * Unblock the monitor thread so it can respond to a state change.
     241 *
     242 * @returns a VBox status code.
     243 * @param     pDrvIns     The driver instance.
     244 * @param     pThread     The send thread.
     245 */
     246static DECLCALLBACK(int) drvHostParallelWakeupMonitorThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     247{
     248    PDRVHOSTPARALLEL pData = PDMINS2DATA(pDrvIns, PDRVHOSTPARALLEL);
     249
     250    return RTFileWrite(pData->WakeupPipeW, "", 1, NULL);
    157251}
    158252
     
    177271     * Init basic data members and interfaces.
    178272     */
    179     pData->ReceiveThread                    = NIL_RTTHREAD;
    180     pData->fShutdown                        = false;
     273
    181274    /* IBase. */
    182     pDrvIns->IBase.pfnQueryInterface        = drvHostParallelQueryInterface;
    183     /* IChar. */
    184     pData->IHostDeviceConnector.pfnWrite                   = drvHostParallelWrite;
    185     pData->IHostDeviceConnector.pfnIOCtl                   = drvHostParallelIOCtl;
    186     pData->IHostDeviceConnector.pfnRead                    = drvHostParallelRead;
     275    pDrvIns->IBase.pfnQueryInterface               = drvHostParallelQueryInterface;
     276    /* IHostParallelConnector. */
     277    pData->IHostParallelConnector.pfnWrite         = drvHostParallelWrite;
     278    pData->IHostParallelConnector.pfnRead          = drvHostParallelRead;
     279    pData->IHostParallelConnector.pfnSetMode       = drvHostParallelSetMode;
     280    pData->IHostParallelConnector.pfnWriteControl  = drvHostParallelWriteControl;
     281    pData->IHostParallelConnector.pfnReadControl   = drvHostParallelReadControl;
     282    pData->IHostParallelConnector.pfnReadStatus    = drvHostParallelReadStatus;
    187283
    188284    /*
     
    218314
    219315    /*
    220      * Get the IHostDevicePort interface of the above driver/device.
    221      */
    222     pData->pDrvHostDevicePort = (PPDMIHOSTDEVICEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_HOST_DEVICE_PORT);
    223     if (!pData->pDrvHostDevicePort)
    224         return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"), pDrvIns->iInstance);
    225 
    226     rc = RTSemEventCreate(&pData->SendSem);
    227     AssertRC(rc);
     316     * Get the IHostParallelPort interface of the above driver/device.
     317     */
     318    pData->pDrvHostParallelPort = (PPDMIHOSTPARALLELPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_HOST_PARALLEL_PORT);
     319    if (!pData->pDrvHostParallelPort)
     320        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"),
     321                                   pDrvIns->iInstance);
     322
     323    /*
     324     * Create wakeup pipe.
     325     */
     326    int aFDs[2];
     327    if (pipe(aFDs) != 0)
     328    {
     329        int rc = RTErrConvertFromErrno(errno);
     330        AssertRC(rc);
     331        return rc;
     332    }
     333    pData->WakeupPipeR = aFDs[0];
     334    pData->WakeupPipeW = aFDs[1];
     335
     336    /*
     337     * Start waiting for interrupts.
     338     */
     339    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pData->pMonitorThread, pData, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0,
     340                                  RTTHREADTYPE_IO, "Interrupt Monitor");
     341    if (VBOX_FAILURE(rc))
     342        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostSerial#%d cannot create monitor thread"), pDrvIns->iInstance);
    228343
    229344    return VINF_SUCCESS;
     
    244359
    245360    LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
    246 
    247     pData->fShutdown = true;
    248     if (pData->ReceiveThread)
    249     {
    250         RTThreadWait(pData->ReceiveThread, 1000, NULL);
    251         if (pData->ReceiveThread != NIL_RTTHREAD)
    252             LogRel(("Parallel%d: receive thread did not terminate\n", pDrvIns->iInstance));
    253     }
    254 
    255     RTSemEventSignal(pData->SendSem);
    256     RTSemEventDestroy(pData->SendSem);
    257     pData->SendSem = NIL_RTSEMEVENT;
    258 
    259     if (pData->SendThread)
    260     {
    261         RTThreadWait(pData->SendThread, 1000, NULL);
    262         if (pData->SendThread != NIL_RTTHREAD)
    263             LogRel(("Parallel%d: send thread did not terminate\n", pDrvIns->iInstance));
    264     }
    265361
    266362    ioctl(pData->FileDevice, PPRELEASE);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette