VirtualBox

Changeset 11277 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 8, 2008 8:15:59 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
34370
Message:

#1865: DevSerial. Also cleaned up the constructor mess.

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Serial/DevSerial.cpp

    r11269 r11277  
     1/* $Id$ */
    12/** @file
    2  *
    3  * VBox serial device:
    4  * Serial communication port driver
     3 * DevSerial - 16450 UART emulation.
    54 */
    65
     
    4746 *
    4847 */
    49 
    5048
    5149/*******************************************************************************
     
    6058#include <iprt/critsect.h>
    6159
    62 #include "Builtins.h"
     60#include "../Builtins.h"
    6361
    6462#undef VBOX_SERIAL_PCI /* The PCI variant has lots of problems: wrong IRQ line and wrong IO base assigned. */
    6563
    6664#ifdef VBOX_SERIAL_PCI
    67 #include <VBox/pci.h>
     65# include <VBox/pci.h>
    6866#endif /* VBOX_SERIAL_PCI */
    6967
     68
     69/*******************************************************************************
     70*   Defined Constants And Macros                                               *
     71*******************************************************************************/
    7072#define SERIAL_SAVED_STATE_VERSION  3
    7173
     
    115117#define UART_LSR_DR                     0x01    /* Receiver data ready */
    116118
     119
     120/*******************************************************************************
     121*   Structures and Typedefs                                                    *
     122*******************************************************************************/
    117123struct SerialState
    118124{
     
    120126    PDMCRITSECT                     CritSect;
    121127
    122     /** Pointer to the device instance. */
    123     R3PTRTYPE(PPDMDEVINS)           pDevInsHC;
    124     /** Pointer to the device instance. */
    125     RCPTRTYPE(PPDMDEVINS)           pDevInsGC;
    126 #if HC_ARCH_BITS == 64
    127     RTRCPTR                         Alignment0;
    128 #endif
     128    /** Pointer to the device instance - R3 Ptr. */
     129    PPDMDEVINSR3                    pDevInsR3;
     130    /** Pointer to the device instance - R0 Ptr. */
     131    PPDMDEVINSR0                    pDevInsR0;
     132    /** Pointer to the device instance - RC Ptr. */
     133    PPDMDEVINSRC                    pDevInsRC;
     134    RTRCPTR                         Alignment0; /**< Alignment. */
    129135    /** The base interface. */
    130136    PDMIBASE                        IBase;
     
    175181
    176182
     183/*******************************************************************************
     184*   Internal Functions                                                         *
     185*******************************************************************************/
    177186__BEGIN_DECLS
    178187PDMBOTHCBDECL(int) serialIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
     
    181190
    182191#ifdef IN_RING3
     192
    183193static void serial_update_irq(SerialState *s)
    184194{
     
    194204    if (s->iir != UART_IIR_NO_INT) {
    195205        Log(("serial_update_irq %d 1\n", s->irq));
    196 #ifdef VBOX_SERIAL_PCI
    197         PDMDevHlpPCISetIrqNoWait(CTXSUFF(s->pDevIns), 0, 1);
    198 #else /* !VBOX_SERIAL_PCI */
    199         PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 1);
    200 #endif /* !VBOX_SERIAL_PCI */
     206# ifdef VBOX_SERIAL_PCI
     207        PDMDevHlpPCISetIrqNoWait(s->CTX_SUFF(pDevIns), 0, 1);
     208# else /* !VBOX_SERIAL_PCI */
     209        PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 1);
     210# endif /* !VBOX_SERIAL_PCI */
    201211    } else {
    202212        Log(("serial_update_irq %d 0\n", s->irq));
    203 #ifdef VBOX_SERIAL_PCI
    204         PDMDevHlpPCISetIrqNoWait(CTXSUFF(s->pDevIns), 0, 0);
    205 #else /* !VBOX_SERIAL_PCI */
    206         PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 0);
    207 #endif /* !VBOX_SERIAL_PCI */
     213# ifdef VBOX_SERIAL_PCI
     214        PDMDevHlpPCISetIrqNoWait(s->CTX_SUFF(pDevIns), 0, 0);
     215# else /* !VBOX_SERIAL_PCI */
     216        PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 0);
     217# endif /* !VBOX_SERIAL_PCI */
    208218    }
    209219}
     
    233243        s->pDrvChar->pfnSetParameters(s->pDrvChar, speed, parity, data_bits, stop_bits);
    234244}
    235 #endif
     245
     246#endif /* IN_RING3 */
    236247
    237248static int serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     
    398409
    399410#ifdef IN_RING3
     411
    400412static DECLCALLBACK(int) serialNotifyRead(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead)
    401413{
     
    496508        {
    497509            Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, u32));
    498             rc = serial_ioport_write (pThis, Port, u32);
     510            rc = serial_ioport_write(pThis, Port, u32);
    499511            PDMCritSectLeave(&pThis->CritSect);
    500512        }
     
    528540        if (rc == VINF_SUCCESS)
    529541        {
    530             *pu32 = serial_ioport_read (pThis, Port, &rc);
     542            *pu32 = serial_ioport_read(pThis, Port, &rc);
    531543            Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
    532544            PDMCritSectLeave(&pThis->CritSect);
     
    540552
    541553#ifdef IN_RING3
     554
    542555/**
    543556 * Saves a state of the serial port device.
     
    610623    if (u32 != ~0U)
    611624    {
    612         AssertMsgFailed(("u32=%#x expected ~0\n", u32));
     625        AssertLogRelMsgFailed(("u32=%#x expected ~0\n", u32));
    613626        return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
    614627    }
     
    621634        AssertRC(rc);
    622635    }
    623     pThis->pDevInsHC = pDevIns;
    624     pThis->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
     636
     637    /* this isn't strictly necessary but cannot hurt... */
     638    pThis->pDevInsR3 = pDevIns;
     639    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     640    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    625641    return VINF_SUCCESS;
    626642}
     
    633649{
    634650    SerialState *pThis = PDMINS_2_DATA(pDevIns, SerialState *);
    635     pThis->pDevInsGC   = PDMDEVINS_2_GCPTR(pDevIns);
     651    pThis->pDevInsRC   = PDMDEVINS_2_RCPTR(pDevIns);
    636652}
    637653
     
    723739    Assert(iInstance < 4);
    724740
    725     pThis->pDevInsHC = pDevIns;
    726     pThis->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
    727 
    728741    /*
    729      * Validate configuration.
     742     * Initialize the instance data.
     743     * (Do this early or the destructor might choke on something!)
    730744     */
    731     if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0IOBase\0"))
    732     {
    733         AssertMsgFailed(("serialConstruct Invalid configuration values\n"));
    734         return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
    735     }
    736 
    737     rc = CFGMR3QueryBool(pCfgHandle, "GCEnabled", &pThis->fGCEnabled);
    738     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    739         pThis->fGCEnabled = true;
    740     else if (RT_FAILURE(rc))
    741         return PDMDEV_SET_ERROR(pDevIns, rc,
    742                                 N_("Configuration error: Failed to get the \"GCEnabled\" value"));
    743 
    744     rc = CFGMR3QueryBool(pCfgHandle, "R0Enabled", &pThis->fR0Enabled);
    745     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    746         pThis->fR0Enabled = true;
    747     else if (RT_FAILURE(rc))
    748         return PDMDEV_SET_ERROR(pDevIns, rc,
    749                                 N_("Configuration error: Failed to get the \"R0Enabled\" value"));
     745    pThis->pDevInsR3 = pDevIns;
     746    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     747    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     748
     749    pThis->lsr = UART_LSR_TEMT | UART_LSR_THRE;
     750    pThis->iir = UART_IIR_NO_INT;
     751    pThis->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
    750752
    751753    /* IBase */
     
    756758    pThis->ICharPort.pfnNotifyStatusLinesChanged = serialNotifyStatusLinesChanged;
    757759
    758     rc = RTSemEventCreate(&pThis->ReceiveSem);
    759     AssertRC(rc);
    760 
    761     /*
    762      * Initialize critical section.
    763      * This must of course be done before attaching drivers or anything else which can call us back..
    764      */
    765     char szName[24];
    766     RTStrPrintf(szName, sizeof(szName), "Serial#%d", iInstance);
    767     rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
    768     if (RT_FAILURE(rc))
    769         return rc;
    770 
    771     rc = CFGMR3QueryU8 (pCfgHandle, "IRQ", &irq_lvl);
    772     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    773     {
    774         /* Provide sensible defaults. */
    775         if (iInstance == 0)
    776             irq_lvl = 4;
    777         else if (iInstance == 1)
    778             irq_lvl = 3;
    779     }
    780     else if (RT_FAILURE(rc))
    781         return PDMDEV_SET_ERROR(pDevIns, rc,
    782                                 N_("Configuration error: Failed to get the \"IRQ\" value"));
    783 
    784     rc = CFGMR3QueryU16 (pCfgHandle, "IOBase", &io_base);
    785     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    786     {
    787         if (iInstance == 0)
    788             io_base = 0x3f8;
    789         else if (iInstance == 1)
    790             io_base = 0x2f8;
    791     }
    792     else if (RT_FAILURE(rc))
    793         return PDMDEV_SET_ERROR(pDevIns, rc,
    794                                 N_("Configuration error: Failed to get the \"IOBase\" value"));
    795 
    796     Log(("serialConstruct instance %d iobase=%04x irq=%d\n", iInstance, io_base, irq_lvl));
    797 
    798     pThis->irq = irq_lvl;
    799     pThis->lsr = UART_LSR_TEMT | UART_LSR_THRE;
    800     pThis->iir = UART_IIR_NO_INT;
    801     pThis->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
    802760#ifdef VBOX_SERIAL_PCI
    803     pThis->base = -1;
     761    /* the PCI device */
    804762    pThis->dev.config[0x00] = 0xee; /* Vendor: ??? */
    805763    pThis->dev.config[0x01] = 0x80;
     
    813771    pThis->dev.config[0x3c] = irq_lvl; /* preconfigure IRQ number (0 = autoconfig)*/
    814772    pThis->dev.config[0x3d] = 1;    /* interrupt pin 0 */
     773#endif /* VBOX_SERIAL_PCI */
     774
     775    /*
     776     * Validate and read the configuration.
     777     */
     778    if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0" "IOBase\0" "GCEnabled\0" "R0Enabled\0"))
     779    {
     780        AssertMsgFailed(("serialConstruct Invalid configuration values\n"));
     781        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
     782    }
     783
     784    rc = CFGMR3QueryBoolDef(pCfgHandle, "GCEnabled", &pThis->fGCEnabled, true);
     785    if (RT_FAILURE(rc))
     786        return PDMDEV_SET_ERROR(pDevIns, rc,
     787                                N_("Configuration error: Failed to get the \"GCEnabled\" value"));
     788
     789    rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &pThis->fR0Enabled, true);
     790    if (RT_FAILURE(rc))
     791        return PDMDEV_SET_ERROR(pDevIns, rc,
     792                                N_("Configuration error: Failed to get the \"R0Enabled\" value"));
     793
     794    rc = CFGMR3QueryU8(pCfgHandle, "IRQ", &irq_lvl);
     795    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     796    {
     797        /* Provide sensible defaults. */
     798        if (iInstance == 0)
     799            irq_lvl = 4;
     800        else if (iInstance == 1)
     801            irq_lvl = 3;
     802        else
     803            AssertReleaseFailed(); /* irq_lvl is undefined. */
     804    }
     805    else if (RT_FAILURE(rc))
     806        return PDMDEV_SET_ERROR(pDevIns, rc,
     807                                N_("Configuration error: Failed to get the \"IRQ\" value"));
     808
     809    rc = CFGMR3QueryU16(pCfgHandle, "IOBase", &io_base);
     810    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     811    {
     812        if (iInstance == 0)
     813            io_base = 0x3f8;
     814        else if (iInstance == 1)
     815            io_base = 0x2f8;
     816        else
     817            AssertReleaseFailed(); /* io_base is undefined */
     818    }
     819    else if (RT_FAILURE(rc))
     820        return PDMDEV_SET_ERROR(pDevIns, rc,
     821                                N_("Configuration error: Failed to get the \"IOBase\" value"));
     822
     823    Log(("DevSerial: instance %d iobase=%04x irq=%d\n", iInstance, io_base, irq_lvl));
     824
     825    pThis->irq = irq_lvl;
     826#ifdef VBOX_SERIAL_PCI
     827    pThis->base = -1;
     828#else
     829    pThis->base = io_base;
     830#endif
     831
     832    /*
     833     * Initialize critical section and the semaphore.
     834     * This must of course be done before attaching drivers or anything else which can call us back..
     835     */
     836    char szName[24];
     837    RTStrPrintf(szName, sizeof(szName), "Serial#%d", iInstance);
     838    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
     839    if (RT_FAILURE(rc))
     840        return rc;
     841
     842    rc = RTSemEventCreate(&pThis->ReceiveSem);
     843    AssertRC(rc);
     844
     845#ifdef VBOX_SERIAL_PCI
     846    /*
     847     * Register the PCI Device and region.
     848     */
    815849    rc = PDMDevHlpPCIRegister(pDevIns, &pThis->dev);
    816850    if (RT_FAILURE(rc))
    817851        return rc;
    818     /*
    819      * Register the PCI I/O ports.
    820      */
    821852    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, serialIOPortRegionMap);
    822853    if (RT_FAILURE(rc))
    823854        return rc;
     855
    824856#else /* !VBOX_SERIAL_PCI */
     857    /*
     858     * Register the I/O ports.
     859     */
    825860    pThis->base = io_base;
    826861    rc = PDMDevHlpIOPortRegister(pDevIns, io_base, 8, 0,
    827862                                 serialIOPortWrite, serialIOPortRead,
    828863                                 NULL, NULL, "SERIAL");
    829     if (RT_FAILURE (rc))
     864    if (RT_FAILURE(rc))
    830865        return rc;
    831866
     
    837872        rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base, 8, 0, "serialIOPortWrite",
    838873                                      "serialIOPortRead", NULL, NULL, "Serial");
    839 
    840874#endif /* !VBOX_SERIAL_PCI */
    841875
    842     /* Attach the char driver and get the interfaces. For now no run-time
    843      * changes are supported. */
    844     rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial Char");
    845     if (RT_SUCCESS(rc))
    846     {
    847         pThis->pDrvChar = (PDMICHAR *)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase, PDMINTERFACE_CHAR);
    848         if (!pThis->pDrvChar)
    849         {
    850             AssertMsgFailed(("Configuration error: instance %d has no char interface!\n", iInstance));
    851             return VERR_PDM_MISSING_INTERFACE;
    852         }
    853         /** @todo provide read notification interface!!!! */
    854     }
    855     else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    856     {
    857         pThis->pDrvBase = NULL;
    858         pThis->pDrvChar = NULL;
    859         LogRel(("Serial%d: no unit\n", iInstance));
    860     }
    861     else
    862     {
    863         AssertMsgFailed(("Serial%d: Failed to attach to char driver. rc=%Vrc\n", iInstance, rc));
    864         /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
    865         return rc;
    866     }
    867 
    868     rc = PDMDevHlpSSMRegister (
     876    /*
     877     * Saved state.
     878     */
     879    rc = PDMDevHlpSSMRegister(
    869880        pDevIns,                /* pDevIns */
    870881        pDevIns->pDevReg->szDeviceName, /* pszName */
     
    882893        return rc;
    883894
     895    /*
     896     * Attach the char driver and get the interfaces.
     897     * For now no run-time changes are supported.
     898     */
     899    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial Char");
     900    if (RT_SUCCESS(rc))
     901    {
     902        pThis->pDrvChar = (PDMICHAR *)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase, PDMINTERFACE_CHAR);
     903        if (!pThis->pDrvChar)
     904        {
     905            AssertLogRelMsgFailed(("Configuration error: instance %d has no char interface!\n", iInstance));
     906            return VERR_PDM_MISSING_INTERFACE;
     907        }
     908        /** @todo provide read notification interface!!!! */
     909    }
     910    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     911    {
     912        pThis->pDrvBase = NULL;
     913        pThis->pDrvChar = NULL;
     914        LogRel(("Serial%d: no unit\n", iInstance));
     915    }
     916    else
     917    {
     918        AssertLogRelMsgFailed(("Serial%d: Failed to attach to char driver. rc=%Vrc\n", iInstance, rc));
     919        /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
     920        return rc;
     921    }
     922
    884923    return VINF_SUCCESS;
    885924}
     925
    886926
    887927/**
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp

    r11270 r11277  
    901901    GEN_CHECK_OFF(SerialState, fGCEnabled);
    902902    GEN_CHECK_OFF(SerialState, fR0Enabled);
    903     GEN_CHECK_OFF(SerialState, pDevInsGC);
    904     GEN_CHECK_OFF(SerialState, pDevInsHC);
     903    GEN_CHECK_OFF(SerialState, pDevInsR3);
     904    GEN_CHECK_OFF(SerialState, pDevInsR0);
     905    GEN_CHECK_OFF(SerialState, pDevInsRC);
    905906    GEN_CHECK_OFF(SerialState, IBase);
    906907    GEN_CHECK_OFF(SerialState, ICharPort);
Note: See TracChangeset for help on using the changeset viewer.

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