Exemplo n.º 1
0
errlHndl_t mboxddShutDown(TARGETING::Target* i_target)
{
    size_t scom_len = sizeof(uint64_t);
    uint64_t scom_data = 0;

    errlHndl_t err = mboxddMaskInterrupts(i_target);

    if(!err)
    {
        // Clear the status reg
        //Turn off Permission to Send
        //Turn off everything possible
        err = deviceOp(DeviceFW::WRITE,
                       i_target,
                       reinterpret_cast<void*>(&scom_data),
                       scom_len,
                       DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
    }

    // Clear any pending stuff
    if(!err)
    {
        err = deviceOp(DeviceFW::READ,
                       i_target,
                       reinterpret_cast<void*>(&scom_data),
                       scom_len,
                       DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_REG_PIB));
    }

    if(!err)
    {
        err = deviceOp(DeviceFW::WRITE,
                       i_target,
                       reinterpret_cast<void*>(&scom_data),
                       scom_len,
                       DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_REG_PIB));
    }

    // Others?

    return err;
}
Exemplo n.º 2
0
errlHndl_t mboxddEnableInterrupts(TARGETING::Target * i_target)
{
    errlHndl_t err = NULL;
    size_t scom_len = sizeof(uint64_t);

    // Setup mailbox intr mask reg
    // Set bits 2,1,0
    // assume we always use mailbox 1
    uint64_t scom_data = (static_cast<uint64_t>(MBOX_DOORBELL_ERROR) |
                          static_cast<uint64_t>(MBOX_HW_ACK) |
                          static_cast<uint64_t>(MBOX_DATA_PENDING)) << 32;

    err = deviceOp(DeviceFW::WRITE,
                   i_target,
                   reinterpret_cast<void*>(&scom_data),
                   scom_len,
                   DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_MASK_PIB_RS));
    return err;
}
Exemplo n.º 3
0
errlHndl_t mboxddMaskInterrupts(TARGETING::Target * i_target)
{
    errlHndl_t err = NULL;

    // Mask off all interrupts
    // Reset intr enable bits by setting the bits in MBOX_DB_INT_MASK_PIB_RC
    uint64_t scom_data = (static_cast<uint64_t>(MBOX_DOORBELL_ERROR) |
                          static_cast<uint64_t>(MBOX_HW_ACK) |
                          static_cast<uint64_t>(MBOX_DATA_PENDING)) << 32;

    size_t scom_len = sizeof(uint64_t);

    err = deviceOp(DeviceFW::WRITE,
                   i_target,
                   reinterpret_cast<void*>(&scom_data),
                   scom_len,
                   DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_MASK_PIB_RC));

    return err;
}
Exemplo n.º 4
0
/**
 * @brief Reads the mailbox PIB error status register
 */
errlHndl_t mboxGetErrStat(TARGETING::Target* i_target,uint64_t &o_status)
{
    errlHndl_t l_err = NULL;
    uint32_t l_64bitBuf[2] = {0};
    size_t l_64bitSize = sizeof(uint64_t);

    do
    {
        l_err = deviceOp(DeviceFW::READ,i_target,
                l_64bitBuf,l_64bitSize,
                DEVICE_XSCOM_ADDRESS(MBOX_DB_ERR_STAT_PIB));
        if (l_err)
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "mboxGetErrStat> Unable to read PIB Error Status");
            break;
        }
        else
        {
            //Check for Illegal Op
            if ((l_64bitBuf[0] & MBOX_ILLEGAL_OP) ==
                 MBOX_ILLEGAL_OP)
            {
                o_status |= MBOX_ILLEGAL_OP;
            }
            //Check for Write Full
            if ((l_64bitBuf[0] & MBOX_DATA_WRITE_ERR) ==
                 MBOX_DATA_WRITE_ERR)
            {
                o_status |= MBOX_DATA_WRITE_ERR;
            }
            //Check for Read Empty
            if ((l_64bitBuf[0] & MBOX_DATA_READ_ERR) ==
                 MBOX_DATA_READ_ERR)
            {
                o_status |= MBOX_DATA_READ_ERR;
            }
            //Check for Parity Error & add address of parity error
            if ((l_64bitBuf[0] & MBOX_PARITY_ERR) ==
                 MBOX_PARITY_ERR)
            {
                o_status |= MBOX_PARITY_ERR;
                uint64_t l_temp = (l_64bitBuf[0] & 0x00FF0000);
                o_status |= (l_temp << 40);
            }
        }
        //Write '1' to Clear Status(16)
        l_64bitBuf[0] = 0x00010000;
        l_err = deviceOp(DeviceFW::WRITE,i_target,
                l_64bitBuf,l_64bitSize,
                DEVICE_XSCOM_ADDRESS(MBOX_DB_ERR_STAT_PIB));
        if (l_err)
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "mboxGetErrStat> Unable to clear PIB Error Status");
            break;
        }

    } while(0);


    return l_err;
}
Exemplo n.º 5
0
/**
 * @brief Performs a mailbox write operation
 */
