コード例 #1
0
void
MandatorySMART_r10b::IssueGetLogPgCmdLessDwords(SharedASQPtr asq,
    SharedACQPtr acq, SharedGetLogPagePtr getLogPgCmd,
    SharedMemBufferPtr getLogPageMem)
{
    string work;

    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);

    for (uint32_t numd = 1; numd <= SMART_HEALTH_NUMD; numd++) {
        LOG_NRM("Issue get log page for smart info with NUMD = %d", numd);
        getLogPageMem->Init(GetLogPage::SMART_DATA_SIZE, true);
        getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
        getLogPgCmd->SetNUMD(numd - 1); // 0-based

        work = str(boost::format("Smart.NSID.%Xh.NUMD.%d") %
            getLogPgCmd->GetNSID() % numd);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true);

        LOG_NRM("Verify the buffer's non-retrieved = 0x00");
        SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer();
        uint32_t offset = (numd * 4);
        uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset;
        for (; offset < GetLogPage::SMART_DATA_SIZE; offset++) {
            LOG_NRM("Verify data at offset = 0x%X", offset);
            if (*cmdPayloadBuff != 0x0) {
                throw FrmwkEx(HERE, "Invalid data at buffer offset = 0x%08X, "
                    "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff);
            }
            cmdPayloadBuff++;
        }
    }
}
コード例 #2
0
ファイル: prp1PRP2_r10b.cpp プロジェクト: bsvinay/tnvme
void
PRP1PRP2_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // Lookup objs which were created in a prior test within group
    string work;
    uint64_t i;
    
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());

    LOG_NRM("Get log page to request firmware slot information");
    getLogPgCmd->SetNUMD(PRP1_ONLY_NUMD - 1); // 0-based
    getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID);
    getLogPgCmd->SetNSID(0xFFFFFFFF);    
    
    LOG_NRM("Set the offset into the buffer at 0x%04X", BUFFER_OFFSET);
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE,
        BUFFER_OFFSET, true);
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "prp1prp2", true);
}
コード例 #3
0
void
UnsupportRrvdFields_r10b::ReadLogPage(SharedACQPtr &acq, SharedASQPtr &asq,
    uint8_t logId)
{
    string work;

    LOG_NRM("Reading log page with LID = %d to clear the event mask", logId);
    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint8_t X = idCtrlrStruct->GetValue(IDCTRLRCAP_ELPE) + 1;
    LOG_NRM("Identify controller ELPE = %d (1-based)", X);

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());

    LOG_NRM("Create memory buffer for log page to request error information");
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);

    LOG_NRM("Get log page to request error information logId = %d", logId);
    getLogPgCmd->SetLID(logId);
    getLogPageMem->Init(GetLogPage::ERRINFO_DATA_SIZE * X, true);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
    getLogPgCmd->SetNUMD((GetLogPage::ERRINFO_DATA_SIZE * X / 4) - 1); //0-based

    work = str(boost::format("ErrorLog%d") % (uint32_t)logId);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, work, true);
}
コード例 #4
0
void
InvalidLogPageNVMSet_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    string work;
    // Lookup objs which were created in a prior test within group
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    send_64b_bitmask prpReq =
            (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);

    getLogPageMem->InitOffset1stPage(BUFFER_SIZE, 0, true);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
    getLogPgCmd->SetNUMD(NUMD - 1); // 0-based
    getLogPgCmd->SetNSID(0xFFFFFFFF);
    list<uint32_t> invalidLIDs = GetInvalidLIDs();
    for (list<uint32_t>::iterator invalidLID = invalidLIDs.begin();
        invalidLID != invalidLIDs.end(); invalidLID++) {
        LOG_NRM("Processing for invalid LID = 0x%04X", *invalidLID);
        getLogPgCmd->SetLID(*invalidLID);

        work = str(boost::format("invalidLID.%d") % *invalidLID);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true, CESTAT_INVAL_LOG_PAGE);
    }
}
コード例 #5
0
void
MandatoryErrInfo_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    string work;

    // Lookup objs which were created in a prior test within group
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint8_t X = idCtrlrStruct->GetValue(IDCTRLRCAP_ELPE) + 1;
    LOG_NRM("Identify controller ELPE = %d (1-based)", X);

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());

    LOG_NRM("Create memory buffer for log page to request error information");
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);

    LOG_NRM("Get log page to request error information");
    getLogPgCmd->SetLID(ERRINFO_LID);

    // loop for all log entries supported by controller
    for (uint32_t numd = ERRINFO_NUMD; numd <= (X * ERRINFO_NUMD);
        numd += ERRINFO_NUMD) {
        LOG_NRM("Issue Get log page cmd with NUMD = %d and log entries = %d",
            numd, (numd/ERRINFO_NUMD));

        getLogPageMem->Init(GetLogPage::ERRINFO_DATA_SIZE * X, true);
        getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
        getLogPgCmd->SetNUMD(numd - 1); // 0-based

        work = str(boost::format("logEnties%d") % (numd / ERRINFO_NUMD));
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true);

        // Verify the buffer's non-retrieved log entries = 0x00.
        SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer();
        uint32_t offset = (numd * 4);
        uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset;
        for (; offset < (X * GetLogPage::ERRINFO_DATA_SIZE); offset++) {
            LOG_NRM("Verify data at offset = 0x%X", offset);
            if (*cmdPayloadBuff != 0x0) {
                throw FrmwkEx(HERE, "Invalid data at buffer offset = 0x%08X, "
                    "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff);
            }
            cmdPayloadBuff++;
        }
    }
}
コード例 #6
0
void
UnsupportRsvdFields_r11b::ReadLogPage(SharedACQPtr &acq, SharedASQPtr &asq,
    uint8_t logId)
{
    string work;

    LOG_NRM("Reading log page with LID = %d to clear the event mask", logId);
    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint16_t elpeVal = idCtrlrStruct->GetValue(IDCTRLRCAP_ELPE) + 1;
    LOG_NRM("Identify controller ELPE = %d (1-based)", elpeVal);

    uint16_t totalBytes = elpeVal * GetLogPage::ERRINFO_DATA_SIZE;
    LOG_NRM("Total bytes available for error info log page: %d", totalBytes);
    uint8_t mps;
    if (!gCtrlrConfig->GetMPS(mps))
        throw FrmwkEx(HERE, "Failed to retrieve CC.MPS value");
    uint32_t twoPages = 2 * (1 << (mps + 12));
    LOG_NRM("Size of two memory pages (i.e. PRP1 & PRP2): %d bytes", twoPages);
    // PRP2 cannot be pointer to PRP list, so don't ask for more than 2 pages
    if (totalBytes > twoPages) {
        LOG_NRM("Can only utilize two memory pages; reducing total bytes");
        totalBytes = twoPages;
    }
    uint16_t totalDwords = totalBytes / 4;

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());

    LOG_NRM("Create memory buffer for log page to request error information");
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);

    LOG_NRM("Get log page to request error information logId = %d", logId);
    getLogPgCmd->SetLID(logId);
    getLogPageMem->Init(totalBytes, true);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
    getLogPgCmd->SetNUMD(totalDwords - 1); //0-based

    work = str(boost::format("ErrorLog%d") % (uint32_t)logId);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, work, true);
}
コード例 #7
0
void
MandatorySMART_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // Lookup objs which were created in a prior test within group
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint32_t nn = idCtrlrStruct->GetValue(IDCTRLRCAP_NN);
    if (nn == 0 )
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");
    uint8_t logPageAttr = (uint8_t)idCtrlrStruct->GetValue(IDCTRLRCAP_LPA);

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());

    getLogPgCmd->SetLID(GetLogPage::LOGID_SMART_HEALTH);
    getLogPgCmd->SetNSID(0xFFFFFFFF);

    LOG_NRM("Issue cmd multiple times such that NUMD loops X=[0...512]");
    IssueGetLogPgCmdLessDwords(asq, acq, getLogPgCmd, getLogPageMem);

    LOG_NRM("If SMART supported per namspc, Reissue cmd for valid NSID's");
    if (logPageAttr) {
        for (uint32_t i = 1; i <= nn; i++) {
            LOG_NRM("Issue Get log page cmd with NSID = %u", i);
            getLogPgCmd->SetNSID(i);
            IssueGetLogPgCmdLessDwords(asq, acq, getLogPgCmd, getLogPageMem);
        }
    }
}
コード例 #8
0
ファイル: numDIsAdhered_r10b.cpp プロジェクト: bsvinay/tnvme
void
NUMDIsAdhered_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // Lookup objs which were created in a prior test within group
    string work;
    uint64_t i;
    
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());

    LOG_NRM("Get log page to request firmware slot information");
    getLogPgCmd->SetNUMD(NUMDW_ADHERED - 1);  // 0-based
    getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID);
    getLogPgCmd->SetNSID(0xFFFFFFFF);
    
    LOG_NRM("Set the offset into the buffer at 0x%04X", BUFFER_OFFSET);
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE,
        BUFFER_OFFSET, true, BUFFER_INIT_VAL);
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "NUMD.adhered", true);

    LOG_NRM("Compare cmd buffer to verify the last half of buffer = 0xA5");
    SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer();
    uint16_t offset = (NUMDW_ADHERED * 4);
    uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset;
    for (; offset < (GetLogPage::FIRMSLOT_DATA_SIZE); offset++) {
        LOG_NRM("Verify data at offset = 0x%X", offset);
        if (*cmdPayloadBuff != BUFFER_INIT_VAL) {
            throw FrmwkEx(HERE, "NUMD not adhered at offset = 0x%08X, "
                "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff);
        }
        cmdPayloadBuff++;
    }
}
コード例 #9
0
void
UnsupportRrvdFields_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // Lookup objs which were created in a prior test within group
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());

    LOG_NRM("Get log page to request firmware slot information");
    getLogPgCmd->SetNUMD(PRP1_ONLY_NUMD - 1); // 0-based
    getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID);

    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE,
        BUFFER_OFFSET, true);
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);

    LOG_NRM("Issue GetLogPage cmd without setting reserved bits.");
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "rsvd.notset", true);

    LOG_NRM("Set all cmd's rsvd bits");
    uint32_t work = getLogPgCmd->GetDword(0);
    work |= 0x0000fc00;      // Set DW0_b15:10 bits
    getLogPgCmd->SetDword(work, 0);

    getLogPgCmd->SetDword(0xffffffff, 2);
    getLogPgCmd->SetDword(0xffffffff, 3);
    getLogPgCmd->SetDword(0xffffffff, 4);
    getLogPgCmd->SetDword(0xffffffff, 5);

    work = getLogPgCmd->GetDword(10);
    work |= 0xf0000000;      // Set DW10_b31:28 bits
    getLogPgCmd->SetDword(work, 10);

    getLogPgCmd->SetDword(0xffffffff, 11);
    getLogPgCmd->SetDword(0xffffffff, 12);
    getLogPgCmd->SetDword(0xffffffff, 13);
    getLogPgCmd->SetDword(0xffffffff, 14);
    getLogPgCmd->SetDword(0xffffffff, 15);

    LOG_NRM("Issue GetLogPage cmd after setting reserved bits.");
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "rsvd.set", true);

}
コード例 #10
0
void
InvalidNamspc_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    string work;
    uint64_t inc, i;

    // Lookup objs which were created in a prior test within group
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    send_64b_bitmask prpReq =
            (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);

    getLogPageMem->InitOffset1stPage(GetLogPage::SMART_DATA_SIZE, 0, true);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
    getLogPgCmd->SetLID(SMART_HEALTH_INFO_LID);
    getLogPgCmd->SetNUMD(SMART_NUMD - 1); // 0 - based

    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN);
    if (nn == 0 )
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");

    uint8_t logPageAttr = (uint8_t)idCtrlrStruct->GetValue(IDCTRLRCAP_LPA);
    // bits 7:1 are reserved, need bit 0
    uint8_t suppSmartPerNamspc = logPageAttr & 0x1;

    if(suppSmartPerNamspc > 0) {
    	LOG_NRM("IDCTRLRCAP_LPA bit0 is set. Per Namespace Smart Pages supported")
    }
    else {
    	LOG_NRM("IDCTRLRCAP_LPA bit0 is not set. Per Namespace Smart Pages is not supported")
    }

    // for all illegal nsid's verify get log page cmd.
    for (i = (nn + 1), inc = 1; i < 0xffffffff; i += (2 * inc), inc += 1327) {
        LOG_NRM("Issue Get log page cmd with illegal namspc ID = 0x%llX",
            (unsigned long long)i);
        getLogPgCmd->SetNSID(i);

        work = str(boost::format("namspc%d") % i);
        // Determine the status based on the per namespace mask bit.
        // While the 1.1+ spec requires the device to return invalid field
        //   the 1.0 spec does NOT require the device to return SUCCESS and
        //   a global log page no matter what value of NSID is provided
        // Instead only the global 0xFFFFFFFF NSID MUST be supported
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true, CESTAT_INVAL_NAMSPC);
    }

    // If per namespc smart log is supported, check all legal nn.
    if (suppSmartPerNamspc) {
        for (i = 1; i <= nn; i++) {
            LOG_NRM("Issue Get log page cmd with legal namspc ID = 0x%llX (per namespace smart log supported)",
                (unsigned long long)i);
            getLogPgCmd->SetNSID(i);

            work = str(boost::format("namspc%d") % i);
            // Determine the status based on the per namespace mask bit.
            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
                asq, acq, getLogPgCmd, work, true);
        }
    }

	// GetLogPage of NSID == 0 is not expected to pass when LPA bit 0 is not set
	// The only requirement is that 0xFFFFFFFF is supported, not that the NSID field
	//   is completely ignored and a global page is always returned...
    /*
    else {
        i = 0;
        getLogPgCmd->SetNSID(i);
        work = str(boost::format("namspc%d") % i);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true);
    }
    */

    // If name space is 0xffffffff, then we should get the global log info.
    i = 0xffffffff;
    getLogPgCmd->SetNSID(i);
    work = str(boost::format("namspc%d") % i);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, work, true);
}