示例#1
0
// ----------------------------------------------------------------------------
// IStepDispatcher::writeIstepControl()
// ----------------------------------------------------------------------------
errlHndl_t AST2400BootConfig::writeIstepControl( istepControl_t i_istepCtl )
{
    errlHndl_t l_err = NULL;
    size_t l_len = sizeof(uint8_t);

    // read istep control from 0x2a
    TRACFCOMP( g_bc_trace, "AST2400BootConfig:: Write istep control %x",  i_istepCtl.istepControl);

    do
    {
        //write status
        l_err = deviceOp( DeviceFW::WRITE,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(i_istepCtl.istepStatus),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_STATUS_REG));
        if(l_err) { break; }

        //write command/control
        l_err = deviceOp( DeviceFW::WRITE,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(i_istepCtl.istepControl),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE,
                                             ISTEP_HOST_CTL_REG));
        if(l_err) { break; }
    }
    while(0);

    return l_err;
}
示例#2
0
// ----------------------------------------------------------------------------
// readIstepControl()
// ----------------------------------------------------------------------------
errlHndl_t AST2400BootConfig::readIstepControl( istepControl_t &o_stepInfo )
{
    errlHndl_t l_err = NULL;
    size_t l_len = sizeof(uint8_t);
    do
    {
        // read istep control from 0x2a
        l_err = deviceOp( DeviceFW::READ,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(o_stepInfo.istepControl),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_CONTROL_REG));
        if(l_err) { break; }

        // read major number from 0x2b
        l_err = deviceOp( DeviceFW::READ,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(o_stepInfo.istepMajorNumber),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_MAJOR_REG));
        if(l_err) { break; }

        // read minor number from 0x2c
        l_err = deviceOp( DeviceFW::READ,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(o_stepInfo.istepMinorNumber),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_MINOR_REG));
    }
    while(0);

    return l_err;
}
示例#3
0
errlHndl_t gpioWrite ( TARGETING::Target * i_target,
                     void * i_buffer,
                     size_t i_buflen,
                     gpioAddr_t & i_gpioInfo)
{
    errlHndl_t err = NULL;

    size_t cmdlen = GPIO_ADDR_SIZE + i_buflen;
    uint8_t cmd[cmdlen];
    cmd[0] = i_gpioInfo.portAddr;
    memcpy(&(cmd[GPIO_ADDR_SIZE]), i_buffer, i_buflen);

    err = deviceOp( DeviceFW::WRITE,
                    i_target,
                    &cmd,
                    cmdlen,
                    DEVICE_I2C_ADDRESS
                    ( i_gpioInfo.i2cPort,
                      i_gpioInfo.engine,
                      i_gpioInfo.i2cDeviceAddr,
                      i_gpioInfo.i2cMuxBusSelector,
                      &(i_gpioInfo.i2cMuxPath)
                    )
                  );
    if(err)
    {
        err->collectTrace( GPIO_COMP_NAME );
    }

    return err;
}
示例#4
0
errlHndl_t gpioRead( TARGETING::Target * i_target,
                     void * o_buffer,
                     size_t & io_buflen,
                     gpioAddr_t & i_gpioInfo)
{
    errlHndl_t err = NULL;

    // This i2c interface writes the gpio portAddr to the device
    // then reads the value of the port w/o a stop bit in between ops
    err = deviceOp( DeviceFW::READ,
                    i_target,
                    o_buffer,
                    io_buflen,
                    DEVICE_I2C_ADDRESS_OFFSET
                    ( i_gpioInfo.i2cPort,
                      i_gpioInfo.engine,
                      i_gpioInfo.i2cDeviceAddr,
                      GPIO_ADDR_SIZE,
                      reinterpret_cast<uint8_t*>(&(i_gpioInfo.portAddr)),
                      i_gpioInfo.i2cMuxBusSelector,
                      &(i_gpioInfo.i2cMuxPath)
                    )
                  );
    if(err)
    {
        err->collectTrace( GPIO_COMP_NAME );
    }

    return err;
}
示例#5
0
    ///
    /// @brief  Receive - get bits off the block-transfer interface
    ///
    errlHndl_t BTMessage::recv(void)
    {
        // Check to make sure we are in the right state (coding error)
        assert(iv_data == NULL);

        // Go down to the device and read. Note the driver is BT specific
        // and we're BT specific so we can send down a BTMessage object.
        size_t unused_length;
        errlHndl_t err = deviceOp(DeviceFW::READ,
                               TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                               static_cast<void*>(this),
                               unused_length,
                               DeviceFW::IPMIBT);
        if (err)
        {
            delete[] iv_data;

            // If the reading the response fails, the caller may still call
            // delete[] on the pointer we return to them. This makes sure that
            // for this case, they're just deleting NULL.
            iv_data = NULL;
            iv_len = 0;
        }

        // For BT messages, the sequence number is the key - for other xports
        // it might be different. Note the sequence number is a reference to
        // our base's iv_key, so we're done.
        return err;
    }