errlHndl_t mboxWrite(TARGETING::Target* i_target,void* i_buffer,
                         size_t& i_buflen)
{
    errlHndl_t l_err = NULL;
    uint32_t l_64bitBuf[2] = {0};
    size_t l_64bitSize = sizeof(uint64_t);

    do
    {
        //If the expected siZe in bytes is bigger than the max data allowed
        // send back an error.
        if (i_buflen > MBOX_MAX_DATA_BYTES)
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Invalid data length : i_buflen=%d", i_buflen);
            /*@
             * @errortype
             * @moduleid     MBOX::MOD_MBOXDD_WRITE
             * @reasoncode   MBOX::RC_INVALID_LENGTH
             * @userdata1    Target ID String...
             * @userdata2    Data Length
             * @devdesc      MboxDD::write> Invalid data length (> msg_t size)
             * @custdesc     A problem occurred during the
             *               IPL of the system.
             */
            l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                            MBOX::MOD_MBOXDD_WRITE,
                                            MBOX::RC_INVALID_LENGTH,
                                            TARGETING::get_huid(i_target),
                                            TO_UINT64(i_buflen),
                                            true /*Add HB Software Callout*/);

            l_err->collectTrace(MBOX_TRACE_NAME,1024);

            // Set the i_buflen to 0 to indicate no write occured
            i_buflen = 0;

            break;
        }

        // read the DB_STATUS_1A_REG: doorbell status and control 1a
        l_err = deviceOp(DeviceFW::READ,i_target,
                         l_64bitBuf,l_64bitSize,
                         DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
        if (l_err)
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "mboxWrite> Unable to read Doorbell Status/Control Register");
            break;
        }

        /*
         * DB_STATUS_1A_REG: doorbell status and control 1a
         * Bit31(MSB) : Permission to Send Doorbell 1
         * Bit30 : Abort Doorbell 1
         * Bit29 : LBUS Slave B Pending Doorbell 1
         * Bit28 : PIB Slave A Pending Doorbell 1
         * Bit27 : Reserved
         * Bit26 : Xdn Doorbell 1
         * Bit25 : Xup Doorbell 1
         * Bit24 : Reserved
         * Bit23-20 : Header Count PIB Slave A Doorbell 1
         * Bit19-12 : Data Count PIB Slave A Doorbell 1
         * Bit11-8 : Header Count LBUS Slave B Doorbell 1
         * Bit7-0 : Data Count LBUS Slave B Doorbell 1
         */

        //Verify There is no LBUS Pending,
        if ((l_64bitBuf[0] &
            (MBOX_LBUS_SLAVE_B_PND |  MBOX_HDR_PIB_SLAVE_A | MBOX_DATA_PIB_SLAVE_A)) == 0)
        {
            // Current register counter indicating which of the mbox registers
            // to write to
            uint32_t cur_reg_cntr = 0;
            uint32_t l_data[2] = {0};

            // Total number of registers to read to get all the data.
            uint8_t l_numRegsToWrite = (i_buflen*sizeof(uint8_t))/sizeof(uint32_t);

            uint8_t l_numBytesLeft =
              (i_buflen*sizeof(uint8_t))%sizeof(uint32_t);

            if (l_numBytesLeft != 0)
            {
                l_numRegsToWrite++;
            }

            uint32_t *l_buf = static_cast<uint32_t *>(i_buffer);

            // For the write we put the data into the MBOX data registers.
            // MBOX_DATA_PIB_START    = 0x00050040 and the end address is
            // MBOX_DATA_PIB_END      = 0x0005004F
            // each address inbetween increments by 1.

            //Write Data registers.  Start at the first and increment through
            //the registers until all the data has been written.
            while (cur_reg_cntr < l_numRegsToWrite)
            {

                // If this is the last register we need to write and are not word aligned
                if (((cur_reg_cntr + 1) == l_numRegsToWrite) &&
                    (l_numBytesLeft != 0))
                {
                    // zero out the data reg.
                    l_data[0] = 0;

                    // Only copy the number of bytes remaining..
                    memcpy(&l_data[0], l_buf+cur_reg_cntr,l_numBytesLeft);

                }
                else
                {
                    // point to the next 32bits of data in the buffer.
                    l_data[0] = *(l_buf+cur_reg_cntr);

                }

                l_err = deviceOp(DeviceFW::WRITE,i_target,
                                 l_data,l_64bitSize,
                                 DEVICE_XSCOM_ADDRESS(MBOX_DATA_PIB_START+cur_reg_cntr));
                if (l_err)
                {
                    TRACFCOMP(g_trac_mbox, ERR_MRK "mboxWrite> Unable to write Data Area Register 0x%X",MBOX_DATA_PIB_START+cur_reg_cntr);
                    break;
                }
                //increment counter so we are at the next register
                cur_reg_cntr++;
            }
            if (l_err)
            {
                break;
            }

            //Write LBUS Pending(28) and Data Count bits(11-0) to indicate
            // data has been written.
            l_64bitBuf[0] =  MBOX_LBUS_SLAVE_B_PND | (MBOX_DATA_PIB_SLAVE_A &
                                                      (i_buflen << 12));

            l_err = deviceOp(DeviceFW::WRITE,i_target,
                             l_64bitBuf,l_64bitSize,
                             DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));

            if (l_err)
            {
                TRACFCOMP(g_trac_mbox, ERR_MRK "mboxWrite> Unable to set Doorbell Status/Control Register");
                break;
            }
        }
        else
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "mboxWrite> Message still pending : MBOX_DB_STAT_CNTRL_1=%X", l_64bitBuf[0]);
            /*@
             * @errortype
             * @moduleid     MBOX::MOD_MBOXDD_WRITE
             * @reasoncode   MBOX::RC_MSG_PENDING
             * @userdata1    Target ID String...
             * @userdata2    Status/Control Register
             * @devdesc      MboxDD::write> Message still pending
             * @custdesc     A problem occurred during the
             *               IPL of the system.
             */
            l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                        MBOX::MOD_MBOXDD_WRITE,
                                        MBOX::RC_MSG_PENDING,
                                        TARGETING::get_huid(i_target),
                                        reinterpret_cast<uint64_t>(l_64bitBuf),
                                        true /*Add HB Software Callout*/);

            // Set the i_buflen to 0 to indicate no write occured
            i_buflen = 0;
            l_err->collectTrace(MBOX_TRACE_NAME,1024);
            break;
        }

    } while(0);

    return l_err;
}
Exemplo n.º 6
0
/**
 * @brief Performs a mailbox read operation
 */
