Beispiel #1
0
void
PRP1PRP2_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */

    LOG_NRM("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("Determine if DUT has atleast one namespace support");
    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0)
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");

    LOG_NRM("Form identify namespace cmd and associate some buffer");
    SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify());
    idCmdNamSpc->SetCNS(false);
    idCmdNamSpc->SetNSID(1);

    SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer());
    idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE,
        PRP_BUFFER_OFFSET, true);

    LOG_NRM("Allow PRP1 and PRP2");
    send_64b_bitmask idPrpNamSpc =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, "prp1Prp2", true);
}
Test::RunType
UnsupportRsvdFields_r11b::RunnableCoreTest(bool preserve)
{
    ///////////////////////////////////////////////////////////////////////////
    // All code contained herein must never permanently modify the state or
    // configuration of the DUT. Permanence is defined as state or configuration
    // changes that will not be restored after a cold hard reset.
    ///////////////////////////////////////////////////////////////////////////

    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS);
    if ((oncs & ONCS_SUP_DSM_CMD) == 0) {
        LOG_NRM("Reporting not supoorted (oncs)%ld", oncs);
        return RUN_FALSE;
    }

    LOG_NRM("Reporting runnable (oncs)%ld", oncs);

    if (gCmdLine.rsvdfields == false)
        return RUN_FALSE;   // Optional rsvd fields test skipped.

    preserve = preserve;    // Suppress compiler error/warning
    return RUN_TRUE;        // This test is never destructive

}
Test::RunType
ReadWriteToUnacquiredReservation::RunnableCoreTest(bool preserve)
{
    ///////////////////////////////////////////////////////////////////////////
    // All code contained herein must never permanently modify the state or
    // configuration of the DUT. Permanence is defined as state or configuration
    // changes that will not be restored after a cold hard reset.
    ///////////////////////////////////////////////////////////////////////////

    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS);
    uint64_t mic = idCtrlrCap->GetValue(IDCTRLRCAP_MIC);
    if((mic & MIC_SUP_PCI_PORTS) == 0)
    {
        LOG_NRM("Reporting only one PCI port is supported (mic)%ld", mic);
        return RUN_FALSE;
    }
    else
    {
        if ((oncs & ONCS_SUP_RSRV) == 0)
        {
            LOG_NRM("Reporting Reservations not supported (oncs)%ld", oncs);
            return RUN_FALSE;
        }
    }
    preserve = preserve;    // Suppress compiler error/warning
    return RUN_TRUE;        // This test is never destructive
}
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);
}
void
UnsupportRsvdFields_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */

    LOG_NRM("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("Determine if DUT has atleast one namespace support");
    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0)
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");

    LOG_NRM("Form identify namespace cmd and associate some buffer");
    SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify());
    idCmdNamSpc->SetCNS(0);
    idCmdNamSpc->SetNSID(1);

    SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer());
    idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE,
        PRP_BUFFER_OFFSET, true);

    LOG_NRM("Allow PRP1 and PRP2");
    send_64b_bitmask idPrpNamSpc =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, "rsvdnone.set", true);

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

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

    work = idCmdNamSpc->GetDword(10);
    work |= 0xfffffffe;      // Set DW10_b31:1 bits
    idCmdNamSpc->SetDword(work, 10);

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

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, "rsvdall.set", true);
}
void
LBAOutOfRangeBare_r12::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    uint64_t nsze;
    char work[256];
    ConstSharedIdentifyPtr namSpcPtr;

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 0; i < bare.size(); i++) {
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]);
        if (namSpcPtr->isZeroFilled()) {
            LOG_NRM("Namespace %lu is inactive", i);
        } else {
            nsze = namSpcPtr->GetValue(IDNAMESPC_NSZE);

            LOG_NRM("Create memory to contain write payload");
            SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
            uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
            writeMem->Init(WR_NUM_BLKS * lbaDataSize);

            LOG_NRM("Create a write cmd to write data to namspc %d", bare[i]);
            SharedWritePtr writeCmd = SharedWritePtr(new Write());
            send_64b_bitmask prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE
                | MASK_PRP2_PAGE | MASK_PRP2_LIST);
            writeCmd->SetPrpBuffer(prpBitmask, writeMem);
            writeCmd->SetNSID(bare[i]);
            writeCmd->SetNLB(WR_NUM_BLKS - 1);    // convert to 0-based value

            LOG_NRM(
                "Issue cmd where 1st block starts at LBA (Identify.NSZE-2)");
            snprintf(work, sizeof(work), "nsze-2.%01d", (uint32_t)i);
            writeCmd->SetSLBA(nsze - 2);
            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, writeCmd, work, true);

            LOG_NRM(
                "Issue cmd where 1st block starts at LBA (Identify.NSZE-1)");
            snprintf(work, sizeof(work), "nsze-1.%d01d", (uint32_t)i);
            writeCmd->SetSLBA(nsze - 1);
            SendCmdToHdw(iosq, iocq, writeCmd, work);

            LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE)");
            snprintf(work, sizeof(work), "nsze.%01d", (uint32_t)i);
            writeCmd->SetSLBA(nsze);
            SendCmdToHdw(iosq, iocq, writeCmd, work);
        }
    }
}
Beispiel #7
0
void
WriteDataPat_r10b::WriteDataPattern()
{
    uint64_t regVal;


    LOG_NRM("Calc buffer size to write %d logical blks to media",
        WRITE_DATA_PAT_NUM_BLKS);
    ConstSharedIdentifyPtr namSpcPtr = gInformative->GetIdentifyCmdNamspc(1);
    if (namSpcPtr == Identify::NullIdentifyPtr) {
        LOG_ERR("Namespace #1 must exist");
        throw exception();
    }
    uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();


    LOG_NRM("Create data pattern to write to media");
    SharedMemBufferPtr dataPat = SharedMemBufferPtr(new MemBuffer());
    dataPat->Init(WRITE_DATA_PAT_NUM_BLKS * lbaDataSize);
    dataPat->SetDataPattern(MemBuffer::DATAPAT_INC_16BIT);
    dataPat->Dump(FileSystem::PrepLogFile(mGrpName, mTestName, "DataPat"),
        "Write buffer's data pattern");
    

    LOG_NRM("Create a generic write cmd to send data pattern to namspc 1");
    SharedWritePtr writeCmd = SharedWritePtr(new Write(mFd));
    send_64b_bitmask prpBitmask = (send_64b_bitmask)
        (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
    writeCmd->SetPrpBuffer(prpBitmask, dataPat);
    writeCmd->SetNSID(1);
    writeCmd->SetNLB(WRITE_DATA_PAT_NUM_BLKS-1);    // convert to 0-based value

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosqContig = CAST_TO_IOSQ(
        gRsrcMngr->GetObj(IOSQ_CONTIG_GROUP_ID))
    SharedIOCQPtr iocqContig = CAST_TO_IOCQ(
        gRsrcMngr->GetObj(IOCQ_CONTIG_GROUP_ID))
    SharedIOSQPtr iosqDiscontig = CAST_TO_IOSQ(
        gRsrcMngr->GetObj(IOSQ_DISCONTIG_GROUP_ID))
    SharedIOCQPtr iocqDiscontig = CAST_TO_IOCQ(
        gRsrcMngr->GetObj(IOCQ_DISCONTIG_GROUP_ID))

    LOG_NRM("Send the cmd to hdw via the contiguous IOQ's");
    SendToIOSQ(iosqContig, iocqContig, writeCmd, "contig");

    // To run the discontig part of this test, the hdw must support that feature
    if (gRegisters->Read(CTLSPC_CAP, regVal) == false) {
        LOG_ERR("Unable to determine Q memory requirements");
        throw exception();
    } else if (regVal & CAP_CQR) {
        LOG_NRM("Unable to utilize discontig Q's, DUT requires contig");
        return;
    }

    LOG_NRM("Send the cmd to hdw via the discontiguous IOQ's");
    SendToIOSQ(iosqDiscontig, iocqDiscontig, writeCmd, "discontig");
}
bool
LBAOutOfRangeBare_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    uint64_t nsze;
    ConstSharedIdentifyPtr namSpcPtr;

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosqContig = CAST_TO_IOSQ(
        gRsrcMngr->GetObj(IOSQ_CONTIG_GROUP_ID))
    SharedIOCQPtr iocqContig = CAST_TO_IOCQ(
        gRsrcMngr->GetObj(IOCQ_CONTIG_GROUP_ID))

    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 1; i < bare.size(); i++) {
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(i);
        if (namSpcPtr == Identify::NullIdentifyPtr) {
            LOG_ERR("Identify namspc struct #%d doesn't exist", bare[i]);
            throw exception();
        }
        nsze = namSpcPtr->GetValue(IDNAMESPC_NSZE);

        LOG_NRM("Create memory to contain read payload");
        SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());
        uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
        readMem->Init(RD_NUM_BLKS * lbaDataSize);

        LOG_NRM("Create a read cmd to read data from namspc %d", bare[i]);
        SharedReadPtr readCmd = SharedReadPtr(new Read(mFd));
        send_64b_bitmask prpBitmask = (send_64b_bitmask)
            (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
        readCmd->SetPrpBuffer(prpBitmask, readMem);
        readCmd->SetNSID(bare[i]);
        readCmd->SetNLB(RD_NUM_BLKS - 1);    // convert to 0-based value

        LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE-2)");
        readCmd->SetSLBA(nsze - 2);
        IO::SendCmdToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosqContig,
            iocqContig, readCmd, "nsze-2", true);

        LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE-1)");
        readCmd->SetSLBA(nsze - 1);
        SendCmdToHdw(iosqContig, iocqContig, readCmd, "nsze-1");

        LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE)");
        readCmd->SetSLBA(nsze);
        SendCmdToHdw(iosqContig, iocqContig, readCmd, "nsze");
    }

    return true;
}
Beispiel #9
0
void
InvalidNamspc_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    uint64_t inc, i;
    string work;
    uint32_t numCE;
    uint32_t isrCountB4;

    LOG_NRM("Lookup objs which were created in a prior test within group");
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    if ((numCE = iocq->ReapInquiry(isrCountB4, true)) != 0) {
        iocq->Dump(
            FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq",
                                     "notEmpty"), "Test assumption have not been met");
        throw FrmwkEx(HERE, "Require 0 CE's within CQ %d, not upheld, found %d",
                      iocq->GetQId(), numCE);
    }

    LOG_NRM("Setup write cmd's values that won't change per namspc");
    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
    uint64_t lbaDataSize = 512;
    writeMem->Init(lbaDataSize);

    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    send_64b_bitmask prpBitmask = (send_64b_bitmask)
                                  (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
    writeCmd->SetPrpBuffer(prpBitmask, writeMem);
    writeCmd->SetNLB(0);    // convert to 0-based value
    writeCmd->SetSLBA(0);

    LOG_NRM("For all namspc's issue cmd to an illegal namspc");
    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN);
    if (nn == 0 ) {
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");
    }

    for (i = (nn + 1), inc = 1; i <= 0xffffffff; i += (2 * inc), inc += 1327) {

        LOG_NRM("Issue flush cmd with illegal namspc ID=%llu",
                (unsigned long long)i);
        writeCmd->SetNSID(i);
        work = str(boost::format("namspc%d") % i);
        SendCmdToHdw(iosq, iocq, writeCmd, work);
    }
}
void
ProtInfoIgnoreBare_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    char context[256];
    ConstSharedIdentifyPtr namSpcPtr;

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 0; i < bare.size(); i++) {

        namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]);
        if (namSpcPtr == Identify::NullIdentifyPtr) {
            throw FrmwkEx(HERE, "Identify namspc struct #%d doesn't exist",
                          bare[i]);
        }

        LOG_NRM("Create memory to contain write payload");
        SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
        uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
        writeMem->Init(lbaDataSize);

        LOG_NRM("Create a write cmd to read data from namspc %d", bare[i]);
        SharedWritePtr writeCmd = SharedWritePtr(new Write());
        send_64b_bitmask prpBitmask = (send_64b_bitmask)
                                      (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
        writeCmd->SetPrpBuffer(prpBitmask, writeMem);
        writeCmd->SetNSID(bare[i]);
        writeCmd->SetNLB(0);    // convert to 0-based value

        for (uint16_t protInfo = 0; protInfo <= 0x0f; protInfo++) {
            uint8_t work = writeCmd->GetByte(12, 3);
            work &= ~0x3c;  // PRINFO specific bits
            work |= (protInfo << 2);
            writeCmd->SetByte(work, 12, 3);

            snprintf(context, sizeof(context), "ns%d.protInfo0x%02X",
                     (uint32_t)i, protInfo);
            IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
                               iocq, writeCmd, context, true);
        }
    }
}
Beispiel #11
0
void
IOSQ::Init(uint16_t qId, uint32_t numEntries, uint16_t cqId,
    uint8_t priority)
{
    uint8_t entrySize;
    uint64_t work;


    LOG_NRM("IOSQ::Init (qId,numEntry,cqId,prior) = (%d,%d,%d,%d)",
        qId, numEntries, cqId, priority);

    switch (priority) {
	case 0:
	case 1:
	case 2:
	case 3:
		mPriority = priority;
		break;
	default:
		throw FrmwkEx(HERE, "Illegal priority value, can't fit within 2 bits");
	}

    if (gCtrlrConfig->GetIOSQES(entrySize) == false)
        throw FrmwkEx(HERE, "Unable to learn IOSQ entry size");

    // Nothing to gain by specifying an element size which the DUT doesn't
    // support, the outcome is undefined, might succeed in crashing the kernel
    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint64_t value = idCtrlrCap->GetValue(IDCTRLRCAP_SQES);
    uint8_t maxElemSize = (uint8_t)((value >> 4) & 0x0f);
    uint8_t minElemSize = (uint8_t)((value >> 0) & 0x0f);
    if ((entrySize < minElemSize) || (entrySize > maxElemSize)) {
        throw FrmwkEx(HERE, "Reg CC.IOSQES yields a bad element size: 0x%04X",
            (1 << entrySize));
    }

    // Detect if doing something that looks suspicious/incorrect/illegal
    if (gRegisters->Read(CTLSPC_CAP, work) == false)
        throw FrmwkEx(HERE, "Unable to determine MQES");

    work &= CAP_MQES;
    work += 1;      // convert to 1-based
    if ((work + 1) < (uint64_t)numEntries) {
        LOG_WARN("Creating Q with %d entries, but DUT only allows %d",
            numEntries, (uint32_t)(work + 1));
    }

    SQ::Init(qId, (1 << entrySize), numEntries, cqId);
}
void
ProtInfoIgnoreBare_r12::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    char context[256];
    ConstSharedIdentifyPtr namSpcPtr;

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 0; i < bare.size(); i++) {
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]);
        if (namSpcPtr->isZeroFilled()) {
            LOG_NRM("Namespace %lu is inactive", i);
        } else {
            LOG_NRM("Create memory to contain read payload");
            SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());
            uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
            readMem->Init(lbaDataSize);

            LOG_NRM("Create a read cmd to read data from namspc %d", bare[i]);
            SharedReadPtr readCmd = SharedReadPtr(new Read());
            send_64b_bitmask prpBitmask = (send_64b_bitmask)
                (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
            readCmd->SetPrpBuffer(prpBitmask, readMem);
            readCmd->SetNSID(bare[i]);
            readCmd->SetNLB(0);    // convert to 0-based value

            for (uint16_t protInfo = 0; protInfo <= 0x0f; protInfo++) {
                uint8_t work = readCmd->GetByte(12, 3);
                work &= ~0x3c;  // PRINFO specific bits
                work |= (protInfo << 2);
                readCmd->SetByte(work, 12, 3);

                snprintf(context, sizeof(context), "ns%d.protInfo0x%02X",
                    (uint32_t)i, protInfo);
                IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
                    iosq, iocq, readCmd, context, true);
            }
        }
    }
}
void
FunctionalityBare_r10b::ResizeDataBuf(SharedReadPtr &readCmd,
    SharedWritePtr &writeCmd, ConstSharedIdentifyPtr namSpcPtr,
    uint64_t maxWrBlks, send_64b_bitmask prpBitmask)
{
    LBAFormat lbaFormat = namSpcPtr->GetLBAFormat();
    uint64_t lbaDataSize = (1 << lbaFormat.LBADS);

    SharedMemBufferPtr readMem = readCmd->GetRWPrpBuffer();
    SharedMemBufferPtr writeMem = writeCmd->GetRWPrpBuffer();

    switch (gInformative->IdentifyNamespace(namSpcPtr)) {
    case Informative::NS_BARE:
    case Informative::NS_METAS:
        LOG_NRM("Resized max rd/wr blks to %ld for separate meta or bare", maxWrBlks);
        writeMem->Init(maxWrBlks * lbaDataSize);
        readMem->Init(maxWrBlks * lbaDataSize);
        break;
    case Informative::NS_METAI:
        LOG_NRM("Resized max rd/wr blks to %ld for integrated meta", maxWrBlks);
        writeMem->Init(maxWrBlks * (lbaDataSize + lbaFormat.MS));
        readMem->Init(maxWrBlks * (lbaDataSize + lbaFormat.MS));
        break;
    case Informative::NS_E2ES:
    case Informative::NS_E2EI:
    throw FrmwkEx(HERE, "Deferring work to handle this case in future");
    break;
    }

    writeCmd->SetPrpBuffer(prpBitmask, writeMem);
    writeCmd->SetNLB(maxWrBlks - 1); // 0 based value.

    readCmd->SetPrpBuffer(prpBitmask, readMem);
    readCmd->SetNLB(maxWrBlks - 1); // 0 based value.
}
Beispiel #14
0
Test::RunType
VerifyNUSE_r10b::RunnableCoreTest(bool preserve)
{
    ///////////////////////////////////////////////////////////////////////////
    // All code contained herein must never permanently modify the state or
    // configuration of the DUT. Permanence is defined as state or configuration
    // changes that will not be restored after a cold hard reset.
    ///////////////////////////////////////////////////////////////////////////

    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS);
    if ((oncs & ONCS_SUP_DSM_CMD) == 0)
        return RUN_FALSE;

    return ((preserve == true) ? RUN_FALSE : RUN_TRUE);   // Test is destructive
}
Beispiel #15
0
void
IgnoreMetaPtrBare_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    string work;
    ConstSharedIdentifyPtr namSpcPtr;

    LOG_NRM("Lookup objs which were created in a prior test within group");
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    LOG_NRM("For all bare namspc's issue cmd with non-zero meta ptr");
    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 0; i < bare.size(); i++) {

        namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]);
        if (namSpcPtr == Identify::NullIdentifyPtr) {
            throw FrmwkEx(HERE, "Identify namspc struct #%d doesn't exist",
                bare[i]);
        }

        LOG_NRM("Setup write cmd's values that won't change per namspc");
        SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
        uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
        writeMem->Init(lbaDataSize);

        SharedWritePtr writeCmd = SharedWritePtr(new Write());
        send_64b_bitmask prpBitmask = (send_64b_bitmask)
            (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
        writeCmd->SetPrpBuffer(prpBitmask, writeMem);
        writeCmd->SetNLB(0);    // convert to 0-based value
        writeCmd->SetSLBA(0);

        LOG_NRM("Set MPTR in cmd to max value");
        writeCmd->SetDword(0xffffffff, 4);
        writeCmd->SetDword(0xffffffff, 5);

        writeCmd->SetNSID(bare[i]);
        work = str(boost::format("namspc%d") % bare[i]);
        IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, iocq,
            writeCmd, work, true);
    }
}
void
UnsupportRsvdFields_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    SharedFlushPtr flushCmd = SharedFlushPtr(new Flush());
    ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr();
    for (uint64_t i = 1; i <= idCtrlr->GetValue(IDCTRLRCAP_NN); i++) {
        LOG_NRM("Processing namspc %ld", i);
        flushCmd->SetNSID(i);

        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,
            flushCmd, "none.set", true);

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

        flushCmd->SetDword(0xffffffff, 2);
        flushCmd->SetDword(0xffffffff, 3);
        flushCmd->SetDword(0xffffffff, 4);
        flushCmd->SetDword(0xffffffff, 5);
        flushCmd->SetDword(0xffffffff, 6);
        flushCmd->SetDword(0xffffffff, 7);
        flushCmd->SetDword(0xffffffff, 8);
        flushCmd->SetDword(0xffffffff, 9);
        flushCmd->SetDword(0xffffffff, 10);
        flushCmd->SetDword(0xffffffff, 11);
        flushCmd->SetDword(0xffffffff, 12);
        flushCmd->SetDword(0xffffffff, 13);
        flushCmd->SetDword(0xffffffff, 14);
        flushCmd->SetDword(0xffffffff, 15);

        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,
            flushCmd, "all.set", true);
    }
}
void
IgnoreMetaPtrBare_r12::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    string work;
    ConstSharedIdentifyPtr namSpcPtr;

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    LOG_NRM("For all bare namspc's issue cmd with non-zero meta ptr");
    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 0; i < bare.size(); i++) {
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]);
        if (namSpcPtr->isZeroFilled()) {
            LOG_NRM("Namespace %lu is inactive", i);
        } else {
            LOG_NRM("Setup read cmd's values that won't change per namspc");
            SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());
            uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
            readMem->Init(lbaDataSize);

            SharedReadPtr readCmd = SharedReadPtr(new Read());
            send_64b_bitmask prpBitmask = (send_64b_bitmask)
                (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
            readCmd->SetPrpBuffer(prpBitmask, readMem);
            readCmd->SetNLB(0);    // convert to 0-based value
            readCmd->SetSLBA(0);

            LOG_NRM("Set MPTR in cmd to max value");
            readCmd->SetDword(0xffffffff, 4);
            readCmd->SetDword(0xffffffff, 5);

            readCmd->SetNSID(bare[i]);
            work = str(boost::format("namspc%d") % bare[i]);
            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, readCmd, work, true);
        }
    }
}
Test::RunType
CreateAndAttachMaxNamespacesAndVerify::RunnableCoreTest(bool preserve)
{
    ///////////////////////////////////////////////////////////////////////////
    // All code contained herein must never permanently modify the state or
    // configuration of the DUT. Permanence is defined as state or configuration
    // changes that will not be restored after a cold hard reset.
    ///////////////////////////////////////////////////////////////////////////

    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint64_t oacs = idCtrlrCap->GetValue(IDCTRLRCAP_OACS);
    if ((oacs & OACS_SUP_NSMANAGEMENT_CMD) == 0) {
        LOG_NRM("Reporting Namespace Management not supported (oacs) 0x%02x", (uint32_t) oacs);
        return RUN_FALSE;
    }

    preserve = preserve;    // Suppress compiler error/warning
    return RUN_TRUE;        // This test is never destruct
}
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);
}
void
IgnoreMetaPtrMeta_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    string work;
    ConstSharedIdentifyPtr namSpcPtr;

    LOG_NRM("Lookup objs which were created in a prior test within group");
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    LOG_NRM("For all imeta namspc's issue read cmd with non-zero meta ptr");
    vector<uint32_t> imeta = gInformative->GetMetaINamespaces();
    for (size_t i = 0; i < imeta.size(); i++) {
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(imeta[i]);

        LOG_NRM("Setup read cmd's values that won't change per namspc");
        SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());
        uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
        LBAFormat lbaFormat = namSpcPtr->GetLBAFormat();
        readMem->Init(lbaDataSize + lbaFormat.MS);

        SharedReadPtr readCmd = SharedReadPtr(new Read());
        send_64b_bitmask prpBitmask = (send_64b_bitmask)
            (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);
        readCmd->SetPrpBuffer(prpBitmask, readMem);
        readCmd->SetNLB(0);    // convert to 0-based value

        LOG_NRM("Set MPTR in cmd to max value");
        readCmd->SetDword(0xffffffff, 4);
        readCmd->SetDword(0xffffffff, 5);

        readCmd->SetNSID(imeta[i]);
        work = str(boost::format("namspc%d") % imeta[i]);
        IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, iocq,
            readCmd, work, true);
    }
}
Beispiel #21
0
void
GetLogPage::SetNUMD(uint16_t numDW)
{
    uint64_t errLogPgEntries;
    uint64_t numDWAvail;

    LOG_NRM("Setting NUMD 0x%04X", numDW);
    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    errLogPgEntries = idCmdCtrlr->GetValue(IDCTRLRCAP_ELPE);
    numDWAvail = ((errLogPgEntries * ERRINFO_DATA_SIZE) / sizeof(uint32_t));
    if (numDWAvail > numDW) {
        // per the spec this action is undef'd, so don't allow it
        LOG_ERR("Request %d DWORDS > %lld available yields undef'd results",
            numDW, (unsigned long long)numDWAvail);
        throw  exception();
    }

    uint16_t curVal = GetWord(10, 1);
    curVal &= ~NUMD_BITMASK;
    curVal |= (numDW & NUMD_BITMASK);
    SetWord(curVal, 10, 1);
}
Beispiel #22
0
SharedReadPtr
FUA_r10b::CreateCmd()
{
    Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E();
    LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat();
    LOG_NRM("Processing read cmd using namspc id %d", namspcData.id);

    ConstSharedIdentifyPtr namSpcPtr = namspcData.idCmdNamspc;
    uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();;
    SharedMemBufferPtr dataPat = SharedMemBufferPtr(new MemBuffer());

    SharedReadPtr readCmd = SharedReadPtr(new Read());
    send_64b_bitmask prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE
                                  | MASK_PRP2_PAGE | MASK_PRP2_LIST);

    switch (namspcData.type) {
    case Informative::NS_BARE:
        dataPat->Init(lbaDataSize);
        break;
    case Informative::NS_METAS:
        dataPat->Init(lbaDataSize);
        if (gRsrcMngr->SetMetaAllocSize(lbaFormat.MS) == false)
            throw FrmwkEx(HERE);
        readCmd->AllocMetaBuffer();
        break;
    case Informative::NS_METAI:
        dataPat->Init(lbaDataSize + lbaFormat.MS);
        break;
    case Informative::NS_E2ES:
    case Informative::NS_E2EI:
        throw FrmwkEx(HERE, "Deferring work to handle this case in future");
        break;
    }

    readCmd->SetPrpBuffer(prpBitmask, dataPat);
    readCmd->SetNSID(namspcData.id);
    readCmd->SetNLB(0);
    return readCmd;
}
Beispiel #23
0
void
Identify_r10b::RunCoreTest()
{
   /** \verbatim
     * Assumptions:
     * 1) This is the 1st within GrpNVMCompareCmd.
     *
     * NOTE: To validate whether a DUT is suppose to support or not support an
     *       optional feature, the cmd line option --golden should be used.
     *       The reason this test is present as the 1st within any optional
     *       grouping of tests is to force a development team to make a
     *       decision as to whether these tests should be included or skipped
     *       based upon their specific hdw requirements. This way nothing will
     *       be missed by accident. The assumption is that every optional
     *       feature is support until told otherwise by the cmd line option
     *       --skiptest.
     * \endverbatim
     */
    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS);
    if ((oncs & ONCS_SUP_DSM_CMD) == 0)
        throw FrmwkEx(HERE, "Optional feature not supported, see this source");
}
void
ProtInfoIgnoreMeta_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) None.
     * \endverbatim
     */
    string context;
    ConstSharedIdentifyPtr namSpcPtr;
    SharedIOSQPtr iosq;
    SharedIOCQPtr iocq;
    send_64b_bitmask prpBitmask = (send_64b_bitmask)
        (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);

    if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
        throw FrmwkEx(HERE);

    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    LOG_NRM("Get all the supported meta namespaces");
    vector<uint32_t> meta = gInformative->GetMetaNamespaces();
    for (size_t i = 0; i < meta.size(); i++) {
        if (gCtrlrConfig->SetState(ST_DISABLE) == false)
            throw FrmwkEx(HERE);

        // All queues will use identical IRQ vector
        IRQ::SetAnySchemeSpecifyNum(1);

        gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
        if (gCtrlrConfig->SetState(ST_ENABLE) == false)
            throw FrmwkEx(HERE);

        LOG_NRM("Create IOSQ and IOCQ with ID #%d", IOQ_ID);
        CreateIOQs(asq, acq, IOQ_ID, iosq, iocq);

        LOG_NRM("Get LBA format and lba data size for namespc #%d", meta[i]);
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(meta[i]);
        LBAFormat lbaFormat = namSpcPtr->GetLBAFormat();
        uint64_t lbaDataSize = (1 << lbaFormat.LBADS);

        LOG_NRM("Create a read cmd to read data from namspc %d", meta[i]);
        SharedReadPtr readCmd = SharedReadPtr(new Read());

        LOG_NRM("Create memory to contain read payload");
        SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

        Informative::NamspcType
            nsType = gInformative->IdentifyNamespace(namSpcPtr);
        switch (nsType) {
        case Informative::NS_BARE:
            throw FrmwkEx(HERE, "Namspc type cannot be BARE.");
        case Informative::NS_METAS:
            readMem->Init(lbaDataSize);
            if (gRsrcMngr->SetMetaAllocSize(lbaFormat.MS) == false)
                throw FrmwkEx(HERE);
            readCmd->AllocMetaBuffer();
            break;
        case Informative::NS_METAI:
            readMem->Init(lbaDataSize + lbaFormat.MS);
            break;
        case Informative::NS_E2ES:
        case Informative::NS_E2EI:
            throw FrmwkEx(HERE, "Deferring work to handle this case in future");
            break;
        }

        readCmd->SetPrpBuffer(prpBitmask, readMem);
        readCmd->SetNSID(meta[i]);
        readCmd->SetNLB(0);    // convert to 0-based value

        for (uint16_t protInfo = 0; protInfo <= 0x0f; protInfo++) {
            uint8_t work = readCmd->GetByte(12, 3);
            work &= ~0x3c;  // PRINFO specific bits
            work |= (protInfo << 2);
            readCmd->SetByte(work, 12, 3);

            context = str(boost::format("ns%d.protInfo0x%02X") %
                (uint32_t)i % protInfo);
            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, readCmd, context, true);
        }
    }
}
void
FunctionalityMeta_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    bool enableLog;
    ConstSharedIdentifyPtr namSpcPtr;
    SharedIOSQPtr iosq;
    SharedIOCQPtr iocq;
    uint64_t maxWrBlks;

    if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
        throw FrmwkEx(HERE);

    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    uint32_t maxDtXferSz = idCmdCtrlr->GetMaxDataXferSize();
    if (maxDtXferSz == 0)
        maxDtXferSz = MAX_DATA_TX_SIZE;

    LOG_NRM("Prepare cmds to be send through Q's.");
    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());

    SharedReadPtr readCmd = SharedReadPtr(new Read());
    SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

    SharedFlushPtr flushCmd = SharedFlushPtr(new Flush());

    DataPattern dataPat[] = {
        DATAPAT_INC_8BIT,
        DATAPAT_CONST_8BIT,
        DATAPAT_INC_16BIT,
        DATAPAT_CONST_16BIT,
        DATAPAT_INC_32BIT,
        DATAPAT_CONST_32BIT
    };
    uint64_t dpArrSize = sizeof(dataPat) / sizeof(dataPat[0]);
    send_64b_bitmask prpBitmask = (send_64b_bitmask)
        (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);

    LOG_NRM("Seeking all meta namspc's.");
    vector<uint32_t> meta = gInformative->GetMetaNamespaces();
    for (size_t i = 0; i < meta.size(); i++) {
        LOG_NRM("Processing meta namspc id #%d of %ld", meta[i], meta.size());
        if (gCtrlrConfig->SetState(ST_DISABLE) == false)
            throw FrmwkEx(HERE);

        // All queues will use identical IRQ vector
        IRQ::SetAnySchemeSpecifyNum(1);

        gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
        if (gCtrlrConfig->SetState(ST_ENABLE) == false)
            throw FrmwkEx(HERE);

        LOG_NRM("Create IOSQ and IOCQ with ID #%d", IOQ_ID);
        CreateIOQs(asq, acq, IOQ_ID, iosq, iocq);

        LOG_NRM("Get LBA format and lba data size for namespc #%d", meta[i]);
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(meta[i]);
        LBAFormat lbaFormat = namSpcPtr->GetLBAFormat();
        uint64_t lbaDataSize = (1 << lbaFormat.LBADS);
        uint64_t ncap = namSpcPtr->GetValue(IDNAMESPC_NCAP);
        uint64_t metaBuffSz = 0;

        LOG_NRM("Set read and write buffers based on the namspc type");
        switch (gInformative->IdentifyNamespace(namSpcPtr)) {
        case Informative::NS_BARE:
            throw FrmwkEx(HERE, "Namspc type cannot be BARE.");
        case Informative::NS_METAS:
            maxWrBlks = maxDtXferSz / lbaDataSize;
            metaBuffSz = maxWrBlks * lbaFormat.MS;
            if (gRsrcMngr->SetMetaAllocSize(metaBuffSz) == false)
                throw FrmwkEx(HERE);
            LOG_NRM("Max rd/wr blks %ld using separate meta buff of ncap %ld",
                maxWrBlks, ncap);
            writeMem->Init(maxWrBlks * lbaDataSize);
            readMem->Init(maxWrBlks * lbaDataSize);
            writeCmd->AllocMetaBuffer();
            readCmd->AllocMetaBuffer();
            break;
        case Informative::NS_METAI:
            maxWrBlks = maxDtXferSz / (lbaDataSize + lbaFormat.MS);
            LOG_NRM("Max rd/wr blks %ld using integrated meta buff of ncap %ld",
                maxWrBlks, ncap);
            writeMem->Init(maxWrBlks * (lbaDataSize + lbaFormat.MS));
            readMem->Init(maxWrBlks * (lbaDataSize + lbaFormat.MS));
            break;
        case Informative::NS_E2ES:
        case Informative::NS_E2EI:
            throw FrmwkEx(HERE, "Deferring work to handle this case in future");
            break;
        }

        writeCmd->SetPrpBuffer(prpBitmask, writeMem);
        writeCmd->SetNSID(meta[i]);
        writeCmd->SetNLB(maxWrBlks - 1);  // 0 based value.

        readCmd->SetPrpBuffer(prpBitmask, readMem);
        readCmd->SetNSID(meta[i]);
        readCmd->SetNLB(maxWrBlks - 1);  // 0 based value.

        flushCmd->SetNSID(meta[i]);

        for (uint64_t sLBA = 0; sLBA < maxWrBlks/*(ncap - 1)*/; sLBA += maxWrBlks) {
            LOG_NRM("Processing at #%ld blk of %ld", sLBA, (ncap -1));
            if ((sLBA + maxWrBlks) >= ncap) {
                maxWrBlks = ncap - sLBA;
                LOG_NRM("Resize max write blocks to #%ld", maxWrBlks);
                ResizeDataBuf(readCmd, writeCmd, namSpcPtr, maxWrBlks,
                    prpBitmask);
                metaBuffSz = maxWrBlks * lbaFormat.MS;
            }
            LOG_NRM("Sending #%ld blks starting at #%ld", maxWrBlks, sLBA);
            for (uint64_t nLBA = 0; nLBA < maxWrBlks; nLBA++) {
                writeMem->SetDataPattern(dataPat[nLBA % dpArrSize],
                    (sLBA + nLBA + 1), (nLBA * lbaDataSize), lbaDataSize);
                writeCmd->SetMetaDataPattern(dataPat[nLBA % dpArrSize],
                    (sLBA + nLBA + 1), (nLBA * lbaFormat.MS), lbaFormat.MS);
            }
            writeCmd->SetSLBA(sLBA);
            readCmd->SetSLBA(sLBA);

            enableLog = false;
            if ((sLBA <= maxWrBlks) || (sLBA >= (ncap - 2 * maxWrBlks)))
                enableLog = true;
            work = str(boost::format("metaID.%d.SLBA.%ld") % meta[i] % sLBA);

            LOG_NRM("Sending write and read commands through ioq's");
            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, writeCmd, work, enableLog);

            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, flushCmd, work, enableLog);

            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, readCmd, work, enableLog);

            VerifyDataPat(readCmd, writeCmd, metaBuffSz);
        }
    }
}
void
CreateAndAttachMaxNamespacesAndVerify::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
	LOG_NRM("Start CreateAndAttachMaxNamespacesAndVerify::RunCoreTest");

	SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
	SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));
	SharedASQPtr   asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID));
	SharedACQPtr   acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID));
	//uint8_t keyToRegister[16];
	//uint32_t memAlignment = sysconf(_SC_PAGESIZE);
	//CEStat retStat;
	send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE);
	uint8_t userBuffer[4096];
    if (userBuffer == 0){} // Suppress unused variable warning

    const uint32_t *namespaceIdListBuffer32BitPtr = NULL;
    const uint16_t *controllerIdListBuffer16BitPtr;

    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint32_t identifyControllerMaxNSID = (uint32_t)idCtrlrCap->GetValue(IDCTRLRCAP_NN);

    // BUGBUG large assumption that NVMCAP values will not be larger than 64bit num bytes, which is 16384 PETAbytes
    // BUGBUG Also assume we need to create on GB multiples

    uint64_t identifyControllerUnallocatedCapacity = idCtrlrCap->GetValue(IDCTRLRCAP_UNVMCAP_LOWER);
    uint64_t identifyControllerTotalCapacity       = idCtrlrCap->GetValue(IDCTRLRCAP_TNVMCAP_LOWER);

    uint64_t individualNamespaceCapacityInGB       = (uint64_t) floor( identifyControllerUnallocatedCapacity / 1024.0 / 1024.0 / 1024.0 / identifyControllerMaxNSID); // In GB units
    uint64_t individualNamespaceCapacity = individualNamespaceCapacityInGB * 1024 * 1024 * 1024 / 512; // In 512B LBA units
    uint32_t newlyCreatedNSID = 0;

    if( identifyControllerUnallocatedCapacity != identifyControllerTotalCapacity) {
    	LOG_NRM("TNVMCAP != UNVMCAP, which points to a namespace being allocated but the previous test should have deleted all");
    }

	LOG_NRM("Create Identify Command To Get All Present NSIDs");
	SharedIdentifyPtr identifyCmd = SharedIdentifyPtr(new Identify());
    SharedMemBufferPtr identifyControllerStruct = SharedMemBufferPtr(new MemBuffer());
    identifyControllerStruct->Init(4096, true, 0x0);
    SharedMemBufferPtr identifyNamespaceStruct = SharedMemBufferPtr(new MemBuffer());
    identifyNamespaceStruct->Init(4096, true, 0x0);
    SharedMemBufferPtr identifyNamespaceList = SharedMemBufferPtr(new MemBuffer());
    identifyNamespaceList->Init(4096, true, 0x0);
    SharedMemBufferPtr identifyControllerList = SharedMemBufferPtr(new MemBuffer());
    identifyControllerList->Init(4096, true, 0x0);

    // Figure 86 in 1.2 spec               CNS  NSID CNTID Returns
    // CNS_Namespace                      0x00    X     -   (Identify Namespace from NSID X. If attached, receive struct, else all 0's, else invalid namespace ID)
    // CNS_Controller                     0x01    -     -   (Identify Controller struct)
    // CNS_NamespaceListAttached          0x02    Y     -   (Identify Namespace LIST, starting at NSID Y and in an increasing order)
    // CNS_NamespaceListSubsystem         0x10    Z     -   (Identify Namespace LIST, starting at NSID Z present in subsystem that may or may not be attached)
    // CNS_NamespaceStructSubsystem       0x11    X     -   (Identify Namespace from NSID A. If attached or not, receive the struct, else invalid namespace ID)
    // CNS_ControllerListAttachedToNSID   0x12    X     A   (Controller List that are attached to NSID X, starting with CNTID greater than A)
    // CNS_ControllerListSubsystem        0x13    -     B   (Controller List present in subsystem starting with CNTID greater than B)

    LOG_NRM("First ensure there are no namespaces present, as this test depends on deleteAllNamespacesAndVerify to complete successfully");
	// See 8.11 in 1.2 spec for describing the process this test is following
	identifyCmd->SetPrpBuffer(prpBitmask, identifyNamespaceList);
	identifyCmd->SetNSID( 0 );
	identifyCmd->SetCNS(  CNS_NamespaceListSubsystem ); // Get all NSIDs attached (or not) to controllers
    identifyCmd->SetCNTID(0);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Reading back (up to) 1024 NSIDs attached to this controller (CNS=2). Command should pass, with 0 NSIDs to be returned", false, CESTAT_SUCCESS);
    namespaceIdListBuffer32BitPtr = (uint32_t*) identifyCmd->GetROPrpBuffer();
    if( namespaceIdListBuffer32BitPtr[0] != 0) {
    	throw FrmwkEx(HERE, "Before creating any namespaces, subsystem was expected to have no NSIDs active and present, but Identify CNS=0x10 returned at least one NSID.");
    }

    LOG_NRM("No namespaces are active, test can continue. Pull back the controller list to be used to attach all NSIDs to all controllers on subsystem");
	identifyCmd->SetPrpBuffer(prpBitmask, identifyControllerList);
	identifyCmd->SetNSID( 0 );
	identifyCmd->SetCNS(  CNS_ControllerListSubsystem ); // Get all controllers in this subsystem
	identifyCmd->SetCNTID(0);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Reading back what controllers are on this subsystem (CNS=0x13), should find at LEAST one.", false, CESTAT_SUCCESS);
    controllerIdListBuffer16BitPtr = (uint16_t*) identifyCmd->GetROPrpBuffer();
    if( controllerIdListBuffer16BitPtr[0] == 0) {
    	throw FrmwkEx(HERE, "Before creating any namespaces, subsystem was expected to have at least one controller ID present, but found zero.");
    }

    SharedNamespaceAttachPtr namespaceAttachCmd = SharedNamespaceAttachPtr(new NamespaceAttach() );
    /*
    //BUGBUG APL is returning an improper list (Ctrlr IDs 1/2 wheras they ID themselves as actually 0/1)
    for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) {
    	userBuffer[bufferIndex]=0;
    }
    userBuffer[0] = 2; // 2 Controllers
    userBuffer[4] = 1; // 1st (byte 2) is 0 and 2nd (byte 4) is 1 to match APL
    identifyControllerList->InitAlignment(4096, 4096, false, 0, userBuffer);
    LOG_NRM("Controller list hardcoded to 0/1 for the time being... BUGBUG");
    // END BUG BUG
    */
    // Set attach namespace buffer to be the full controller list, to attach all new NSIDs to to all on this subsystem
    namespaceAttachCmd->SetPrpBuffer(prpBitmask, identifyControllerList);

	LOG_NRM("Create Namespace Management to create all namespaces before attaching to all contollers");
    SharedNamespaceManagementPtr namespaceManagementCmd = SharedNamespaceManagementPtr(new NamespaceManagement() );
    SharedMemBufferPtr managementBuffer = SharedMemBufferPtr(new MemBuffer() );

    NamespaceManagementCreateStruct nscreate;
    nscreate.NSZE = individualNamespaceCapacity;
    nscreate.NCAP = individualNamespaceCapacity;
    nscreate.FLBAS = 0;
    nscreate.DPS   = 0;
    nscreate.NMIC  = 1;

    //NamespaceManagementCreateStruct nscreate( individualNamespaceCapacity, individualNamespaceCapacity, 0, 0, 1 );
    // BUGBUG we are going to assume a 512B size and barenamespace as FLBAS=0... otherwise we need to determine what format via namespace structs...
    //CreateNamespaceManagementStructure( individualNamespaceCapacity, individualNamespaceCapacity, 0, 0, 1, userBuffer);
    LOG_NRM("Each of the %d namespaces will be of 0x%llx size", identifyControllerMaxNSID, (long long unsigned int) individualNamespaceCapacity);
    nscreate.print();

    managementBuffer->InitAlignment(384, 4096, false, 0x0, (uint8_t*) &nscreate); // Contains namespace struct info for namespace management to consume (384B)
    namespaceManagementCmd->SetPrpBuffer(prpBitmask, managementBuffer);
    namespaceAttachCmd->SetSEL( 0 );
    namespaceAttachCmd->SetNSID( 0 );

	LOG_NRM("Start main loop over valid NSIDs to create/attach them.");
	for(uint64_t currentNamespaceIdToCreate = 0; currentNamespaceIdToCreate < identifyControllerMaxNSID; currentNamespaceIdToCreate++ ) {
		// Get the current
		// Create this namespace using 1/NNth amount of the total available space.
	    namespaceManagementCmd->SetSEL(0);
	    namespaceManagementCmd->SetNSID(0);
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceManagementCmd, "Creating namespace that is 1/NNth size of total NVM capacity, 512B bare LBAs.", false, CESTAT_SUCCESS);
	    newlyCreatedNSID = (acq->PeekCEwithCID( namespaceManagementCmd->GetCID() ) ).t.dw0;
	    LOG_NRM("Newly created NS has NSID of 0x%llu", (long long unsigned) newlyCreatedNSID);

		// ID this namespace and see if it is all 0s. Namespace should be created but 'inactive'.
		identifyCmd->SetCNS(CNS_Namespace ); // Standard Namespace ID, should also be attached to this controller
		identifyCmd->SetNSID( newlyCreatedNSID ); //
	    identifyCmd->SetCNTID(0);
		identifyCmd->SetPrpBuffer(prpBitmask, identifyNamespaceStruct);
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Read Identify Controller struct from created NSID, expecting it to be all 0's since it has not yet attached", false, CESTAT_SUCCESS);
	    // Currently fails on FW
	    for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) {
    		if ( identifyCmd->GetROPrpBuffer()[bufferIndex] != 0) {
    			throw FrmwkEx(HERE, "Expected Identify Namespace to returned all zero buffer as namespace should be inactive and non-attached");
    		}
    	}

	    // Now attach the drive to all controllers on the subsystem
	    namespaceAttachCmd->SetNSID( newlyCreatedNSID );
	    namespaceAttachCmd->SetSEL(0);
	    // Should already have the ControllerList associated with the NamespaceAttach command
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceAttachCmd, "Attaching NSID to all controllers on subsystem", false, CESTAT_SUCCESS);

	    // Reread this NS struct back and make sure the values match what we had requested...
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Read Identify Controller struct from created NSID, expecting non-zero since it is now attached", false, CESTAT_SUCCESS);
	    // First ensure the buffer is not completely non-zero
	    bool identifyNamespaceBufferIsZeroFilled = true;
	    for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) {
    		if ( identifyCmd->GetROPrpBuffer()[bufferIndex] != 0) {
    			identifyNamespaceBufferIsZeroFilled = false;
    			break;
    		}
    	}
	    if( identifyNamespaceBufferIsZeroFilled == true) {
	    	throw FrmwkEx(HERE, "Expected Identify Namespace to returned a non-zero buffer as namespace should now be attached");
	    }

	    // Now check a couple fields (BUGBUG should check all!)
	    IdNamespcStruct *currentNamespaceStruct = (IdNamespcStruct*) identifyCmd->GetROPrpBuffer();
	    if(currentNamespaceStruct->NSZE != individualNamespaceCapacity) {
	    	LOG_NRM("Namespace NSZE 0x%llx != what was passed to namespaceManagement 0x%08llx", (long long unsigned) currentNamespaceStruct->NSZE, (long long unsigned) individualNamespaceCapacity);
	    	throw FrmwkEx(HERE, "Newly created namespace's NSZE does not match what was sent to namespaceManagement");
	    }
	    if(currentNamespaceStruct->NCAP != individualNamespaceCapacity) {
	    	LOG_NRM("Namespace NCAP 0x%llx != what was passed to namespaceManagement 0x%08llx", (long long unsigned) currentNamespaceStruct->NCAP, (long long unsigned) individualNamespaceCapacity);
	    	throw FrmwkEx(HERE, "Newly created namespace's NCAP does not match what was sent to namespaceManagement");
	    }

	    // Repull the Identify Controller information and make sure the UNVMCAP values have decreased the amount we just allocatd for this create namespace
	    identifyCmd->SetCNS(CNS_Controller);
	    identifyCmd->SetNSID(0);
	    identifyCmd->SetCNTID(0);
	    identifyCmd->SetPrpBuffer(prpBitmask, identifyControllerStruct);
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Pull Identify Controller to check usage sizes have changed.", false, CESTAT_SUCCESS);
	    IdCtrlrCapStruct *currentControllerStruct = (IdCtrlrCapStruct*) identifyCmd->GetROPrpBuffer();
	    uint64_t expectedNVMCAP = identifyControllerTotalCapacity - (individualNamespaceCapacity * (currentNamespaceIdToCreate+1) * 512);
	    if(currentControllerStruct->UNVMCAP_LOWER != expectedNVMCAP) {
	    	LOG_NRM("Expecting UNVMCAP to decrease by last allocated namespace. UNVMCAP = 0x%llx expecting 0x%llx", (long long unsigned) currentControllerStruct->UNVMCAP_LOWER, (long long unsigned) expectedNVMCAP);
	    	throw FrmwkEx(HERE, "Identify Controller UNVMCAP is not adjusted after creating a namespace of 1/NNth size");
	    }

	    // Try to retry the attachment again and ensure a proper fail case
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceAttachCmd, "Attaching an already attached NSID to all controllers again to check fail case", false, CESTAT_NS_ALREADY_ATTACHED);
	}

	// At this point we can double sanity check.
	// 1) Controller should state 0 bytes available
	// 2) Should be Cntrl.NN namespaces active and attached to all controllers on the subsystem

    LOG_NRM("Completed CreateAndAttachMaxNamespacesAndVerify::RunCoreTest");
}
Beispiel #27
0
void
StartingLBABare_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    string work;
    bool enableLog;
    ConstSharedIdentifyPtr namSpcPtr;

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    uint32_t maxDtXferSz = idCmdCtrlr->GetMaxDataXferSize();
    if (maxDtXferSz == 0)
        maxDtXferSz = MAX_DATA_TX_SIZE;

    LOG_NRM("Prepare cmds to be send through Q's.");
    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
    send_64b_bitmask prpBitmask = (send_64b_bitmask)
        (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);

    SharedReadPtr readCmd = SharedReadPtr(new Read());
    SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

    DataPattern dataPat[] = {
        DATAPAT_INC_8BIT,
        DATAPAT_CONST_8BIT,
        DATAPAT_INC_16BIT,
        DATAPAT_CONST_16BIT,
        DATAPAT_INC_32BIT,
        DATAPAT_CONST_32BIT
    };
    uint64_t dpArrSize = sizeof(dataPat) / sizeof(dataPat[0]);

    LOG_NRM("Seeking all bare namspc's.");
    vector<uint32_t> bare = gInformative->GetBareNamespaces();
    for (size_t i = 0; i < bare.size(); i++) {
        LOG_NRM("Processing for BARE name space id #%d", bare[i]);
        namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]);
        uint64_t ncap = namSpcPtr->GetValue(IDNAMESPC_NCAP);
        uint64_t lbaDataSize = namSpcPtr->GetLBADataSize();
        uint64_t maxWrBlks = maxDtXferSz / lbaDataSize;

        writeMem->Init(maxWrBlks * lbaDataSize);
        writeCmd->SetPrpBuffer(prpBitmask, writeMem);
        writeCmd->SetNSID(bare[i]);
        writeCmd->SetNLB(maxWrBlks - 1);  // 0 based value.

        readMem->Init(maxWrBlks * lbaDataSize);
        readCmd->SetPrpBuffer(prpBitmask, readMem);
        readCmd->SetNSID(bare[i]);
        readCmd->SetNLB(maxWrBlks - 1);  // 0 based value.

        for (uint64_t nWrBlks = 0; nWrBlks < (ncap - 1); nWrBlks += maxWrBlks) {
            LOG_NRM("Sending #%ld blks of #%ld", nWrBlks, (ncap -1));
            for (uint64_t nLBA = 0; nLBA < maxWrBlks; nLBA++) {
                writeMem->SetDataPattern(dataPat[nLBA % dpArrSize],
                    (nWrBlks + nLBA + 1), (nLBA * lbaDataSize), lbaDataSize);
            }
            writeCmd->SetSLBA(nWrBlks);
            readCmd->SetSLBA(nWrBlks);

            enableLog = false;
            if ((nWrBlks <= maxWrBlks) || (nWrBlks >= (ncap - 2 * maxWrBlks)))
                enableLog = true;
            work = str(boost::format("NSID.%d.SLBA.%ld") % bare[i] % nWrBlks);

            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, writeCmd, work, enableLog);

            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, readCmd, work, enableLog);

            VerifyDataPat(readCmd, writeMem);
        }
    }
}
void
UnsupportRsvdFields_r11b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    SharedDatasetMgmtPtr datasetMgmtCmd =
        SharedDatasetMgmtPtr(new DatasetMgmt());

    uint16_t timeout;
    if (gCmdLine.setAD)
        timeout = 1000;
    else
        timeout = 1;

    ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr();
    for (uint64_t i = 1; i <= idCtrlr->GetValue(IDCTRLRCAP_NN); i++) {
        LOG_NRM("Processing namspc %ld", i);
        datasetMgmtCmd->SetNSID(i);

        LOG_NRM("Create memory to contain 1 dataset range def");
        SharedMemBufferPtr rangeMem = SharedMemBufferPtr(new MemBuffer());
        rangeMem->Init(sizeof(RangeDef), true);
        send_64b_bitmask prpReq =
            (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
        datasetMgmtCmd->SetPrpBuffer(prpReq, rangeMem);

        LOG_NRM("Setup generic range def guidelines");
        RangeDef *rangeDef = (RangeDef *)rangeMem->GetBuffer();
        rangeDef->length = 1;

        if (gCmdLine.setAD)
            datasetMgmtCmd->SetAD(true);

        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(timeout), iosq,
            iocq, datasetMgmtCmd, "none.set", true);

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

        datasetMgmtCmd->SetDword(0xffffffff, 2);
        datasetMgmtCmd->SetDword(0xffffffff, 3);
        datasetMgmtCmd->SetDword(0xffffffff, 4);
        datasetMgmtCmd->SetDword(0xffffffff, 5);
        datasetMgmtCmd->SetDword(0xffffffff, 8);
        datasetMgmtCmd->SetDword(0xffffffff, 9);

        work = datasetMgmtCmd->GetDword(10);
        work |= 0xffffff00;     // Set DW10_b31:8 bits
        datasetMgmtCmd->SetDword(work, 10);

        work = datasetMgmtCmd->GetDword(11);
        work |= 0xfffffff8;     // Set DW11_b31:3 bits
        if (gCmdLine.setAD)
            work |= 0x4; // Set Bit2 AD=1 (Deallocate)
        datasetMgmtCmd->SetDword(work, 11);

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

        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(timeout), iosq,
            iocq, datasetMgmtCmd, "all.set", true);
    }
}
void
UnsupportRsvdFields_r12::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    CE ce;
    vector<uint32_t> activeNamespaces;
    string work;
    LOG_NRM("Admin queue setup");

    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID));
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID));
    LOG_NRM("Test proper");


    LOG_NRM("Form identify cmd for namespace list and associate some buffer");
    SharedIdentifyPtr idCmdNamSpcList = SharedIdentifyPtr(new Identify());
    idCmdNamSpcList->SetCNS(CNS_NamespaceListActive);
    idCmdNamSpcList->SetNSID(0);

    SharedMemBufferPtr idMemNamSpcList = SharedMemBufferPtr(new MemBuffer());
    idMemNamSpcList->InitAlignment(NAMSPC_LIST_SIZE * NAMSPC_ENTRY_SIZE);

    send_64b_bitmask idPrpNamSpc =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    idCmdNamSpcList->SetPrpBuffer(idPrpNamSpc, idMemNamSpcList);

    LOG_NRM("Sending Identify command CNS.%02Xh", CNS_NamespaceListActive);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpcList, "namspcList", true);

    LOG_NRM("Reading in active Namespaces.");
    const uint8_t *data = &((idCmdNamSpcList->GetROPrpBuffer())[0]);

    while ((*((uint32_t *)data) & 0xffff) != 0x0000){
        uint32_t nsid = (*((uint32_t *)data) & 0xffff);
        LOG_NRM("Found active NSID: %08X", nsid);
        activeNamespaces.push_back(nsid);
        data += 4;
    }

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr();

    for (size_t i = 0; i < activeNamespaces.size(); i++) {
        LOG_NRM("Processing namspc %ld", i);
        SharedFlushPtr flushCmd = SharedFlushPtr(new Flush());
        flushCmd->SetNSID(activeNamespaces[i]);

        ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,
            flushCmd, "none.set", true);
        if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){
            throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, "
                    "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC);
        }

        if (ce.n.reserved != 0){
            throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X",
                    ce.n.reserved);
        } else if(ce.n.cmdSpec != 0){
            throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X",
                    ce.n.cmdSpec);
        }

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

        flushCmd->SetDword(0xffffffff, 2);
        flushCmd->SetDword(0xffffffff, 3);
        flushCmd->SetDword(0xffffffff, 4);
        flushCmd->SetDword(0xffffffff, 5);
        flushCmd->SetDword(0xffffffff, 6);
        flushCmd->SetDword(0xffffffff, 7);
        flushCmd->SetDword(0xffffffff, 8);
        flushCmd->SetDword(0xffffffff, 9);
        flushCmd->SetDword(0xffffffff, 10);
        flushCmd->SetDword(0xffffffff, 11);
        flushCmd->SetDword(0xffffffff, 12);
        flushCmd->SetDword(0xffffffff, 13);
        flushCmd->SetDword(0xffffffff, 14);
        flushCmd->SetDword(0xffffffff, 15);

        ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
                iosq, iocq,flushCmd, "all.set", true);
        if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){
            throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, "
                    "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC);
        }

        if (ce.n.reserved != 0){
            throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X",
                    ce.n.reserved);
        } else if(ce.n.cmdSpec != 0){
            throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X",
                    ce.n.cmdSpec);
        }
    }

    // This highestNSID could provide a case where it issues to an inactive NSID
    // In the case of an inactive NSID the error status would be Invalid Field
    /*uint32_t highestNSID = 0;
    for (uint32_t i = 0; i < activeNamespaces.size(); i++){
        if (activeNamespaces[i] > highestNSID)
            highestNSID = activeNamespaces[i];
    }

    if (highestNSID != 0xffffffff){
        SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush());
        invalidFlushCmd->SetNSID(highestNSID + 1);
        // Could be Invalid Field or Invalid Namespace or Format
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,
            invalidFlushCmd, "none.set", true, CESTAT_INVAL_NAMSPC);
    }*/
    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN);
    // Issuing flush cmd with a few invalid NSIDs
    int count = 0;
    for (uint64_t i = 0; pow(2, i) <= 0xffffffff; i++) {
        if (pow(2, i) <= nn)
            continue;
        LOG_NRM("Issue flush cmd with illegal namspc ID=%llu",
                (unsigned long long)i);
        SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush());
        invalidFlushCmd->SetNSID(pow(2, i));
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, invalidFlushCmd, "Flush.Invalid", true, CESTAT_INVAL_NAMSPC);
        count++;
    }
    LOG_NRM("Ran with: %d invalid NSIDs", count);
}
void
PRPOffsetDualPgMultiBlk_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    int64_t X;
    bool enableLog;

    if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
        throw FrmwkEx(HERE);

    LOG_NRM("Create ACQ and ASQ objects which have test life time");
    SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(mFd)))
    acq->Init(5);
    SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd)))
    asq->Init(5);

    IRQ::SetAnySchemeSpecifyNum(2);     // throws upon error

    gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
    if (gCtrlrConfig->SetState(ST_ENABLE) == false)
        throw FrmwkEx(HERE);

    SharedIOCQPtr iocq;
    SharedIOSQPtr iosq;
    InitTstRsrcs(asq, acq, iosq, iocq);

    LOG_NRM("Compute memory page size from CC.MPS.");
    uint8_t mpsRegVal;
    if (gCtrlrConfig->GetMPS(mpsRegVal) == false)
        throw FrmwkEx(HERE, "Unable to get MPS value from CC.");
    uint64_t ccMPS = (uint64_t)(1 << (mpsRegVal + 12));

    LOG_NRM("Get namspc and determine LBA size");
    Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E();
    send_64b_bitmask prpBitmask =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat();
    uint64_t lbaDataSize = (1 << lbaFormat.LBADS);
    LOG_NRM("LBA data size is %ld.", lbaDataSize);

    LOG_NRM("Seeking max data xfer size for chosen namspc");
    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    uint32_t maxDtXferSz = idCmdCtrlr->GetMaxDataXferSize();

    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    writeCmd->SetNSID(namspcData.id);

    SharedReadPtr readCmd = SharedReadPtr(new Read());
    readCmd->SetNSID(namspcData.id);

    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
    SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

    switch (namspcData.type) {
    case Informative::NS_BARE:
        X =  ccMPS - lbaDataSize;
        break;
    case Informative::NS_METAS:
        X =  ccMPS - lbaDataSize;
        LOG_NRM("Allocating separate meta data buffer.");
        if (gRsrcMngr->SetMetaAllocSize(
            lbaFormat.MS * ((2 * ccMPS) / lbaDataSize)) == false) {
            throw FrmwkEx(HERE, "Unable to allocate Meta buffers.");
        }
        writeCmd->AllocMetaBuffer();
        readCmd->AllocMetaBuffer();
        break;
    case Informative::NS_METAI:
        X =  ccMPS - (lbaDataSize + lbaFormat.MS);
        break;
    case Informative::NS_E2ES:
    case Informative::NS_E2EI:
        throw FrmwkEx(HERE, "Deferring work to handle this case in future");
        break;
    }
    if (X < 0) {
        LOG_WARN("CC.MPS < lba data size(LBADS); Can't run test.");
        return;
    }

    DataPattern dataPat;
    uint64_t wrVal;
    uint64_t Y;

    for (int64_t pgOff = 0; pgOff <= X; pgOff += 4) {
        switch (namspcData.type) {
        case Informative::NS_BARE:
        case Informative::NS_METAS:
            Y = ((2 * ccMPS) - pgOff) / lbaDataSize;
            break;
        case Informative::NS_METAI:
            Y = ((2 * ccMPS) - pgOff) / (lbaDataSize + lbaFormat.MS);
            break;
        case Informative::NS_E2ES:
        case Informative::NS_E2EI:
            throw FrmwkEx(HERE, "Deferring work to handle this case in future");
            break;
        }
        for (uint64_t nLBAs = 1; nLBAs <= Y; nLBAs++) {
            LOG_NRM("Sending LBA #%ld of #%ld", nLBAs, Y);
            if ((maxDtXferSz != 0) && (maxDtXferSz < (lbaDataSize * nLBAs))) {
                // If the total data xfer exceeds the maximum data xfer
                // allowed then we break from the inner loop and continue
                // test with next offset (outer loop).
                LOG_WARN("Data xfer size exceeds max allowed, continuing..");
                break;
            }
            if ((nLBAs % 2) != 0) {
                dataPat = DATAPAT_INC_32BIT;
                wrVal = pgOff + nLBAs;
            } else {
                dataPat = DATAPAT_CONST_16BIT;
                wrVal = pgOff + nLBAs;
            }

            uint64_t metabufSz = nLBAs * lbaFormat.MS;
            switch (namspcData.type) {
            case Informative::NS_BARE:
                writeMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff,
                    false);
                readMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false);
                break;
            case Informative::NS_METAS:
                writeMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff,
                    false);
                readMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false);
                writeCmd->SetMetaDataPattern(dataPat, wrVal, 0, metabufSz);
                break;
            case Informative::NS_METAI:
                writeMem->InitOffset1stPage(
                    ((lbaDataSize + lbaFormat.MS) * nLBAs), pgOff, false);
                readMem->InitOffset1stPage(
                    ((lbaDataSize + lbaFormat.MS) * nLBAs), pgOff, false);
                break;
            case Informative::NS_E2ES:
            case Informative::NS_E2EI:
                throw FrmwkEx(HERE,
                    "Deferring work to handle this case in future");
                break;
            }
            work = str(boost::format("pgOff.%d.nlba.%d") % pgOff % nLBAs);
            writeCmd->SetPrpBuffer(prpBitmask, writeMem);
            writeMem->SetDataPattern(dataPat, wrVal);
            writeCmd->SetNLB(nLBAs - 1); // convert to 0 based.

            enableLog = false;
            if ((pgOff <= 8) || (pgOff >= (X - 8)))
                enableLog = true;

            IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
                iocq, writeCmd, work, enableLog);

            readCmd->SetPrpBuffer(prpBitmask, readMem);
            readCmd->SetNLB(nLBAs - 1); // convert to 0 based.

            IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
                iocq, readCmd, work, enableLog);

            VerifyDataPat(readCmd, dataPat, wrVal, metabufSz);
        }
    }
}