VirtualBox

Changeset 1476

Show
Ignore:
Timestamp:
03/14/07 17:36:04 (2 years ago)
Author:
vboxsync
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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 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, 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy