VirtualBox

儲存庫 vbox 的更動 81891


忽略:
時間撮記:
2019-11-16 上午01:43:54 (5 年 以前)
作者:
vboxsync
訊息:

DevOxPcie958: Converting to new PDM device style. bugref:9218

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Devices/Serial/DevOxPcie958.cpp

    r81591 r81891  
    107107    /** Pointer to the device instance - RC ptr. */
    108108    PPDMDEVINSRC                    pDevInsRC;
    109     /** Flag whether R0 is enabled. */
    110     bool                            fR0Enabled;
    111     /** Flag whether RC is enabled. */
    112     bool                            fRCEnabled;
    113     /** Alignment. */
    114     bool                            afAlignment[2];
     109    uint32_t                        u32Alignment;
    115110    /** UART global IRQ status. */
    116111    volatile uint32_t               u32RegIrqStsGlob;
     
    123118    /** MMIO Base address. */
    124119    RTGCPHYS                        GCPhysMMIO;
     120    /** Handle to the MMIO region (PCI region \#0). */
     121    IOMMMIOHANDLE                   hMmio;
    125122    /** The UARTs. */
    126123    OX958UART                       aUarts[OX958_UARTS_MAX];
    127 
    128124} DEVOX958;
    129125/** Pointer to an OXPCIe958 device instance. */
     
    138134 *
    139135 * @returns nothing.
     136 * @param   pDevIns             The device instance.
    140137 * @param   pThis               The OXPCIe958 device instance.
    141138 */
    142 static void ox958IrqUpdate(PDEVOX958 pThis)
     139static void ox958IrqUpdate(PPDMDEVINS pDevIns, PDEVOX958 pThis)
    143140{
    144141    uint32_t u32IrqSts = ASMAtomicReadU32(&pThis->u32RegIrqStsGlob);
     
    146143
    147144    if (u32IrqSts & u32IrqEn)
    148         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_HIGH);
     145        PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH);
    149146    else
    150         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_LOW);
     147        PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
    151148}
    152149
     
    155152 * Performs a register read from the given UART.
    156153 *
    157  * @returns nothing.
     154 * @returns Strict VBox status code.
    158155 * @param   pThis               The OXPCIe958 device instance.
    159156 * @param   pUart               The UART accessed.
     
    162159 * @param   cb                  Number of bytes to read.
    163160 */
    164 static int ox958UartRegRead(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, void *pv, unsigned cb)
    165 {
    166     int rc = VINF_SUCCESS;
     161static VBOXSTRICTRC ox958UartRegRead(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, void *pv, unsigned cb)
     162{
     163    VBOXSTRICTRC rc;
    167164    RT_NOREF(pThis);
    168165
     
    170167    {
    171168        /* Access to the DMA registers. */
     169        rc = VINF_SUCCESS;
    172170    }
    173171    else /* Access UART registers. */
     
    181179 * Performs a register write to the given UART.
    182180 *
    183  * @returns nothing.
     181 * @returns Strict VBox status code.
    184182 * @param   pThis               The OXPCIe958 device instance.
    185183 * @param   pUart               The UART accessed.
     
    188186 * @param   cb                  Number of bytes to write.
    189187 */
    190 static int ox958UartRegWrite(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, const void *pv, unsigned cb)
    191 {
    192     int rc = VINF_SUCCESS;
     188static VBOXSTRICTRC ox958UartRegWrite(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, const void *pv, unsigned cb)
     189{
     190    VBOXSTRICTRC rc;
    193191    RT_NOREF(pThis);
    194192
     
    196194    {
    197195        /* Access to the DMA registers. */
     196        rc = VINF_SUCCESS;
    198197    }
    199198    else /* Access UART registers. */
     
    222221    else
    223222        ASMAtomicAndU32(&pThis->u32RegIrqStsGlob, ~RT_BIT_32(iLUN));
    224     ox958IrqUpdate(pThis);
    225 }
    226 
    227 
    228 /**
    229  * Read a MMIO register.
    230  *
    231  * @returns VBox status code suitable for scheduling.
    232  * @param   pDevIns     The device instance.
    233  * @param   pvUser      A user argument (ignored).
    234  * @param   GCPhysAddr  The physical address being written to. (This is within our MMIO memory range.)
    235  * @param   pv          Where to put the data we read.
    236  * @param   cb          The size of the read.
    237  */
    238 PDMBOTHCBDECL(int) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    239 {
    240     PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
    241     uint32_t  offReg = (GCPhysAddr - pThis->GCPhysMMIO);
    242     int       rc = VINF_SUCCESS;
    243     RT_NOREF(pThis, pvUser);
    244 
    245     if (offReg < OX958_REG_UART_REGION_OFFSET)
     223    ox958IrqUpdate(pDevIns, pThis);
     224}
     225
     226
     227/**
     228 * @callback_method_impl{FNIOMMMIONEWREAD}
     229 */
     230static DECLCALLBACK(VBOXSTRICTRC) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
     231{
     232    PDEVOX958    pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
     233    VBOXSTRICTRC rc    = VINF_SUCCESS;
     234    RT_NOREF(pvUser);
     235
     236    if (off < OX958_REG_UART_REGION_OFFSET)
    246237    {
    247238        uint32_t *pu32 = (uint32_t *)pv;
    248239        Assert(cb == 4);
    249240
    250         switch (offReg)
     241        switch ((uint32_t)off)
    251242        {
    252243            case OX958_REG_CC_REV_ID:
     
    278269    {
    279270        /* Figure out the UART accessed from the offset. */
    280         offReg -= OX958_REG_UART_REGION_OFFSET;
    281         uint32_t iUart = offReg / OX958_REG_UART_REGION_SIZE;
    282         uint32_t offUartReg = offReg % OX958_REG_UART_REGION_SIZE;
    283         if (iUart < pThis->cUarts)
     271        off -= OX958_REG_UART_REGION_OFFSET;
     272        uint32_t iUart      = (uint32_t)off / OX958_REG_UART_REGION_SIZE;
     273        uint32_t offUartReg = (uint32_t)off % OX958_REG_UART_REGION_SIZE;
     274        if (iUart < RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)))
    284275        {
    285276            POX958UART pUart = &pThis->aUarts[iUart];
     
    297288
    298289/**
    299  * Write to a MMIO register.
    300  *
    301  * @returns VBox status code suitable for scheduling.
    302  * @param   pDevIns     The device instance.
    303  * @param   pvUser      A user argument (ignored).
    304  * @param   GCPhysAddr  The physical address being written to. (This is within our MMIO memory range.)
    305  * @param   pv          Pointer to the data being written.
    306  * @param   cb          The size of the data being written.
    307  */
    308 PDMBOTHCBDECL(int) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    309 {
    310     PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
    311     uint32_t  offReg = (GCPhysAddr - pThis->GCPhysMMIO);
    312     int       rc = VINF_SUCCESS;
     290 * @callback_method_impl{FNIOMMMIONEWWRITE}
     291 */
     292static DECLCALLBACK(VBOXSTRICTRC) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
     293{
     294    PDEVOX958    pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
     295    VBOXSTRICTRC rc    = VINF_SUCCESS;
    313296    RT_NOREF1(pvUser);
    314297
    315     if (offReg < OX958_REG_UART_REGION_OFFSET)
     298    if (off < OX958_REG_UART_REGION_OFFSET)
    316299    {
    317300        const uint32_t u32 = *(const uint32_t *)pv;
    318301        Assert(cb == 4);
    319302
    320         switch (offReg)
     303        switch ((uint32_t)off)
    321304        {
    322305            case OX958_REG_UART_IRQ_ENABLE:
    323306                ASMAtomicOrU32(&pThis->u32RegIrqEnGlob, u32);
    324                 ox958IrqUpdate(pThis);
     307                ox958IrqUpdate(pDevIns, pThis);
    325308                break;
    326309            case OX958_REG_UART_IRQ_DISABLE:
    327310                ASMAtomicAndU32(&pThis->u32RegIrqEnGlob, ~u32);
    328                 ox958IrqUpdate(pThis);
     311                ox958IrqUpdate(pDevIns, pThis);
    329312                break;
    330313            case OX958_REG_UART_WAKE_IRQ_ENABLE:
     
    338321            case OX958_REG_UART_CNT:     /* Readonly */
    339322            default:
    340                 rc = VINF_SUCCESS;
     323                break;
    341324        }
    342325    }
     
    344327    {
    345328        /* Figure out the UART accessed from the offset. */
    346         offReg -= OX958_REG_UART_REGION_OFFSET;
    347         uint32_t iUart = offReg / OX958_REG_UART_REGION_SIZE;
    348         uint32_t offUartReg = offReg % OX958_REG_UART_REGION_SIZE;
    349         if (iUart < pThis->cUarts)
     329        off -= OX958_REG_UART_REGION_OFFSET;
     330        uint32_t iUart      = (uint32_t)off / OX958_REG_UART_REGION_SIZE;
     331        uint32_t offUartReg = (uint32_t)off % OX958_REG_UART_REGION_SIZE;
     332        if (iUart < RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)))
    350333        {
    351334            POX958UART pUart = &pThis->aUarts[iUart];
     
    361344
    362345#ifdef IN_RING3
    363 /**
    364  * @callback_method_impl{FNPCIIOREGIONMAP}
    365  */
    366 static DECLCALLBACK(int) ox958R3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    367                                     RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
    368 {
    369     PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
    370     int       rc    = VINF_SUCCESS;
    371     RT_NOREF(pPciDev, enmType);
    372     Assert(pPciDev == pDevIns->apPciDevs[0]);
    373 
    374     if (iRegion == 0)
    375     {
    376         Assert(enmType == PCI_ADDRESS_SPACE_MEM);
    377 
    378         rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    379                                    IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    380                                    ox958MmioWrite, ox958MmioRead, "OxPCIe958");
    381         if (RT_FAILURE(rc))
    382             return rc;
    383 
    384         /* Enable (or not) RC/R0 support. */
    385         if (pThis->fRCEnabled)
    386         {
    387             rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
    388                                          "ox958MmioWrite", "ox958MmioRead");
    389             if (RT_FAILURE(rc))
    390                 return rc;
    391         }
    392 
    393         if (pThis->fR0Enabled)
    394         {
    395             rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,
    396                                          "ox958MmioWrite", "ox958MmioRead");
    397             if (RT_FAILURE(rc))
    398                 return rc;
    399         }
    400 
    401         pThis->GCPhysMMIO = GCPhysAddress;
    402     }
    403 
    404     return VINF_SUCCESS;
    405 }
    406 
    407346
    408347/** @interface_method_impl{PDMDEVREG,pfnDetach} */
     
    425364    RT_NOREF(fFlags);
    426365
    427     if (iLUN >= pThis->cUarts)
     366    if (iLUN >= RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)))
    428367        return VERR_PDM_LUN_NOT_FOUND;
    429368
     
    441380    pThis->u32RegIrqEnWake  = 0x00;
    442381
    443     for (uint32_t i = 0; i < pThis->cUarts; i++)
     382    uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts));
     383    for (uint32_t i = 0; i < cUarts; i++)
    444384        uartR3Reset(&pThis->aUarts[i].UartCore);
    445385}
     
    453393
    454394    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    455     for (uint32_t i = 0; i < pThis->cUarts; i++)
     395    uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts));
     396    for (uint32_t i = 0; i < cUarts; i++)
    456397        uartR3Relocate(&pThis->aUarts[i].UartCore, offDelta);
    457398}
     
    461402static DECLCALLBACK(int) ox958R3Destruct(PPDMDEVINS pDevIns)
    462403{
     404    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
    463405    PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
    464     PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
    465 
    466     for (uint32_t i = 0; i < pThis->cUarts; i++)
     406
     407    uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts));
     408    for (uint32_t i = 0; i < cUarts; i++)
    467409        uartR3Destruct(&pThis->aUarts[i].UartCore);
    468410
     
    474416static DECLCALLBACK(int) ox958R3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
    475417{
     418    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    476419    RT_NOREF(iInstance);
    477     PDEVOX958   pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
    478     bool        fRCEnabled = true;
    479     bool        fR0Enabled = true;
    480     bool        fMsiXSupported = false;
    481     int         rc;
    482 
    483     PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     420    PDEVOX958       pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
     421    PCPDMDEVHLPR3   pHlp  = pDevIns->pHlpR3;
     422    bool            fMsiXSupported = false;
     423    int             rc;
     424
     425    /*
     426     * Init instance data.
     427     */
     428    pThis->pDevInsR3             = pDevIns;
     429    pThis->pDevInsR0             = PDMDEVINS_2_R0PTR(pDevIns);
     430    pThis->pDevInsRC             = PDMDEVINS_2_RCPTR(pDevIns);
     431
     432    rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
     433    AssertRCReturn(rc, rc);
    484434
    485435    /*
    486436     * Validate and read configuration.
    487437     */
    488     if (!CFGMR3AreValuesValid(pCfg, "RCEnabled\0"
    489                                     "R0Enabled\0"
    490                                     "MsiXSupported\0"
    491                                     "UartCount\0"))
    492         return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
    493                                 N_("OXPCIe958 configuration error: Unknown option specified"));
    494 
    495     rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &fRCEnabled, true);
     438    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "MsiXSupported|UartCount", "");
     439
     440    rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true);
    496441    if (RT_FAILURE(rc))
    497         return PDMDEV_SET_ERROR(pDevIns, rc,
    498                                 N_("OXPCIe958 configuration error: Failed to read \"RCEnabled\" as boolean"));
    499 
    500     rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
     442        return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean"));
     443
     444    rc = pHlp->pfnCFGMQueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX);
    501445    if (RT_FAILURE(rc))
    502         return PDMDEV_SET_ERROR(pDevIns, rc,
    503                                 N_("OXPCIe958 configuration error: failed to read \"R0Enabled\" as boolean"));
    504 
    505     rc = CFGMR3QueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true);
    506     if (RT_FAILURE(rc))
    507         return PDMDEV_SET_ERROR(pDevIns, rc,
    508                                 N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean"));
    509 
    510     rc = CFGMR3QueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX);
    511     if (RT_FAILURE(rc))
    512         return PDMDEV_SET_ERROR(pDevIns, rc,
    513                                 N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer"));
     446        return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer"));
    514447
    515448    if (!pThis->cUarts || pThis->cUarts > OX958_UARTS_MAX)
     
    519452
    520453    /*
    521      * Init instance data.
     454     * Fill PCI config space.
    522455     */
    523     pThis->fR0Enabled            = fR0Enabled;
    524     pThis->fRCEnabled            = fRCEnabled;
    525     pThis->pDevInsR3             = pDevIns;
    526     pThis->pDevInsR0             = PDMDEVINS_2_R0PTR(pDevIns);
    527     pThis->pDevInsRC             = PDMDEVINS_2_RCPTR(pDevIns);
    528 
    529     /* Fill PCI config space. */
    530456    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
    531457    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     
    534460    PDMPciDevSetDeviceId(pPciDev,           OX958_PCI_DEVICE_ID);
    535461    PDMPciDevSetCommand(pPciDev,            0x0000);
    536 #ifdef VBOX_WITH_MSI_DEVICES
     462# ifdef VBOX_WITH_MSI_DEVICES
    537463    PDMPciDevSetStatus(pPciDev,             VBOX_PCI_STATUS_CAP_LIST);
    538464    PDMPciDevSetCapabilityList(pPciDev,     OX958_PCI_MSI_CAP_OFS);
    539 #else
     465# else
    540466    PDMPciDevSetCapabilityList(pPciDev,     0x70);
    541 #endif
     467# endif
    542468    PDMPciDevSetRevisionId(pPciDev,         0x00);
    543469    PDMPciDevSetClassBase(pPciDev,          0x07); /* Communication controller. */
     
    552478    PDMPciDevSetInterruptPin(pPciDev,       0x01);
    553479    /** @todo More Capabilities. */
    554 
    555     rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
    556     if (RT_FAILURE(rc))
    557         return rc;
    558480
    559481    /*
     
    564486        return rc;
    565487
    566 #ifdef VBOX_WITH_MSI_DEVICES
     488# ifdef VBOX_WITH_MSI_DEVICES
    567489    PDMMSIREG MsiReg;
    568490    RT_ZERO(MsiReg);
     
    584506        /* That's OK, we can work without MSI */
    585507    }
    586 #endif
    587 
    588     rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, _16K, PCI_ADDRESS_SPACE_MEM, ox958R3Map);
    589     if (RT_FAILURE(rc))
    590         return rc;
     508# endif
     509
     510    rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 0 /*iPciRegion*/, _16K, PCI_ADDRESS_SPACE_MEM,
     511                                        ox958MmioWrite, ox958MmioRead, NULL /*pvUser*/,
     512                                        IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
     513                                        "OxPCIe958", &pThis->hMmio);
     514    AssertRCReturn(rc, rc);
    591515
    592516    /** @todo This dynamic symbol resolving will be reworked later! */
     
    595519    RTRCPTR pfnSerialIrqReqRC = NIL_RTRCPTR;
    596520
    597 #ifdef VBOX_WITH_RAW_MODE_KEEP
    598     if (   fRCEnabled
     521# ifdef VBOX_WITH_RAW_MODE_KEEP
     522    if (   pDevIns->fRCEnabled
    599523        && VM_IS_RAW_MODE_ENABLED(pVM))
    600524    {
     
    603527            return rc;
    604528    }
    605 #endif
    606 
    607     if (fR0Enabled)
     529# endif
     530
     531    if (pDevIns->fR0Enabled)
    608532    {
    609533        rc = PDMR3LdrGetSymbolR0(pVM, pDevIns->pReg->pszR0Mod, "ox958IrqReq", &pfnSerialIrqReqR0);
     
    625549}
    626550
    627 #endif /* IN_RING3 */
     551#else  /* !IN_RING3 */
     552
     553/**
     554 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
     555 */
     556static DECLCALLBACK(int) ox958RZConstruct(PPDMDEVINS pDevIns)
     557{
     558    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     559    PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
     560
     561    int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
     562    AssertRCReturn(rc, rc);
     563
     564    rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, ox958MmioWrite, ox958MmioRead, NULL /*pvUser*/);
     565    AssertRCReturn(rc, rc);
     566
     567    return VINF_SUCCESS;
     568}
     569
     570#endif /* !IN_RING3 */
    628571
    629572
     
    670613#elif defined(IN_RING0)
    671614    /* .pfnEarlyConstruct = */      NULL,
    672     /* .pfnConstruct = */           NULL,
     615    /* .pfnConstruct = */           ox958RZConstruct,
    673616    /* .pfnDestruct = */            NULL,
    674617    /* .pfnFinalDestruct = */       NULL,
     
    683626    /* .pfnReserved7 = */           NULL,
    684627#elif defined(IN_RC)
    685     /* .pfnConstruct = */           NULL,
     628    /* .pfnConstruct = */           ox958RZConstruct,
    686629    /* .pfnReserved0 = */           NULL,
    687630    /* .pfnReserved1 = */           NULL,
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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