VirtualBox

Changeset 1476 in vbox for trunk


Ignore:
Timestamp:
Mar 14, 2007 4:36:04 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
19537
Message:

First go at a serial port device with I/O hooked to named pipe/local
socket. Doesn't support mounting/unmounting at runtime yet.

Location:
trunk
Files:
5 edited

Legend:

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

    r210 r1476  
    123123    /** Block driver group. */
    124124    LOG_GROUP_DRV_BLOCK,
     125    /** Char driver group. */
     126    LOG_GROUP_DRV_CHAR,
    125127    /** Floppy media driver group. */
    126128    LOG_GROUP_DRV_FLOPPY,
     
    143145    /** Mouse Queue driver group. */
    144146    LOG_GROUP_DRV_MOUSE_QUEUE,
     147    /** Named Pipe stream driver group. */
     148    LOG_GROUP_DRV_NAMEDPIPE,
    145149    /** NAT network transport driver group */
    146150    LOG_GROUP_DRV_NAT,
     
    300304    "DRV_ACPI",     \
    301305    "DRV_BLOCK",    \
     306    "DRV_CHAR",     \
    302307    "DRV_FLOPPY",   \
    303308    "DRV_HOST_BASE", \
     
    310315    "DRV_KBD_QUEUE", \
    311316    "DRV_MOUSE_QUEUE", \
     317    "DRV_NAMEDPIPE", \
    312318    "DRV_NAT",      \
    313319    "DRV_RAW_IMAGE", \
  • trunk/include/VBox/pdm.h

    r628 r1476  
    7777#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
    7878    uint32_t                        Alignment0;
    79 #endif 
     79#endif
    8080} PDMQUEUEITEMCORE;
    8181
     
    438438    /** PDMIDISPLAYCONNECTOR    - The display connector interface.      (Up)    Coupled with PDMINTERFACE_DISPLAY_PORT. */
    439439    PDMINTERFACE_DISPLAY_CONNECTOR,
     440    /** PDMICHARPORT            - The char notify interface.            (Down)  Coupled with PDMINTERFACE_CHAR. */
     441    PDMINTERFACE_CHAR_PORT,
     442    /** PDMICHAR                - The char driver interface.            (Up)    Coupled with PDMINTERFACE_CHAR_PORT. */
     443    PDMINTERFACE_CHAR,
     444    /** PDMISTREAM              - The stream driver interface           (Up)    No coupling.
     445     * Used by a char driver to implement PDMINTERFACE_CHAR. */
     446    PDMINTERFACE_STREAM,
    440447    /** PDMIBLOCKPORT           - The block notify interface            (Down)  Coupled with PDMINTERFACE_BLOCK. */
    441448    PDMINTERFACE_BLOCK_PORT,
     
    893900typedef PDMIBLOCKPORT *PPDMIBLOCKPORT;
    894901
    895 
    896902/** Pointer to a block interface. */
    897903typedef struct PDMIBLOCK *PPDMIBLOCK;
    898904/**
    899905 * Block interface.
    900  * Pair with PDMIBLOCK.
     906 * Pair with PDMIBLOCKPORT.
    901907 */
    902908typedef struct PDMIBLOCK
     
    14231429
    14241430
     1431/** Pointer to a char port interface. */
     1432typedef struct PDMICHARPORT *PPDMICHARPORT;
     1433/**
     1434 * Char port interface.
     1435 * Pair with PDMICHAR.
     1436 */
     1437typedef struct PDMICHARPORT
     1438{
     1439    /**
     1440     * Deliver data read to the device/driver.
     1441     *
     1442     * @returns VBox status code.
     1443     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1444     * @param   pvBuf           Where the read bits are stored.
     1445     * @param   pcbRead         Number of bytes available for reading/having been read.
     1446     * @thread  Any thread.
     1447     */
     1448    DECLR3CALLBACKMEMBER(int, pfnNotifyRead,(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead));
     1449} PDMICHARPORT;
     1450
     1451/** Pointer to a char interface. */
     1452typedef struct PDMICHAR *PPDMICHAR;
     1453/**
     1454 * Char interface.
     1455 * Pair with PDMICHARPORT.
     1456 */
     1457typedef struct PDMICHAR
     1458{
     1459    /**
     1460     * Write bits.
     1461     *
     1462     * @returns VBox status code.
     1463     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1464     * @param   pvBuf           Where to store the write bits.
     1465     * @param   cbWrite         Number of bytes to write.
     1466     * @thread  Any thread.
     1467     */
     1468    DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMICHAR pInterface, const void *pvBuf, size_t cbWrite));
     1469} PDMICHAR;
     1470
     1471
     1472/** Pointer to a stream interface. */
     1473typedef struct PDMISTREAM *PPDMISTREAM;
     1474/**
     1475 * Stream interface.
     1476 * Makes up the fundation for PDMICHAR.
     1477 */
     1478typedef struct PDMISTREAM
     1479{
     1480    /**
     1481     * Read bits.
     1482     *
     1483     * @returns VBox status code.
     1484     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1485     * @param   pvBuf           Where to store the read bits.
     1486     * @param   cbRead          Number of bytes to read/bytes actually read.
     1487     * @thread  Any thread.
     1488     */
     1489    DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMISTREAM pInterface, void *pvBuf, size_t *cbRead));
     1490
     1491    /**
     1492     * Write bits.
     1493     *
     1494     * @returns VBox status code.
     1495     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1496     * @param   pvBuf           Where to store the write bits.
     1497     * @param   cbWrite         Number of bytes to write/bytes actually written.
     1498     * @thread  Any thread.
     1499     */
     1500    DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMISTREAM pInterface, const void *pvBuf, size_t *cbWrite));
     1501} PDMISTREAM;
     1502
     1503
    14251504/** ACPI power source identifier */
    14261505typedef enum PDMACPIPOWERSOURCE
     
    14971576     */
    14981577    DECLR3CALLBACKMEMBER(int, pfnQueryBatteryStatus,(PPDMIACPICONNECTOR, bool *pfPresent, PPDMACPIBATCAPACITY penmRemainingCapacity,
    1499                                                      PPDMACPIBATSTATE penmBatteryState, uint32_t *pu32PresentRate));
     1578                PPDMACPIBATSTATE penmBatteryState, uint32_t *pu32PresentRate));
    15001579} PDMIACPICONNECTOR;
    15011580
     
    15671646     */
    15681647    DECLR3CALLBACKMEMBER(int, pfnSetCredentials,(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
    1569                                                  const char *pszPassword, const char *pszDomain,
    1570                                                  uint32_t fFlags));
     1648                const char *pszPassword, const char *pszDomain,
     1649                uint32_t fFlags));
    15711650
    15721651    /**
     
    21342213 * @returns VBox status.
    21352214 * @param   pDrvIns     The driver instance data.
    2136  *                      If the registration structure is needed, pDrvIns->pDrvReg points to it.
    2137  * @param   pCfgHandle  Configuration node handle for the driver. Use this to obtain the configuration
    2138  *                      of the driver instance. It's also found in pDrvIns->pCfgHandle it's expected
    2139  *                      to be used primarily in this function.
     2215 *                      If the registration structure is needed,
     2216 *                      pDrvIns->pDrvReg points to it.
     2217 * @param   pCfgHandle  Configuration node handle for the driver. Use this to
     2218 *                      obtain the configuration of the driver instance. It's
     2219 *                      also found in pDrvIns->pCfgHandle as it's expected to
     2220 *                      be used frequently in this function.
    21402221 */
    21412222typedef DECLCALLBACK(int)   FNPDMDRVCONSTRUCT(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle);
     
    21462227 * Destruct a driver instance.
    21472228 *
    2148  * Most VM resources are freed by the VM. This callback is provided so that any non-VM
    2149  * resources can be freed correctly.
     2229 * Most VM resources are freed by the VM. This callback is provided so that
     2230 * any non-VM resources can be freed correctly.
    21502231 *
    21512232 * @param   pDrvIns     The driver instance data.
     
    23382419/** ISCSI Transport related driver. */
    23392420#define PDM_DRVREG_CLASS_ISCSITRANSPORT BIT(12)
     2421/** Char driver. */
     2422#define PDM_DRVREG_CLASS_CHAR           BIT(13)
     2423/** Stream driver. */
     2424#define PDM_DRVREG_CLASS_STREAM         BIT(14)
    23402425/** @} */
    23412426
     
    31223207/** ACPI. */
    31233208#define PDM_DEVREG_CLASS_ACPI           BIT(15)
    3124 /** Serial Porst */
    3125 #define PDM_DEVREG_CLASS_SERIAL_PORT    BIT(16)
     3209/** Serial controller device. */
     3210#define PDM_DEVREG_CLASS_SERIAL         BIT(16)
    31263211/** @} */
    31273212
     
    66916776
    66926777/**
    6693  * Serivce a VMMCALLHOST_PDM_LOCK call.
     6778 * Service a VMMCALLHOST_PDM_LOCK call.
    66946779 *
    66956780 * @returns VBox status code.
  • trunk/src/VBox/Devices/Builtins.cpp

    r1458 r1476  
    204204#endif
    205205
     206    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvChar);
     207    if (VBOX_FAILURE(rc))
     208        return rc;
     209    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvNamedPipe);
     210    if (VBOX_FAILURE(rc))
     211        return rc;
     212
    206213    return VINF_SUCCESS;
    207214}
  • trunk/src/VBox/Devices/Builtins.h

    r240 r1476  
    7575extern const PDMDRVREG g_DrvACPI;
    7676extern const PDMDRVREG g_DrvVUSBRootHub;
     77extern const PDMDRVREG g_DrvChar;
     78extern const PDMDRVREG g_DrvNamedPipe;
    7779
    7880__END_DECLS
  • trunk/src/VBox/Devices/Serial/serial.c

    r1031 r1476  
    6161#include <iprt/uuid.h>
    6262#include <iprt/string.h>
     63#include <iprt/semaphore.h>
    6364
    6465#include "Builtins.h"
    6566#include "../vl_vbox.h"
    6667
    67 #define VBOX_SERIAL_PCI
     68#undef VBOX_SERIAL_PCI /* The PCI variant has lots of problems: wrong IRQ line and wrong IO base assigned. */
    6869
    6970#ifdef VBOX_SERIAL_PCI
     
    148149    PCIDEVICE dev;
    149150#endif /* VBOX_SERIAL_PCI */
    150     /* Be careful with pointers in the structure; load just gets the whole structure from the saved state */
    151151    PPDMDEVINS pDevIns;
    152 #if 0
    153     PDMICHAR pDevChar;
    154 #endif
     152    PDMIBASE IBase;
     153    PDMICHARPORT ICharPort;
     154    PPDMIBASE pDrvBase;
     155    PPDMICHAR pDrvChar;
     156
     157    RTSEMEVENT ReceiveSem;
    155158#else /* !VBOX */
    156159    CharDriverState *chr;
     
    167170#define PCIDEV_2_SERIALSTATE(pPciDev) ( (SerialState *)((uintptr_t)(pPciDev) - RT_OFFSETOF(SerialState, dev)) )
    168171#endif /* VBOX_SERIAL_PCI */
     172#define PDMIBASE_2_SERIALSTATE(pInstance) ( (SerialState *)((uintptr_t)(pInterface) - RT_OFFSETOF(SerialState, IBase)) )
     173#define PDMICHARPORT_2_SERIALSTATE(pInstance) ( (SerialState *)((uintptr_t)(pInterface) - RT_OFFSETOF(SerialState, ICharPort)) )
    169174#endif /* VBOX */
    170175
     
    180185    if (s->iir != UART_IIR_NO_INT) {
    181186#ifdef VBOX
    182         s->pDevIns->pDevHlp->pfnISASetIrq (s->pDevIns, s->irq, 1);
     187#ifdef VBOX_SERIAL_PCI
     188        PDMDevHlpPCISetIrqNoWait(s->pDevIns, 0, 1);
     189#else /* !VBOX_SERIAL_PCI */
     190        PDMDevHlpISASetIrqNoWait(s->pDevIns, s->irq, 1);
     191#endif /* !VBOX_SERIAL_PCI */
    183192#else /* !VBOX */
    184193        s->set_irq(s->irq_opaque, s->irq, 1);
     
    186195    } else {
    187196#ifdef VBOX
    188         s->pDevIns->pDevHlp->pfnISASetIrq (s->pDevIns, s->irq, 0);
     197#ifdef VBOX_SERIAL_PCI
     198        PDMDevHlpPCISetIrqNoWait(s->pDevIns, 0, 0);
     199#else /* !VBOX_SERIAL_PCI */
     200        PDMDevHlpISASetIrqNoWait(s->pDevIns, s->irq, 0);
     201#endif /* !VBOX_SERIAL_PCI */
    189202#else /* !VBOX */
    190203        s->set_irq(s->irq_opaque, s->irq, 0);
     
    248261            ch = val;
    249262#ifdef VBOX
    250 #if 0
     263            /** @todo implement backpressure for writing (don't set interrupt
     264             * bits/line until the character is actually written). This way
     265             * EMT wouldn't block for writes taking longer than normal. */
    251266            if (s->pDrvChar)
    252267            {
     
    254269                AssertRC(rc);
    255270            }
    256 #endif
    257271#else /* !VBOX */
    258272            qemu_chr_write(s->chr, &ch, 1);
     
    321335            s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
    322336            serial_update_irq(s);
     337#ifdef VBOX
     338            {
     339                int rc = RTSemEventSignal(s->ReceiveSem);
     340                AssertRC(rc);
     341            }
     342#endif /* VBOX */
    323343        }
    324344        break;
     
    368388
    369389#ifdef VBOX
    370 /* Provide non-blocking functions to receive data from the host system. */
    371 
     390static DECLCALLBACK(int) serialNotifyRead(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead)
     391{
     392    SerialState *s = PDMICHARPORT_2_SERIALSTATE(pInterface);
     393    int rc;
     394
     395    Assert(*pcbRead != 0);
     396    rc = RTSemEventWait(s->ReceiveSem, 250);
     397    if (VBOX_FAILURE(rc))
     398        return rc;
     399    Assert(!(s->lsr & UART_LSR_DR));
     400    s->rbr = *(const char *)pvBuf;
     401    s->lsr |= UART_LSR_DR;
     402    serial_update_irq(s);
     403    *pcbRead = 1;
     404    return VINF_SUCCESS;
     405}
    372406#else /* !VBOX */
    373407static int serial_can_receive(SerialState *s)
     
    651685    /* Be careful with pointers in the structure; they are not preserved
    652686     * in the saved state. */
     687
     688    if (s->lsr & UART_LSR_DR)
     689    {
     690        int rc = RTSemEventSignal(s->ReceiveSem);
     691        AssertRC(rc);
     692    }
    653693    s->pDevIns = pDevIns;
    654694    return VINF_SUCCESS;
     
    668708
    669709    pData->base = (RTIOPORT)GCPhysAddress;
     710    LogRel(("Serial#%d: mapping I/O at %#06x\n", pData->pDevIns->iInstance, pData->base));
    670711
    671712    /*
    672713     * Register our port IO handlers.
    673714     */
    674     rc = pPciDev->pDevIns->pDevHlp->pfnIOPortRegister(pPciDev->pDevIns, (RTIOPORT)GCPhysAddress, 8, (void *)pData,
    675                                                       serial_io_write, serial_io_read, NULL, NULL, "SERIAL");
     715    rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns, (RTIOPORT)GCPhysAddress, 8, (void *)pData,
     716                                 serial_io_write, serial_io_read, NULL, NULL, "SERIAL");
    676717    AssertRC(rc);
    677718    return rc;
     
    679720
    680721#endif /* VBOX_SERIAL_PCI */
     722
     723
     724/** @copyfrom PIBASE::pfnqueryInterface */
     725static DECLCALLBACK(void *) serialQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
     726{
     727    SerialState *pData = PDMIBASE_2_SERIALSTATE(pInterface);
     728    switch (enmInterface)
     729    {
     730        case PDMINTERFACE_BASE:
     731            return &pData->IBase;
     732        case PDMINTERFACE_CHAR_PORT:
     733            return &pData->ICharPort;
     734        default:
     735            return NULL;
     736    }
     737}
     738
    681739
    682740/**
     
    702760    uint8_t        irq_lvl;
    703761
    704     Assert(iInstance < 2);
     762    Assert(iInstance < 4);
    705763
    706764    s->pDevIns = pDevIns;
     
    712770    }
    713771
     772    /* IBase */
     773    s->IBase.pfnQueryInterface = serialQueryInterface;
     774
     775    /* ICharPort */
     776    s->ICharPort.pfnNotifyRead = serialNotifyRead;
     777
     778    rc = RTSemEventCreate(&s->ReceiveSem);
     779    AssertRC(rc);
    714780
    715781/** @todo r=bird: Check for VERR_CFGM_VALUE_NOT_FOUND and provide sensible defaults.
     
    745811    s->dev.config[0x3c] = irq_lvl; /* preconfigure IRQ number (0 = autoconfig)*/
    746812    s->dev.config[0x3d] = 1;    /* interrupt pin 0 */
    747     rc = pDevIns->pDevHlp->pfnPCIRegister(pDevIns, &s->dev);
     813    rc = PDMDevHlpPCIRegister(pDevIns, &s->dev);
    748814    if (VBOX_FAILURE(rc))
    749815        return rc;
     
    751817     * Register the PCI I/O ports.
    752818     */
    753     rc = pDevIns->pDevHlp->pfnPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, serialIOPortRegionMap);
     819    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, serialIOPortRegionMap);
    754820    if (VBOX_FAILURE(rc))
    755821        return rc;
    756822#else /* !VBOX_SERIAL_PCI */
    757823    s->base = io_base;
    758     rc = pDevIns->pDevHlp->pfnIOPortRegister (
    759         pDevIns,
    760         io_base,
    761         8,
    762         s,
    763         serial_io_write,
    764         serial_io_read,
    765         NULL, NULL,
    766         "SERIAL"
    767         );
     824    rc = PDMDevHlpIOPortRegister(pDevIns, io_base, 8, s,
     825                                 serial_io_write, serial_io_read,
     826                                 NULL, NULL, "SERIAL");
    768827    if (VBOX_FAILURE (rc)) {
    769828        return rc;
     
    771830#endif /* !VBOX_SERIAL_PCI */
    772831
    773     rc = pDevIns->pDevHlp->pfnSSMRegister (
     832    /* Attach the char driver and get the interfaces. For now no run-time
     833     * changes are supported. */
     834    rc = PDMDevHlpDriverAttach(pDevIns, 0, &s->IBase, &s->pDrvBase, "Serial Char");
     835    if (VBOX_SUCCESS(rc))
     836    {
     837        s->pDrvChar = (PDMICHAR *)s->pDrvBase->pfnQueryInterface(s->pDrvBase, PDMINTERFACE_CHAR);
     838        if (!s->pDrvChar)
     839        {
     840            AssertMsgFailed(("Configuration error: instance %d has no char interface!\n", iInstance));
     841            return VERR_PDM_MISSING_INTERFACE;
     842        }
     843        /** @todo provide read notification interface!!!! */
     844    }
     845    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     846    {
     847        s->pDrvBase = NULL;
     848        s->pDrvChar = NULL;
     849        LogRel(("Serial%d: no unit\n", iInstance));
     850    }
     851    else
     852    {
     853        AssertMsgFailed(("Serial%d: Failed to attach to char driver. rc=%Vrc\n", iInstance, rc));
     854        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     855                                   N_("Serial device %d cannot attach to char driver\n"), iInstance);
     856    }
     857
     858    rc = PDMDevHlpSSMRegister (
    774859        pDevIns,                /* pDevIns */
    775860        pDevIns->pDevReg->szDeviceName, /* pszName */
     
    808893    PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT,
    809894    /* fClass */
    810     PDM_DEVREG_CLASS_SERIAL_PORT,
     895    PDM_DEVREG_CLASS_SERIAL,
    811896    /* cMaxInstances */
    812897    1,
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