errlHndl_t mboxRead(TARGETING::Target* i_target,void *o_buffer,
                        size_t &io_buflen,uint64_t* o_status)
{
    uint64_t l_stat = 0;
    errlHndl_t l_err = NULL;
    uint32_t l_64bitBuf[2] = {0};
    uint32_t l_StatusReg[2] = {0};
    uint32_t l_IntReg[2] = {0};
    size_t l_64bitSize = sizeof(uint64_t);
    size_t input_buflen = io_buflen;
    io_buflen = 0;

    do
    {
       // no longer check for buffer length.. MBox DD will pass back the max
       // allowed data if the buflen is > the max size.  This is done prior
       // to reading the data from the mbox registers.

        // Read the Int Reg B
        l_err = deviceOp(DeviceFW::READ,i_target,
                l_IntReg,l_64bitSize,
                DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_REG_PIB));
        if (l_err)
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "mboxRead> Unable to read PIB Interrupt Register");
            break;
        }

        /*if nothing on in the interrupt reg -- nothing for this function to do*/
        if(!(l_IntReg[0]))
        {
            break;
        }

        // Check to see if there is an error bit set.
        if ((l_IntReg[0] & MBOX_DOORBELL_ERROR) ==
             MBOX_DOORBELL_ERROR)
        {
            TRACFCOMP(g_trac_mbox, INFO_MRK
                      "mboxRead> Found interrupt on error status register");
            // Go get the error info
            l_err = mboxGetErrStat(i_target,l_stat);

            if (l_err)
            {
                break;
            }
        }

#if defined(__DESTRUCTIVE_MBOX_TEST__)
        if(g_forceError)
        {
            TRACFCOMP(g_trac_mbox,"MBOXDD> forcing error!");
            g_forceError = false;
            l_stat |= MBOX_DOORBELL_ERROR | MBOX_DATA_WRITE_ERR;
        }