示例#6
0
文件: mboxdd.C 项目: bjwyman/hostboot
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;
}
示例#7
0
    ///
    /// @brief  Transimit - send the data out the device interface
    ///
    errlHndl_t BTMessage::phy_xmit(void)
    {
        // When a uint8_t is constructed, it's initialied to 0. So,
        // this initializes the sequence counter to 0.
        static Util::Lockfree::Counter<uint8_t> seq;

        // Assign a "unique" sequence number. Note that we don't
        // leverage the network function to create a sequence
        // number, we just keep an 8 bit counter. This *should*
        // be ok - it means we will get back the response to any
        // particular message before we send another 254 messages.
        // This seems safe.
        iv_seq = seq.next();

        // Initialize the error state of the message
        iv_state = 0;

        size_t unused_size;
        errlHndl_t err = deviceOp(DeviceFW::WRITE,
                              TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                              static_cast<void*>(this),
                              unused_size,
                              DeviceFW::IPMIBT);

        // If we're not going to remain on the i_sendq, we need to delete
        // the data.
        if ((err) || (iv_state != EAGAIN))
        {
            delete[] iv_data;
            iv_data = NULL;
        }

        if (!err)
        {
            // If there wasn't an error, and we don't see EAGAIN, we need to
            // queue up for a response. Note we queue up both synchronus and
            // asynchronous messages, and let the subclasses handle what
            // happens when the response arrives (because it will.)
            if (iv_state != EAGAIN)
            {
                Singleton<IpmiRP>::instance().queueForResponse(*this);
            }

            // Otherwise we had no error, but were told EAGAIN, which means the
            // interface was busy.
            else
            {
                IPMI_TRAC(INFO_MRK "busy, queue head %x:%x", iv_netfun, iv_cmd);
            }
        }

        return err;
    }
示例#8
0
文件: mboxdd.C 项目: bjwyman/hostboot
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;
}
示例#9
0
文件: mboxdd.C 项目: bjwyman/hostboot
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;
}
示例#10
0
文件: mboxdd.C 项目: bjwyman/hostboot
/**
 * @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;
}
示例#11
0
文件: mboxdd.C 项目: bjwyman/hostboot
/**
 * @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;
}
示例#12
0
文件: mboxdd.C 项目: bjwyman/hostboot
/**
 * @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;
}
示例#13
0
文件: scom.C 项目: bjwyman/hostboot
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;
}
示例#14
0
// ----------------------------------------------------------------------------
// readAndProcessBootConfig()
// ----------------------------------------------------------------------------
errlHndl_t AST2400BootConfig::readAndProcessBootConfig()
{

    TRACDCOMP(g_bc_trace, ENTER_MRK"readAndProcessBootConfig()");

    errlHndl_t l_err = NULL;

    uint8_t register_data = 0;
    size_t l_len = sizeof(uint8_t);
    do
    {
        // read the register holding the agreed upon magic
        // number to indicate registers have been configured

        // Registers below 0x30 do not belong to any particular SIO device.
        // Device field advised to be set to SUART1 or iLPC2AHB as these are the
        // only two devices currently in use and will thereby save additional
        // SIO before and after this call.
        l_err = deviceOp( DeviceFW::READ,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(register_data),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE, BOOT_FLAGS_VERSION_REG));
        if( l_err )
        {
            TRACFCOMP(g_bc_trace,"Failed reading the boot flags version, skip processing");
            break;
        }

        if( register_data != BOOT_FLAGS_VERSION_1 )
        {

            TRACFCOMP(g_bc_trace,"WRN>>readAndProcessBootConfig() - "
                    "boot flags not correct version"
                    " 0x%x!=0x%x", register_data, BOOT_FLAGS_VERSION_1 );

#ifdef CONFIG_CONSOLE
            CONSOLE::displayf(NULL, "Ignoring boot flags, incorrect version 0x%x", register_data);
            CONSOLE::flush();
#endif

            break;
        }

        // read the SIO register holding the boot flags
        l_err = deviceOp( DeviceFW::READ,
                          TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
                          &(register_data),
                          l_len,
                          DEVICE_SIO_ADDRESS(SIO::DONT_CARE, BOOT_FLAGS_REG));
        if( l_err )
        {
            TRACFCOMP(g_bc_trace,"Failed reading the boot flags, leave"
                    " settings at default values");

            break;
        }

        processBootFlagsV1( register_data );

    }while(0);

    TRACDCOMP(g_bc_trace, EXIT_MRK"readAndProcessBootConfig()");

    return l_err;
}