#endif

        // No errors so read the doorbell status and control 1a register
        l_err = deviceOp(DeviceFW::READ,i_target,
                         l_64bitBuf,l_64bitSize,
                         DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
        if (l_err)
        {
            TRACFCOMP(g_trac_mbox, ERR_MRK "mboxRead> Unable to read Doorbell Status/Control Register");
            break;
        }
        /*
         * DB_STATUS_1A_REG: doorbell status and control 1a
         * Bit31(MSB) : Permission to Send Doorbell 1
         * Bit30 : Abort Doorbell 1
         * Bit29 : LBUS Slave B Pending Doorbell 1
         * Bit28 : PIB Slave A Pending Doorbell 1
         * Bit27 : Reserved
         * Bit26 : Xdn Doorbell 1
         * Bit25 : Xup Doorbell 1
         * Bit24 : Reserved
         * Bit23-20 : Header Count PIB Slave A Doorbell 1
         * Bit19-12 : Data Count PIB Slave A Doorbell 1
         * Bit11-8 : Header Count LBUS Slave B Doorbell 1
         * Bit7-0 : Data Count LBUS Slave B Doorbell 1
         */

        //If the Acknowledge bit is on and the Xup bit is on
        if ((l_IntReg[0] & MBOX_HW_ACK) ==
            MBOX_HW_ACK &&
            (l_64bitBuf[0] & MBOX_XUP) == MBOX_XUP)
        {
            l_stat |= MBOX_HW_ACK;
            l_StatusReg[0] |= MBOX_XUP;
        }
        //Check for PIB Pending.  If PIB pending is found then we need
        // to go read the data from the mailbox registers.
        if ((l_IntReg[0] & MBOX_DATA_PENDING) ==
             MBOX_DATA_PENDING &&
            (l_64bitBuf[0] & MBOX_PIB_SLAVE_A_PND) == MBOX_PIB_SLAVE_A_PND)
        {
            l_stat |= MBOX_DATA_PENDING;

            //Set the io_buflen to the number of bytes of data available to
            // be read.
            io_buflen = (l_64bitBuf[0] & MBOX_DATA_LBUS_SLAVE_B);

            // If the buffer length passed in is less than the data size read,
            // then set the buffer length to the passed in size and only read
            // that much data. (truncate the data to fit into the buffer)
            // Conversely, if the input_buflen is greater than the size of the
            // data read, the io_buflen returned to the user becomes the size
            // of the data read.
            if (input_buflen < io_buflen)
            {
                TRACFCOMP(g_trac_mbox, INFO_MRK

                          "mboxRead> Data truncated, input buffer length less than number of significant bytes");
                // set the io_buflen to the size of the buffer passed in.
                // which will only read enough data to fill the buffer.
                io_buflen = input_buflen;
            }

            // Current register counter indicating which of the mbox registers
            // we are currently reading from.
            uint32_t cur_reg_cntr = 0;
            uint32_t l_data[2];

            // Total number of registers to read to get all the data.
            uint8_t l_numRegsToRead = (io_buflen*sizeof(uint8_t))/sizeof(uint32_t);

            uint8_t l_numBytesLeft =
              (io_buflen*sizeof(uint8_t))%sizeof(uint32_t);

            if (l_numBytesLeft != 0)
            {
                l_numRegsToRead++;
            }

            uint32_t *local_buf = static_cast<uint32_t *>(o_buffer);
            // For the read we extract the data from the MBOX data registers.
            // MBOX_DATA_LBUS_START = 0x00050080 and the end address is
            // MBOX_DATA_LBUS_END   = 0x0005008F
            // each address inbetween increments by 1.

            //Loop through the mbox registers until all the data to be read has
            // been extracted from the mbox registers.
            while (cur_reg_cntr < l_numRegsToRead)
            {
                l_err = deviceOp(DeviceFW::READ,i_target,
                                 l_data,l_64bitSize,
                                 DEVICE_XSCOM_ADDRESS(MBOX_DATA_LBUS_START+cur_reg_cntr));
                if (l_err)
                {
                    TRACFCOMP(g_trac_mbox, ERR_MRK "mboxRead> Unable to read Data Area Register 0x%X",MBOX_DATA_LBUS_START+cur_reg_cntr);
                    break;
                }

                // Need to check here to make sure we are not overrunning our
                // buffer.

                // If this is the last register we need to read and we are not word aligned
                if (((cur_reg_cntr + 1) == l_numRegsToRead) &&
                    (l_numBytesLeft != 0))
                {
                    // Only copy the number of bytes remaining..
                    memcpy( local_buf + cur_reg_cntr,
                            &l_data[0], l_numBytesLeft);
                }
                // normal copy path.. copy the entire word.
                else
                {
                    memcpy( local_buf + cur_reg_cntr, &l_data[0], sizeof(uint32_t));
                }

                cur_reg_cntr++;
            }
            if (l_err)
            {
                break;
            }

            //Write-to-Clear Xup,and bits 20-32 (data and header count)
            //Write to set Xup (by setting PIB_SLAVE_PND)
            //Write the Xdn to indicate read is done
            l_StatusReg[0] |= MBOX_PIB_SLAVE_A_PND | MBOX_XDN |
                              MBOX_HDR_LBUS_SLAVE_B | MBOX_DATA_LBUS_SLAVE_B;
        }


        //Write to clear PIB Pending, Abort, and XUP (all that apply)
        if(l_StatusReg[0])
        {
            l_err = deviceOp(DeviceFW::WRITE,i_target,
                             l_StatusReg,l_64bitSize,
                             DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
            if (l_err)
            {
                TRACFCOMP(g_trac_mbox, ERR_MRK "mboxRead> Unable to clear Doorbell Status/Control Register");
                break;
            }
        }

        //Write-to-Clear 'on' bits of interrupt reg
        if(l_IntReg[0])
        {
            l_err = deviceOp(DeviceFW::WRITE,i_target,
                             l_IntReg,l_64bitSize,
                             DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_REG_PIB));
            if (l_err)
            {
                TRACFCOMP(g_trac_mbox, ERR_MRK "mboxRead> Unable to clear PIB Interrupt Register");
                break;
            }
        }
    } while(0);

    (*o_status) = l_stat;


    return l_err;
}
Exemplo n.º 7
0
errlHndl_t doScomOp(DeviceFW::OperationType i_opType,
                    TARGETING::Target* i_target,
                    void* io_buffer,
                    size_t& io_buflen,
                    int64_t i_accessType,
                    uint64_t i_addr)
{

    errlHndl_t l_err = NULL;

    do{
        TARGETING::ScomSwitches scomSetting;
        scomSetting.useXscom = true;  //Default to Xscom supported.
        if(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL != i_target)
        {
            scomSetting =
              i_target->getAttr<TARGETING::ATTR_SCOM_SWITCHES>();
        }

        //Always XSCOM the Master Sentinel
        if((TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL == i_target) ||
            (scomSetting.useXscom))
        {  //do XSCOM

            l_err = deviceOp(i_opType,
                             i_target,
                             io_buffer,
                             io_buflen,
                             DEVICE_XSCOM_ADDRESS(i_addr));
            break;
        }
        else if(scomSetting.useInbandScom)
        {   //do IBSCOM
            l_err = deviceOp(i_opType,
                             i_target,
                             io_buffer,
                             io_buflen,
                             DEVICE_IBSCOM_ADDRESS(i_addr));
            if( l_err ) { break; }
        }
        else if(scomSetting.useFsiScom)
        {   //do FSISCOM
            l_err = deviceOp(i_opType,
                             i_target,
                             io_buffer,
                             io_buflen,
                             DEVICE_FSISCOM_ADDRESS(i_addr));
            if( l_err ) { break; }
        }
        else
        {
            assert(0,"SCOM::scomPerformOp> ATTR_SCOM_SWITCHES does not indicate Xscom, Ibscom, or FSISCOM is supported. i_target=0x%.8x", get_huid(i_target));
            break;
        }

    }while(0);

    //Look for special retry codes
    if( l_err
        && (0xFFFFFFFF != i_accessType)
        && (l_err->reasonCode() == IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR) )
    {
        delete l_err;
        TRACFCOMP(g_trac_scom, "Forcing retry of Scom to %.16X on %.8X", i_addr, TARGETING::get_huid(i_target));
        // use the unused i_accessType parameter to avoid an infinite recursion
        int64_t accessType_flag = 0xFFFFFFFF;
        l_err = doScomOp( i_opType, i_target, io_buffer,
                          io_buflen, accessType_flag, i_addr );
    }

    //Add some additional FFDC based on the specific operation
    if( l_err )
    {
        addScomFailFFDC( l_err, i_target, i_addr );
    }

    return l_err;
}
Exemplo n.º 8
0
/**
 * @brief Collect XSCOM FFDC data and add to the originating xscom failing
 *    errorlog.
 *
 * @param[in]  i_target        XSCom target
 * @param[in]  i_virtAddr      Target's virtual address
 * @param[in/out] io_errl      Originating errorlog that we will add FFDC data
 *                             to
 * @return none
 */
void collectXscomFFDC(TARGETING::Target* i_target,
                            uint64_t* i_virtAddr,
                            errlHndl_t& io_errl)
{
    errlHndl_t l_err = NULL;
    HMER l_hmer;
    uint64_t io_buffer = 0;
    size_t io_buflen = XSCOM_BUFFER_SIZE;
    uint64_t* l_virtAddr = 0;

    // xscom registers that need to be set.
    XscomAddrType_t XscomAddr[4] = { {0x0202000F, CurThreadCpu},
                                     {0x02020004, TargetCpu},
                                     {0x02020007, TargetCpu},
                                     {0x02020009, TargetCpu},};


    TRACFCOMP(g_trac_xscom,"collectXscomFFDC: XSCOM COLLECT FFDC STARTED");

    ERRORLOG::ErrlUserDetailsLogRegister l_logReg(i_target);

    // Loop through the addresses you want to collect.
    for (int i = 0; i<4; i++)
    {

        // If collecting first address, need to collect from Source Chip
        if (XscomAddr[i].target_type == CurThreadCpu)
        {
            l_virtAddr =  getCpuIdVirtualAddress();
        }
        else
        {
            l_virtAddr = i_virtAddr;
        }

        //*********************************************************
        // READ SCOM ADDR
        //*********************************************************
        l_err = xScomDoOp(DeviceFW::READ,
                          l_virtAddr,
                          XscomAddr[i].addr,
                          &io_buffer,
                          io_buflen,
                          l_hmer);

        // If not successful
        if (l_err)
        {
            delete l_err;

            TRACFCOMP(g_trac_xscom,ERR_MRK "XSCOM Collect FFDC FAILED: XscomAddr = %.16llx, VAddr=%llx",XscomAddr[i], l_virtAddr);
        }
        // only add the Register data to the originating errorlog if successful
        else
        {
            // Collect the data from the read
            l_logReg.addDataBuffer(&io_buffer, sizeof(io_buffer),
                                   DEVICE_XSCOM_ADDRESS(XscomAddr[i].addr));
        }

        // unmap the device now that we are done with the scom to that area.
        if (XscomAddr[i].target_type == CurThreadCpu)
        {
            mmio_dev_unmap(reinterpret_cast<void*>(l_virtAddr));
        }

    }

    // Add the register FFDC to the errorlog passed in.
    l_logReg.addToLog(io_errl);

    return;
}
Exemplo n.º 9
0
errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
                         TARGETING::Target* i_target,
                         void* io_buffer,
                         size_t& io_buflen,
                         int64_t i_accessType,
                         va_list i_args)
{
    errlHndl_t l_err = NULL;

    uint64_t l_scomAddr = va_arg(i_args,uint64_t);
    ioData6432 scratchData;
    uint32_t l_command = 0;
    uint32_t l_status = 0;
    bool need_unlock = false;
    size_t op_size = sizeof(uint32_t);
    mutex_t* l_mutex = NULL;

    do{

        if( io_buflen != sizeof(uint64_t) )
        {
            TRACFCOMP( g_trac_fsiscom, ERR_MRK "fsiScomPerformOp> Invalid data length : io_buflen=%d", io_buflen );
            /*@
             * @errortype
             * @moduleid     FSISCOM::MOD_FSISCOM_PERFORMOP
             * @reasoncode   FSISCOM::RC_INVALID_LENGTH
             * @userdata1    SCOM Address
             * @userdata2    Data Length
             * @devdesc      fsiScomPerformOp> Invalid data length (!= 8 bytes)
             * @custdesc     A problem occurred during the IPL of the system:
             *               Invalid data length for a SCOM operation.
             */
            l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                            FSISCOM::MOD_FSISCOM_PERFORMOP,
                                            FSISCOM::RC_INVALID_LENGTH,
                                            l_scomAddr,
                                            TO_UINT64(io_buflen));
            l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
                                        HWAS::SRCI_PRIORITY_LOW );
            ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target").
              addToLog(l_err);
            break;
        }

        if( (l_scomAddr & 0xFFFFFFFF80000000) != 0)
        {
            TRACFCOMP( g_trac_fsiscom, ERR_MRK "fsiScomPerformOp> Address contains more than 31 bits : l_scomAddr=0x%.16X", l_scomAddr );
            /*@
             * @errortype
             * @moduleid     FSISCOM::MOD_FSISCOM_PERFORMOP
             * @reasoncode   FSISCOM::RC_INVALID_ADDRESS
             * @userdata1    SCOM Address
             * @userdata2    Target HUID
             * @devdesc      fsiScomPerformOp> Address contains
             *               more than 31 bits.
             * @custdesc     A problem occurred during the IPL of the system:
             *               Invalid address on a SCOM operation.
             */
            l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                            FSISCOM::MOD_FSISCOM_PERFORMOP,
                                            FSISCOM::RC_INVALID_ADDRESS,
                                            l_scomAddr,
                                            TARGETING::get_huid(i_target));
            l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
                                        HWAS::SRCI_PRIORITY_LOW );
            ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target").
              addToLog(l_err);
            break;
        }

        l_command = static_cast<uint32_t>(l_scomAddr & 0x000000007FFFFFFF);

        // use the chip-specific mutex attribute
        l_mutex = i_target->getHbMutexAttr<TARGETING::ATTR_FSI_SCOM_MUTEX>();

        if(i_opType == DeviceFW::WRITE)
        {
            memcpy(&(scratchData.data64), io_buffer, 8);

            TRACUCOMP( g_trac_fsiscom, "fsiScomPerformOp> Write(l_scomAddr=0x%X, l_data0=0x%X, l_data1=0x%X)", l_scomAddr, scratchData.data32_0, scratchData.data32_1);


            // atomic section >>
            mutex_lock(l_mutex);
            need_unlock = true;


            //write bits 0-31 to data0
            l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
                                        i_target,
                                        &scratchData.data32_0,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(DATA0_REG));
            if(l_err)
            {
                break;
            }

            //write bits 32-63 to data1
            l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
                                        i_target,
                                        &scratchData.data32_1,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(DATA1_REG));
            if(l_err)
            {
                break;
            }

            //write to FSI2PIB command reg starts write operation
             //bit 0 high => write command
            l_command = 0x80000000 | l_command;
            l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
                                        i_target,
                                        &l_command,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(COMMAND_REG));
            if(l_err)
            {
                break;
            }

            //check status reg to see result
            l_err = DeviceFW::deviceOp( DeviceFW::READ,
                                        i_target,
                                        &l_status,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(STATUS_REG));
            if(l_err)
            {
                break;
            }

            // Check the status reg for errors
            if( (l_status & PIB_ERROR_BITS)      // PCB/PIB Errors
                || (l_status & PIB_ABORT_BIT)  ) // PIB Abort
            {
                TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Write: PCB/PIB error received: l_status=0x%X)", l_status);
                /*@
                 * @errortype
                 * @moduleid     FSISCOM::MOD_FSISCOM_PERFORMOP
                 * @reasoncode   FSISCOM::RC_WRITE_ERROR
                 * @userdata1    SCOM Addr
                 * @userdata2[00:31]  Target HUID
                 * @userdata2[32:63]  SCOM Status Reg
                 * @devdesc      fsiScomPerformOp> Error returned
                 *               from SCOM Engine after write
                 * @custdesc     A problem occurred during the IPL of the system:
                 *               Error returned from SCOM engine after write.
                 */
                l_err = new ERRORLOG::ErrlEntry(
                                ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                FSISCOM::MOD_FSISCOM_PERFORMOP,
                                FSISCOM::RC_WRITE_ERROR,
                                l_scomAddr,
                                TWO_UINT32_TO_UINT64(
                                           TARGETING::get_huid(i_target),
                                           l_status));

                // call common error handler to do callouts and recovery
                pib_error_handler( i_target, l_err, l_status, l_scomAddr );

                //Grab the PIB2OPB Status reg for a XSCOM Block error
                if( (l_status & 0x00007000) == 0x00001000 ) //piberr=001
                {
                    //@todo: Switch to external FSI FFDC interfaces RTC:35064
                    TARGETING::Target* l_master = NULL;
                    TARGETING::targetService().
                      masterProcChipTargetHandle(l_master);

                    uint64_t scomdata = 0;
                    size_t scomsize = sizeof(uint64_t);
                    errlHndl_t l_err2 = DeviceFW::deviceOp( DeviceFW::READ,
                                           l_master,
                                           &scomdata,
                                           scomsize,
                                           DEVICE_XSCOM_ADDRESS(0x00020001));
                    if( l_err2 ) {
                        delete l_err2;
                    } else {
                        TRACFCOMP( g_trac_fsiscom, "PIB2OPB Status = %.16X", scomdata );
                    }
                }

                break;
            }

            // atomic section <<
            need_unlock = false;
            mutex_unlock(l_mutex);
        }
        else if(i_opType == DeviceFW::READ)
        {
            TRACUCOMP( g_trac_fsiscom, "fsiScomPerformOp: Read(l_scomAddr=0x%.8X)", l_scomAddr);

            // atomic section >>
            mutex_lock(l_mutex);
            need_unlock = true;


            //write to FSI2PIB command reg starts read operation
            // bit 0 low -> read command
            l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
                                        i_target,
                                        &l_command,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(COMMAND_REG));
            if(l_err)
            {
                break;
            }

            //check ststus reg to see result
            l_err = DeviceFW::deviceOp( DeviceFW::READ,
                                        i_target,
                                        &l_status,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(STATUS_REG));
            if(l_err)
            {
                break;
            }

            // Check the status reg for errors
            if( (l_status & PIB_ERROR_BITS)      // PCB/PIB Errors
                || (l_status & PIB_ABORT_BIT)  ) // PIB Abort
            {
                TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Read: PCB/PIB error received: l_status=0x%0.8X)", l_status);

                /*@
                 * @errortype
                 * @moduleid     FSISCOM::MOD_FSISCOM_PERFORMOP
                 * @reasoncode   FSISCOM::RC_READ_ERROR
                 * @userdata1    SCOM Addr
                 * @userdata2[00:31]  Target HUID
                 * @userdata2[32:63]  SCOM Status Reg
                 * @devdesc      fsiScomPerformOp> Error returned from SCOM Engine after read.
                 * @custdesc     A problem occurred during the IPL of the system:
                 *               Error returned from SCOM engine after read.
                 */
                l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                                FSISCOM::MOD_FSISCOM_PERFORMOP,
                                                FSISCOM::RC_READ_ERROR,
                                                l_scomAddr,
                                                TWO_UINT32_TO_UINT64(
                                                 TARGETING::get_huid(i_target),
                                                 l_status));

                // call common error handler to do callouts and recovery
                pib_error_handler( i_target, l_err, l_status, l_scomAddr );

                break;
            }

            //read bits 0-31 to data0
            l_err = DeviceFW::deviceOp( DeviceFW::READ,
                                        i_target,
                                        &scratchData.data32_0,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(DATA0_REG));
            if(l_err)
            {
                break;
            }

            //read bits 32-63 to data1
            l_err = DeviceFW::deviceOp( DeviceFW::READ,
                                        i_target,
                                        &scratchData.data32_1,
                                        op_size,
                                        DEVICE_FSI_ADDRESS(DATA1_REG));
            if(l_err)
            {
                break;
            }

            // atomic section <<
            need_unlock = false;
            mutex_unlock(l_mutex);

            TRACUCOMP( g_trac_fsiscom, "fsiScomPerformOp: Read: l_scomAddr=0x%X, l_data0=0x%X, l_data1=0x%X", l_scomAddr, scratchData.data32_0, scratchData.data32_1);

             memcpy(io_buffer, &(scratchData.data64), 8);
        }
        else
        {
            TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Unsupported Operation Type: i_opType=%d)", i_opType);

            /*@
             * @errortype
             * @moduleid     FSISCOM::MOD_FSISCOM_PERFORMOP
             * @reasoncode   FSISCOM::RC_INVALID_OPTYPE
             * @userdata1[0:31]    Operation Type (i_opType) : 0=READ, 1=WRITE
             * @userdata1[32:64]   Input scom address
             * @userdata2    Target HUID
             * @devdesc      fsiScomPerformOp> Unsupported Operation Type specified
             * @custdesc     A problem occurred during the IPL of the system:
             *               Unsupported SCOM operation type.
             */
            l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                            FSISCOM::MOD_FSISCOM_PERFORMOP,
                                            FSISCOM::RC_INVALID_OPTYPE,
                                            TWO_UINT32_TO_UINT64(i_opType,
                                                                 l_scomAddr),
                                            TARGETING::get_huid(i_target),
                                            true /*SW error*/);
            //Add this target to the FFDC
            ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target").
              addToLog(l_err);

            break;

        }

    }while(0);

    if( need_unlock && l_mutex )
    {
        mutex_unlock(l_mutex);
    }


    return l_err;

}