<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QScreen>
#include <QTimer>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QIcon>
#include <QTranslator>
#include <QDebug>
#include <QEvent>
#include <systemd/sd-daemon.h>

#include "notifications/notificationmanager.h"
#include "notifications/notificationpreviewpresenter.h"
#include "notifications/batterynotifier.h"
#include "notifications/diskspacenotifier.h"
#include "notifications/thermalnotifier.h"
#include "screenlock/screenlock.h"
#include "screenlock/screenlockadaptor.h"
#include "devicelock/devicelock.h"
#include "devicelock/devicelockadaptor.h"
#include "lipsticksettings.h"
#include "homeapplication.h"
#include "homewindow.h"
#include "compositor/lipstickcompositor.h"
#include "compositor/lipstickcompositorwindow.h"
#include "lipstickdbus.h"

#include "volume/volumecontrol.h"
#include "usbmodeselector.h"
#include "shutdownscreen.h"
#include "shutdownscreenadaptor.h"
#include "connectionselector.h"
#include "screenshotservice.h"
#include "screenshotserviceadaptor.h"

void HomeApplication::quitSignalHandler(int)
{
    qApp->quit();
}

static void registerDBusObject(QDBusConnection &bus, const char *path, QObject *object)
{
    if (!bus.registerObject(path, object)) {
        qWarning("Unable to register object at path %s: %s", path, bus.lastError().message().toUtf8().constData());
    }
}

HomeApplication::HomeApplication(int &argc, char **argv, const QString &qmlPath)
    : QGuiApplication(argc, argv)
    , _mainWindowInstance(0)
    , _qmlPath(qmlPath)
    , originalSigIntHandler(signal(SIGINT, quitSignalHandler))
    , originalSigTermHandler(signal(SIGTERM, quitSignalHandler))
    , homeReadySent(false)
{
    setApplicationName("Lipstick");
    // TODO: autogenerate this from tags
    setApplicationVersion(VERSION);

    QTranslator *engineeringEnglish = new QTranslator(this);
    engineeringEnglish->load("lipstick_eng_en", "/usr/share/translations");
    installTranslator(engineeringEnglish);
    QTranslator *translator = new QTranslator(this);
    translator->load(QLocale(), "lipstick", "-", "/usr/share/translations");
    installTranslator(translator);

    // Initialize the QML engine
    qmlEngine = new QQmlEngine(this);

    // Initialize the notification manager
    NotificationManager::instance();
    new NotificationPreviewPresenter(this);

    // Create screen lock logic - not parented to "this" since destruction happens too late in that case
    screenLock = new ScreenLock;
    LipstickSettings::instance()->setScreenLock(screenLock);
    new ScreenLockAdaptor(screenLock);

    deviceLock = new DeviceLock(this);
    new DeviceLockAdaptor(deviceLock);

    volumeControl = new VolumeControl;
    new BatteryNotifier(this);
    new DiskSpaceNotifier(this);
    new ThermalNotifier(this);
    usbModeSelector = new USBModeSelector(this);
    connect(usbModeSelector, SIGNAL(dialogShown()), screenLock, SLOT(unlockScreen()));
    shutdownScreen = new ShutdownScreen(this);
    new ShutdownScreenAdaptor(shutdownScreen);
    connectionSelector = new ConnectionSelector(this);

    // MCE and usb-moded expect services to be registered on the system bus
    QDBusConnection systemBus = QDBusConnection::systemBus();
    if (!systemBus.registerService(LIPSTICK_DBUS_SERVICE_NAME)) {
        qWarning("Unable to register D-Bus service %s: %s", LIPSTICK_DBUS_SERVICE_NAME, systemBus.lastError().message().toUtf8().constData());
    }

    registerDBusObject(systemBus, LIPSTICK_DBUS_SCREENLOCK_PATH, screenLock);
    registerDBusObject(systemBus, LIPSTICK_DBUS_DEVICELOCK_PATH, deviceLock);
    registerDBusObject(systemBus, LIPSTICK_DBUS_SHUTDOWN_PATH, shutdownScreen);

    ScreenshotService *screenshotService = new ScreenshotService(this);
    new ScreenshotServiceAdaptor(screenshotService);
    QDBusConnection sessionBus = QDBusConnection::sessionBus();

    registerDBusObject(sessionBus, LIPSTICK_DBUS_SCREENSHOT_PATH, screenshotService);

    // Setting up the context and engine things
    qmlEngine->rootContext()->setContextProperty("initialSize", QGuiApplication::primaryScreen()->size());
    qmlEngine->rootContext()->setContextProperty("lipstickSettings", LipstickSettings::instance());
    qmlEngine->rootContext()->setContextProperty("LipstickSettings", LipstickSettings::instance());
    qmlEngine->rootContext()->setContextProperty("deviceLock", deviceLock);
    qmlEngine->rootContext()->setContextProperty("volumeControl", volumeControl);

    connect(this, SIGNAL(homeReady()), this, SLOT(sendStartupNotifications()));
}

HomeApplication::~HomeApplication()
{
    emit aboutToDestroy();

    delete volumeControl;
    delete screenLock;
    delete _mainWindowInstance;
    delete qmlEngine;
}

HomeApplication *HomeApplication::instance()
{
    return qobject_cast<HomeApplication *>(qApp);
}

void HomeApplication::restoreSignalHandlers()
{
    signal(SIGINT, originalSigIntHandler);
    signal(SIGTERM, originalSigTermHandler);
}

void HomeApplication::sendHomeReadySignalIfNotAlreadySent()
{
    if (!homeReadySent) {
        homeReadySent = true;
        disconnect(LipstickCompositor::instance(), SIGNAL(frameSwapped()), this, SLOT(sendHomeReadySignalIfNotAlreadySent()));

        emit homeReady();
    }
}

void HomeApplication::sendStartupNotifications()
{
    static QDBusConnection systemBus = QDBusConnection::systemBus();
    QDBusMessage homeReadySignal =
        QDBusMessage::createSignal("/com/nokia/duihome",
                                   "com.nokia.duihome.readyNotifier",
                                   "ready");
    systemBus.send(homeReadySignal);

    /* Let systemd know that we are initialized */
    if (arguments().indexOf("--systemd") >= 0) {
        sd_notify(0, "READY=1");
    }

    /* Let timed know that the UI is up */
    systemBus.call(QDBusMessage::createSignal("/com/nokia/startup/signal", "com.nokia.startup.signal", "desktop_visible"), QDBus::NoBlock);
}

bool HomeApplication::homeActive() const
{
    LipstickCompositor *c = LipstickCompositor::instance();
    return c?c->homeActive():(QGuiApplication::focusWindow() != 0);
}

bool HomeApplication::event(QEvent *e)
{
    bool rv = QGuiApplication::event(e);
    if (LipstickCompositor::instance() == 0 &&
        (e->type() == QEvent::ApplicationActivate ||
         e->type() == QEvent::ApplicationDeactivate))
        emit homeActiveChanged();
    return rv;
}

const QString &HomeApplication::qmlPath() const
{
    return _qmlPath;
}

void HomeApplication::setQmlPath(const QString &path)
{
    _qmlPath = path;

    if (_mainWindowInstance) {
        _mainWindowInstance->setSource(path);
        if (_mainWindowInstance->hasErrors()) {
            qWarning() << "HomeApplication: Errors while loading" << path;
            qWarning() << _mainWindowInstance->errors();
        }
    }
}

const QString &HomeApplication::compositorPath() const
{
    return _compositorPath;
}

void HomeApplication::setCompositorPath(const QString &path)
{
    if (path.isEmpty()) {
        qWarning() << "HomeApplication: Invalid empty compositor path";
        return;
    }

    if (!_compositorPath.isEmpty()) {
        qWarning() << "HomeApplication: Compositor already set";
        return;
    }

    _compositorPath = path;
    QQmlComponent component(qmlEngine, QUrl(path));
    if (component.isError()) {
        qWarning() << "HomeApplication: Errors while loading compositor from" << path;
        qWarning() << component.errors();
        return;
    }

    QObject *compositor = component.beginCreate(qmlEngine->rootContext());
    if (compositor) {
        compositor->setParent(this);
        if (LipstickCompositor::instance())
            LipstickCompositor::instance()->setGeometry(QRect(QPoint(0, 0), QGuiApplication::primaryScreen()->size()));

        component.completeCreate();

        if (!qmlEngine->incubationController() && LipstickCompositor::instance()) {
            // install default incubation controller
            qmlEngine->setIncubationController(LipstickCompositor::instance()->incubationController());
        }

        if (LipstickCompositor::instance())
            LipstickCompositor::instance()->show();
    } else {
        qWarning() << "HomeApplication: Error creating compositor from" << path;
        qWarning() << component.errors();
    }
}

HomeWindow *HomeApplication::mainWindowInstance()
{
    if (_mainWindowInstance)
        return _mainWindowInstance;

    _mainWindowInstance = new HomeWindow();
    _mainWindowInstance->setGeometry(QRect(QPoint(), QGuiApplication::primaryScreen()->size()));
    _mainWindowInstance->setWindowTitle("Home");
    QObject::connect(_mainWindowInstance->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
    QObject::connect(_mainWindowInstance, SIGNAL(visibleChanged(bool)), this, SLOT(connectFrameSwappedSignal(bool)));

    // Setting the source, if present
    if (!_qmlPath.isEmpty())
        _mainWindowInstance->setSource(_qmlPath);

    return _mainWindowInstance;
}

QQmlEngine *HomeApplication::engine() const
{
    return qmlEngine;
}

void HomeApplication::connectFrameSwappedSignal(bool mainWindowVisible)
{
    if (!homeReadySent && mainWindowVisible) {
        connect(LipstickCompositor::instance(), SIGNAL(frameSwapped()), this, SLOT(sendHomeReadySignalIfNotAlreadySent()));
    }
}
<commit_msg>[lipstick] Set translated application name<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QScreen>
#include <QTimer>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QIcon>
#include <QTranslator>
#include <QDebug>
#include <QEvent>
#include <systemd/sd-daemon.h>

#include "notifications/notificationmanager.h"
#include "notifications/notificationpreviewpresenter.h"
#include "notifications/batterynotifier.h"
#include "notifications/diskspacenotifier.h"
#include "notifications/thermalnotifier.h"
#include "screenlock/screenlock.h"
#include "screenlock/screenlockadaptor.h"
#include "devicelock/devicelock.h"
#include "devicelock/devicelockadaptor.h"
#include "lipsticksettings.h"
#include "homeapplication.h"
#include "homewindow.h"
#include "compositor/lipstickcompositor.h"
#include "compositor/lipstickcompositorwindow.h"
#include "lipstickdbus.h"

#include "volume/volumecontrol.h"
#include "usbmodeselector.h"
#include "shutdownscreen.h"
#include "shutdownscreenadaptor.h"
#include "connectionselector.h"
#include "screenshotservice.h"
#include "screenshotserviceadaptor.h"

void HomeApplication::quitSignalHandler(int)
{
    qApp->quit();
}

static void registerDBusObject(QDBusConnection &bus, const char *path, QObject *object)
{
    if (!bus.registerObject(path, object)) {
        qWarning("Unable to register object at path %s: %s", path, bus.lastError().message().toUtf8().constData());
    }
}

HomeApplication::HomeApplication(int &argc, char **argv, const QString &qmlPath)
    : QGuiApplication(argc, argv)
    , _mainWindowInstance(0)
    , _qmlPath(qmlPath)
    , originalSigIntHandler(signal(SIGINT, quitSignalHandler))
    , originalSigTermHandler(signal(SIGTERM, quitSignalHandler))
    , homeReadySent(false)
{
    // TODO: autogenerate this from tags
    setApplicationVersion(VERSION);

    QTranslator *engineeringEnglish = new QTranslator(this);
    engineeringEnglish->load("lipstick_eng_en", "/usr/share/translations");
    installTranslator(engineeringEnglish);
    QTranslator *translator = new QTranslator(this);
    translator->load(QLocale(), "lipstick", "-", "/usr/share/translations");
    installTranslator(translator);

    // Set the application name, as used in notifications
    //% "System"
    setApplicationName(qtTrId("qtn_ap_lipstick"));

    // Initialize the QML engine
    qmlEngine = new QQmlEngine(this);

    // Initialize the notification manager
    NotificationManager::instance();
    new NotificationPreviewPresenter(this);

    // Create screen lock logic - not parented to "this" since destruction happens too late in that case
    screenLock = new ScreenLock;
    LipstickSettings::instance()->setScreenLock(screenLock);
    new ScreenLockAdaptor(screenLock);

    deviceLock = new DeviceLock(this);
    new DeviceLockAdaptor(deviceLock);

    volumeControl = new VolumeControl;
    new BatteryNotifier(this);
    new DiskSpaceNotifier(this);
    new ThermalNotifier(this);
    usbModeSelector = new USBModeSelector(this);
    connect(usbModeSelector, SIGNAL(dialogShown()), screenLock, SLOT(unlockScreen()));
    shutdownScreen = new ShutdownScreen(this);
    new ShutdownScreenAdaptor(shutdownScreen);
    connectionSelector = new ConnectionSelector(this);

    // MCE and usb-moded expect services to be registered on the system bus
    QDBusConnection systemBus = QDBusConnection::systemBus();
    if (!systemBus.registerService(LIPSTICK_DBUS_SERVICE_NAME)) {
        qWarning("Unable to register D-Bus service %s: %s", LIPSTICK_DBUS_SERVICE_NAME, systemBus.lastError().message().toUtf8().constData());
    }

    registerDBusObject(systemBus, LIPSTICK_DBUS_SCREENLOCK_PATH, screenLock);
    registerDBusObject(systemBus, LIPSTICK_DBUS_DEVICELOCK_PATH, deviceLock);
    registerDBusObject(systemBus, LIPSTICK_DBUS_SHUTDOWN_PATH, shutdownScreen);

    ScreenshotService *screenshotService = new ScreenshotService(this);
    new ScreenshotServiceAdaptor(screenshotService);
    QDBusConnection sessionBus = QDBusConnection::sessionBus();

    registerDBusObject(sessionBus, LIPSTICK_DBUS_SCREENSHOT_PATH, screenshotService);

    // Setting up the context and engine things
    qmlEngine->rootContext()->setContextProperty("initialSize", QGuiApplication::primaryScreen()->size());
    qmlEngine->rootContext()->setContextProperty("lipstickSettings", LipstickSettings::instance());
    qmlEngine->rootContext()->setContextProperty("LipstickSettings", LipstickSettings::instance());
    qmlEngine->rootContext()->setContextProperty("deviceLock", deviceLock);
    qmlEngine->rootContext()->setContextProperty("volumeControl", volumeControl);

    connect(this, SIGNAL(homeReady()), this, SLOT(sendStartupNotifications()));
}

HomeApplication::~HomeApplication()
{
    emit aboutToDestroy();

    delete volumeControl;
    delete screenLock;
    delete _mainWindowInstance;
    delete qmlEngine;
}

HomeApplication *HomeApplication::instance()
{
    return qobject_cast<HomeApplication *>(qApp);
}

void HomeApplication::restoreSignalHandlers()
{
    signal(SIGINT, originalSigIntHandler);
    signal(SIGTERM, originalSigTermHandler);
}

void HomeApplication::sendHomeReadySignalIfNotAlreadySent()
{
    if (!homeReadySent) {
        homeReadySent = true;
        disconnect(LipstickCompositor::instance(), SIGNAL(frameSwapped()), this, SLOT(sendHomeReadySignalIfNotAlreadySent()));

        emit homeReady();
    }
}

void HomeApplication::sendStartupNotifications()
{
    static QDBusConnection systemBus = QDBusConnection::systemBus();
    QDBusMessage homeReadySignal =
        QDBusMessage::createSignal("/com/nokia/duihome",
                                   "com.nokia.duihome.readyNotifier",
                                   "ready");
    systemBus.send(homeReadySignal);

    /* Let systemd know that we are initialized */
    if (arguments().indexOf("--systemd") >= 0) {
        sd_notify(0, "READY=1");
    }

    /* Let timed know that the UI is up */
    systemBus.call(QDBusMessage::createSignal("/com/nokia/startup/signal", "com.nokia.startup.signal", "desktop_visible"), QDBus::NoBlock);
}

bool HomeApplication::homeActive() const
{
    LipstickCompositor *c = LipstickCompositor::instance();
    return c?c->homeActive():(QGuiApplication::focusWindow() != 0);
}

bool HomeApplication::event(QEvent *e)
{
    bool rv = QGuiApplication::event(e);
    if (LipstickCompositor::instance() == 0 &&
        (e->type() == QEvent::ApplicationActivate ||
         e->type() == QEvent::ApplicationDeactivate))
        emit homeActiveChanged();
    return rv;
}

const QString &HomeApplication::qmlPath() const
{
    return _qmlPath;
}

void HomeApplication::setQmlPath(const QString &path)
{
    _qmlPath = path;

    if (_mainWindowInstance) {
        _mainWindowInstance->setSource(path);
        if (_mainWindowInstance->hasErrors()) {
            qWarning() << "HomeApplication: Errors while loading" << path;
            qWarning() << _mainWindowInstance->errors();
        }
    }
}

const QString &HomeApplication::compositorPath() const
{
    return _compositorPath;
}

void HomeApplication::setCompositorPath(const QString &path)
{
    if (path.isEmpty()) {
        qWarning() << "HomeApplication: Invalid empty compositor path";
        return;
    }

    if (!_compositorPath.isEmpty()) {
        qWarning() << "HomeApplication: Compositor already set";
        return;
    }

    _compositorPath = path;
    QQmlComponent component(qmlEngine, QUrl(path));
    if (component.isError()) {
        qWarning() << "HomeApplication: Errors while loading compositor from" << path;
        qWarning() << component.errors();
        return;
    }

    QObject *compositor = component.beginCreate(qmlEngine->rootContext());
    if (compositor) {
        compositor->setParent(this);
        if (LipstickCompositor::instance())
            LipstickCompositor::instance()->setGeometry(QRect(QPoint(0, 0), QGuiApplication::primaryScreen()->size()));

        component.completeCreate();

        if (!qmlEngine->incubationController() && LipstickCompositor::instance()) {
            // install default incubation controller
            qmlEngine->setIncubationController(LipstickCompositor::instance()->incubationController());
        }

        if (LipstickCompositor::instance())
            LipstickCompositor::instance()->show();
    } else {
        qWarning() << "HomeApplication: Error creating compositor from" << path;
        qWarning() << component.errors();
    }
}

HomeWindow *HomeApplication::mainWindowInstance()
{
    if (_mainWindowInstance)
        return _mainWindowInstance;

    _mainWindowInstance = new HomeWindow();
    _mainWindowInstance->setGeometry(QRect(QPoint(), QGuiApplication::primaryScreen()->size()));
    _mainWindowInstance->setWindowTitle("Home");
    QObject::connect(_mainWindowInstance->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
    QObject::connect(_mainWindowInstance, SIGNAL(visibleChanged(bool)), this, SLOT(connectFrameSwappedSignal(bool)));

    // Setting the source, if present
    if (!_qmlPath.isEmpty())
        _mainWindowInstance->setSource(_qmlPath);

    return _mainWindowInstance;
}

QQmlEngine *HomeApplication::engine() const
{
    return qmlEngine;
}

void HomeApplication::connectFrameSwappedSignal(bool mainWindowVisible)
{
    if (!homeReadySent && mainWindowVisible) {
        connect(LipstickCompositor::instance(), SIGNAL(frameSwapped()), this, SLOT(sendHomeReadySignalIfNotAlreadySent()));
    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_vas_scom.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_vas_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr auto literal_0x00000100000D7FFF = 0x00000100000D7FFF;
constexpr auto literal_0x0000000000000FFF = 0x0000000000000FFF;
constexpr auto literal_0x00FF0203C00C0FFF = 0x00FF0203C00C0FFF;
constexpr auto literal_0x1 = 0x1;

fapi2::ReturnCode p9_vas_scom(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT0,
                              const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& TGT1)
{
    fapi2::ReturnCode l_rc = 0;

    do
    {
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            l_rc = fapi2::getScom( TGT0, 0x3011803ull, l_scom_buffer );

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: getScom (0x3011803ull)");
                break;
            }

            {
                l_scom_buffer.insert<uint64_t> (literal_0x00000100000D7FFF, 0, 54, 0 );
            }

            l_rc = fapi2::putScom(TGT0, 0x3011803ull, l_scom_buffer);

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: putScom (0x3011803ull)");
                break;
            }
        }
        {
            l_rc = fapi2::getScom( TGT0, 0x3011806ull, l_scom_buffer );

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: getScom (0x3011806ull)");
                break;
            }

            {
                l_scom_buffer.insert<uint64_t> (literal_0x0000000000000FFF, 0, 54, 0 );
            }

            l_rc = fapi2::putScom(TGT0, 0x3011806ull, l_scom_buffer);

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: putScom (0x3011806ull)");
                break;
            }
        }
        {
            l_rc = fapi2::getScom( TGT0, 0x3011807ull, l_scom_buffer );

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: getScom (0x3011807ull)");
                break;
            }

            {
                l_scom_buffer.insert<uint64_t> (literal_0x00FF0203C00C0FFF, 0, 54, 0 );
            }

            l_rc = fapi2::putScom(TGT0, 0x3011807ull, l_scom_buffer);

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: putScom (0x3011807ull)");
                break;
            }
        }
        {
            l_rc = fapi2::getScom( TGT0, 0x301184dull, l_scom_buffer );

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: getScom (0x301184dull)");
                break;
            }

            {
                l_scom_buffer.insert<uint64_t> (literal_0x1, 19, 1, 63 );
            }

            l_rc = fapi2::putScom(TGT0, 0x301184dull, l_scom_buffer);

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: putScom (0x301184dull)");
                break;
            }
        }
        fapi2::ATTR_PROC_FABRIC_ADDR_BAR_MODE_Type l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE;
        l_rc = FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_ADDR_BAR_MODE, TGT1, l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE);

        if (l_rc)
        {
            FAPI_ERR("ERROR executing: FAPI_ATTR_GET (ATTR_PROC_FABRIC_ADDR_BAR_MODE)");
            break;
        }

        {
            l_rc = fapi2::getScom( TGT0, 0x301184eull, l_scom_buffer );

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: getScom (0x301184eull)");
                break;
            }

            {
                if ((l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_SMALL_SYSTEM))
                {
                    constexpr auto l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_ON = 0x1;
                    l_scom_buffer.insert<uint64_t> (l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_ON, 13, 1, 63 );
                }
                else if ((l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM))
                {
                    constexpr auto l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_OFF = 0x0;
                    l_scom_buffer.insert<uint64_t> (l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_OFF, 13, 1, 63 );
                }
            }

            l_rc = fapi2::putScom(TGT0, 0x301184eull, l_scom_buffer);

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: putScom (0x301184eull)");
                break;
            }
        }

        {
            l_rc = fapi2::getScom( TGT0, 0x301184full, l_scom_buffer );

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: getScom (0x301184full)");
                break;
            }

            {
                l_scom_buffer.insert<uint64_t> (literal_0x1, 0, 1, 63 );
            }

            l_rc = fapi2::putScom(TGT0, 0x301184full, l_scom_buffer);

            if (l_rc)
            {
                FAPI_ERR("ERROR executing: putScom (0x301184full)");
                break;
            }
        }
    }
    while (0);

    return l_rc;
}
<commit_msg>Add support for iterating over EC_LEVELS<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_vas_scom.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_vas_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr auto literal_0x0000000000000FFF = 0x0000000000000FFF;
constexpr auto literal_0x00FF0203C00C0FFF = 0x00FF0203C00C0FFF;
constexpr auto literal_0x00000100000D7FFF = 0x00000100000D7FFF;
constexpr auto literal_0x1 = 0x1;

fapi2::ReturnCode p9_vas_scom(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT0,
                              const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& TGT1)
{
    fapi2::ReturnCode l_rc = 0;

    do
    {
        fapi2::ATTR_EC_Type   l_chip_ec;
        fapi2::ATTR_NAME_Type l_chip_id;
        l_rc = FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_NAME, TGT0, l_chip_id);

        if (l_rc)
        {
            FAPI_ERR("ERROR getting ATTR_NAME");
            break;
        }

        l_rc = FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_EC, TGT0, l_chip_ec);

        if (l_rc)
        {
            FAPI_ERR("ERROR getting ATTR_EC");
            break;
        }

        fapi2::ATTR_PROC_FABRIC_ADDR_BAR_MODE_Type l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE;
        l_rc = FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_ADDR_BAR_MODE, TGT1, l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE);

        if (l_rc)
        {
            FAPI_ERR("ERROR executing: FAPI_ATTR_GET (ATTR_PROC_FABRIC_ADDR_BAR_MODE)");
            break;
        }

        {
            fapi2::buffer<uint64_t> l_scom_buffer;
            {
                l_rc = fapi2::getScom( TGT0, 0x301184eull, l_scom_buffer );

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: getScom (0x301184eull)");
                    break;
                }

                {
                    if ((l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_SMALL_SYSTEM))
                    {
                        constexpr auto l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_ON = 0x1;
                        l_scom_buffer.insert<uint64_t> (l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_ON, 13, 1, 63 );
                    }
                    else if ((l_TGT1_ATTR_PROC_FABRIC_ADDR_BAR_MODE == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM))
                    {
                        constexpr auto l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_OFF = 0x0;
                        l_scom_buffer.insert<uint64_t> (l_VA_VA_SOUTH_VA_EG_EG_SCF_ADDR_BAR_MODE_OFF, 13, 1, 63 );
                    }
                }

                l_rc = fapi2::putScom(TGT0, 0x301184eull, l_scom_buffer);

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: putScom (0x301184eull)");
                    break;
                }
            }
        }

        {
            fapi2::buffer<uint64_t> l_scom_buffer;
            {
                l_rc = fapi2::getScom( TGT0, 0x3011806ull, l_scom_buffer );

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: getScom (0x3011806ull)");
                    break;
                }

                {
                    l_scom_buffer.insert<uint64_t> (literal_0x0000000000000FFF, 0, 54, 0 );
                }

                l_rc = fapi2::putScom(TGT0, 0x3011806ull, l_scom_buffer);

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: putScom (0x3011806ull)");
                    break;
                }
            }
        }

        {
            fapi2::buffer<uint64_t> l_scom_buffer;
            {
                l_rc = fapi2::getScom( TGT0, 0x3011807ull, l_scom_buffer );

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: getScom (0x3011807ull)");
                    break;
                }

                {
                    l_scom_buffer.insert<uint64_t> (literal_0x00FF0203C00C0FFF, 0, 54, 0 );
                }

                l_rc = fapi2::putScom(TGT0, 0x3011807ull, l_scom_buffer);

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: putScom (0x3011807ull)");
                    break;
                }
            }
        }

        {
            fapi2::buffer<uint64_t> l_scom_buffer;
            {
                l_rc = fapi2::getScom( TGT0, 0x3011803ull, l_scom_buffer );

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: getScom (0x3011803ull)");
                    break;
                }

                {
                    l_scom_buffer.insert<uint64_t> (literal_0x00000100000D7FFF, 0, 54, 0 );
                }

                l_rc = fapi2::putScom(TGT0, 0x3011803ull, l_scom_buffer);

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: putScom (0x3011803ull)");
                    break;
                }
            }
        }

        {
            fapi2::buffer<uint64_t> l_scom_buffer;
            {
                l_rc = fapi2::getScom( TGT0, 0x301184full, l_scom_buffer );

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: getScom (0x301184full)");
                    break;
                }

                {
                    l_scom_buffer.insert<uint64_t> (literal_0x1, 0, 1, 63 );
                }

                l_rc = fapi2::putScom(TGT0, 0x301184full, l_scom_buffer);

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: putScom (0x301184full)");
                    break;
                }
            }
        }

        {
            fapi2::buffer<uint64_t> l_scom_buffer;
            {
                l_rc = fapi2::getScom( TGT0, 0x301184dull, l_scom_buffer );

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: getScom (0x301184dull)");
                    break;
                }

                {
                    l_scom_buffer.insert<uint64_t> (literal_0x1, 19, 1, 63 );
                }

                l_rc = fapi2::putScom(TGT0, 0x301184dull, l_scom_buffer);

                if (l_rc)
                {
                    FAPI_ERR("ERROR executing: putScom (0x301184dull)");
                    break;
                }
            }
        }

    }
    while(0);

    return l_rc;
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)             */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "ClusterPool.h"

const char * ClusterPool::table = "cluster_pool";

const char * ClusterPool::db_names = "oid, cluster_name";

const char * ClusterPool::db_bootstrap =
    "CREATE TABLE IF NOT EXISTS cluster_pool ("
    "oid INTEGER PRIMARY KEY, cluster_name VARCHAR(128), "
    "UNIQUE(cluster_name) )";

/* -------------------------------------------------------------------------- */

int ClusterPool::allocate(int * clid, string name, SqlDB *db)
{
    int rc;

    map<int, string>::iterator  it;

    // Return error if name already exists
    for(it=cluster_names.begin();it!=cluster_names.end();it++)
    {
        if(it->second == name)
        {
            goto error_existing_name;
        }
    }

    // Get the highest key, and add 1
    *clid = cluster_names.rbegin()->first + 1;

    rc = insert(*clid, name, db);

    if(rc != 0)
    {
        goto error_db;
    }

    return *clid;

// TODO: LOG ERRORS
error_existing_name:
error_db:
error_common:
    return -1;
}

/* -------------------------------------------------------------------------- */

string ClusterPool::info(int clid)
{
    ostringstream oss;

    map<int, string>::iterator it;

    it = cluster_names.find(clid);

    if(it != cluster_names.end())
    {
        dump(oss, it->first, it->second);
    }

    return oss.str();
}

/* -------------------------------------------------------------------------- */

int ClusterPool::drop(int clid, SqlDB *db)
{
    int             rc;
    ostringstream   oss;

    // Return error if cluster is 'default' or if it doesn't exist
    if( clid == 0 || cluster_names.count(clid) == 0 )
    {
        return -1;
    }

    oss << "DELETE FROM " << table << " WHERE oid=" << clid;

    rc = db->exec(oss);

    if(rc == 0)
    {
        cluster_names.erase(clid);
    }

    return rc;
}

/* -------------------------------------------------------------------------- */

int ClusterPool::dump(ostringstream& oss)
{
    map<int, string>::iterator  it;

    oss << "<CLUSTER_POOL>";

    for(it=cluster_names.begin();it!=cluster_names.end();it++)
    {
        dump(oss, it->first, it->second);
    }

    oss << "</CLUSTER_POOL>";

    return 0;
}

/* -------------------------------------------------------------------------- */

int ClusterPool::insert(int oid, string name, SqlDB *db)
{
    ostringstream   oss;

    int    rc;

    char * sql_name;

    sql_name = db->escape_str(name.c_str());

    if ( sql_name == 0 )
    {
        return -1;
    }

    oss << "INSERT INTO "<< table <<" ("<< db_names <<") VALUES ("
        <<          oid             << ","
        << "'" <<   sql_name    << "')";

    rc = db->exec(oss);

    db->free_str(sql_name);

    if( rc == 0 )
    {
        cluster_names.insert( make_pair(oid, name) );
    }

    return rc;
}

/* -------------------------------------------------------------------------- */

void ClusterPool::dump(ostringstream& oss, int id, string name)
{
    oss <<
        "<CLUSTER>"     <<
            "<ID>"      << id       << "</ID>"      <<
            "<NAME>"    << name     << "</NAME>"    <<
        "</CLUSTER>";
}
<commit_msg>feature #201: set cluster id to -1 on error.<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)             */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "ClusterPool.h"

const char * ClusterPool::table = "cluster_pool";

const char * ClusterPool::db_names = "oid, cluster_name";

const char * ClusterPool::db_bootstrap =
    "CREATE TABLE IF NOT EXISTS cluster_pool ("
    "oid INTEGER PRIMARY KEY, cluster_name VARCHAR(128), "
    "UNIQUE(cluster_name) )";

/* -------------------------------------------------------------------------- */

int ClusterPool::allocate(int * clid, string name, SqlDB *db)
{
    int rc;

    map<int, string>::iterator  it;

    // Return error if name already exists
    for(it=cluster_names.begin();it!=cluster_names.end();it++)
    {
        if(it->second == name)
        {
            goto error_existing_name;
        }
    }

    // Get the highest key, and add 1
    *clid = cluster_names.rbegin()->first + 1;

    rc = insert(*clid, name, db);

    if(rc != 0)
    {
        goto error_db;
    }

    return *clid;

// TODO: LOG ERRORS
error_existing_name:
error_db:
error_common:
    *clid = -1;
    return *clid;
}

/* -------------------------------------------------------------------------- */

string ClusterPool::info(int clid)
{
    ostringstream oss;

    map<int, string>::iterator it;

    it = cluster_names.find(clid);

    if(it != cluster_names.end())
    {
        dump(oss, it->first, it->second);
    }

    return oss.str();
}

/* -------------------------------------------------------------------------- */

int ClusterPool::drop(int clid, SqlDB *db)
{
    int             rc;
    ostringstream   oss;

    // Return error if cluster is 'default' or if it doesn't exist
    if( clid == 0 || cluster_names.count(clid) == 0 )
    {
        return -1;
    }

    oss << "DELETE FROM " << table << " WHERE oid=" << clid;

    rc = db->exec(oss);

    if(rc == 0)
    {
        cluster_names.erase(clid);
    }

    return rc;
}

/* -------------------------------------------------------------------------- */

int ClusterPool::dump(ostringstream& oss)
{
    map<int, string>::iterator  it;

    oss << "<CLUSTER_POOL>";

    for(it=cluster_names.begin();it!=cluster_names.end();it++)
    {
        dump(oss, it->first, it->second);
    }

    oss << "</CLUSTER_POOL>";

    return 0;
}

/* -------------------------------------------------------------------------- */

int ClusterPool::insert(int oid, string name, SqlDB *db)
{
    ostringstream   oss;

    int    rc;

    char * sql_name;

    sql_name = db->escape_str(name.c_str());

    if ( sql_name == 0 )
    {
        return -1;
    }

    oss << "INSERT INTO "<< table <<" ("<< db_names <<") VALUES ("
        <<          oid             << ","
        << "'" <<   sql_name    << "')";

    rc = db->exec(oss);

    db->free_str(sql_name);

    if( rc == 0 )
    {
        cluster_names.insert( make_pair(oid, name) );
    }

    return rc;
}

/* -------------------------------------------------------------------------- */

void ClusterPool::dump(ostringstream& oss, int id, string name)
{
    oss <<
        "<CLUSTER>"     <<
            "<ID>"      << id       << "</ID>"      <<
            "<NAME>"    << name     << "</NAME>"    <<
        "</CLUSTER>";
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <lib/utils/count_dimm.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;

extern "C"
{
///
/// @brief Pattern test the DRAM
/// @param[in] i_target the McBIST of the ports of the dram you're training
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mem_diags %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t is_sim = false;
        FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_sim) );

        // We start the sf_init (write 0's) and it'll tickle the MCBIST complete FIR. PRD will see that
        // and start a background scrub.
        FAPI_TRY( memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // If we're in the sim, we want to poll for the FIR bit. I don't think this ever really happens
        // unless we're expressly testing this API.
        if (is_sim)
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            static const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<commit_msg>Remove static keyword from polling vectors due to thread error.<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <lib/utils/count_dimm.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;

extern "C"
{
///
/// @brief Pattern test the DRAM
/// @param[in] i_target the McBIST of the ports of the dram you're training
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mem_diags %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t is_sim = false;
        FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_sim) );

        // We start the sf_init (write 0's) and it'll tickle the MCBIST complete FIR. PRD will see that
        // and start a background scrub.
        FAPI_TRY( memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // If we're in the sim, we want to poll for the FIR bit. I don't think this ever really happens
        // unless we're expressly testing this API.
        if (is_sim)
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/http_connection.hpp"

#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <asio/ip/tcp.hpp>
#include <string>

using boost::bind;

namespace libtorrent
{

	enum { max_bottled_buffer = 1024 * 1024 };

void http_connection::get(std::string const& url, time_duration timeout
	, bool handle_redirect)
{
	m_redirect = handle_redirect;
	std::string protocol;
	std::string auth;
	std::string hostname;
	std::string path;
	int port;
	boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url);
	std::stringstream headers;
	headers << "GET " << path << " HTTP/1.0\r\n"
		"Host:" << hostname <<
		"\r\nConnection: close\r\n";
	if (!auth.empty())
		headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
	headers << "\r\n";
	sendbuffer = headers.str();
	start(hostname, boost::lexical_cast<std::string>(port), timeout);
}

void http_connection::start(std::string const& hostname, std::string const& port
	, time_duration timeout, bool handle_redirect)
{
	m_redirect = handle_redirect;
	m_timeout = timeout;
	m_timer.expires_from_now(m_timeout);
	m_timer.async_wait(bind(&http_connection::on_timeout
		, boost::weak_ptr<http_connection>(shared_from_this()), _1));
	m_called = false;
	if (m_sock.is_open() && m_hostname == hostname && m_port == port)
	{
		m_parser.reset();
		asio::async_write(m_sock, asio::buffer(sendbuffer)
			, bind(&http_connection::on_write, shared_from_this(), _1));
	}
	else
	{
		m_sock.close();
		tcp::resolver::query query(hostname, port);
		m_resolver.async_resolve(query, bind(&http_connection::on_resolve
			, shared_from_this(), _1, _2));
		m_hostname = hostname;
		m_port = port;
	}
}

void http_connection::on_connect_timeout()
{
	if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
	m_connection_ticket = -1;

	if (m_bottled && m_called) return;
	m_called = true;
	m_handler(asio::error::timed_out, m_parser, 0, 0);
	close();
}

void http_connection::on_timeout(boost::weak_ptr<http_connection> p
	, asio::error_code const& e)
{
	boost::shared_ptr<http_connection> c = p.lock();
	if (!c) return;
	if (c->m_connection_ticket > -1) c->m_cc.done(c->m_connection_ticket);
	c->m_connection_ticket = -1;

	if (e == asio::error::operation_aborted) return;

	if (c->m_bottled && c->m_called) return;

	if (c->m_last_receive + c->m_timeout < time_now())
	{
		c->m_called = true;
		c->m_handler(asio::error::timed_out, c->m_parser, 0, 0);
		return;
	}

	c->m_timer.expires_at(c->m_last_receive + c->m_timeout);
	c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
}

void http_connection::close()
{
	m_timer.cancel();
	m_limiter_timer.cancel();
	m_sock.close();
	m_hostname.clear();
	m_port.clear();

	if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
	m_connection_ticket = -1;
}

void http_connection::on_resolve(asio::error_code const& e
		, tcp::resolver::iterator i)
{
	if (e)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
		return;
	}
	TORRENT_ASSERT(i != tcp::resolver::iterator());
	m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
		, bind(&http_connection::on_connect_timeout, shared_from_this())
		, m_timeout);
}

void http_connection::connect(int ticket, tcp::endpoint target_address)
{
	m_connection_ticket = ticket;
	m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect
		, shared_from_this(), _1/*, ++i*/));
}

void http_connection::on_connect(asio::error_code const& e
	/*, tcp::resolver::iterator i*/)
{
	if (!e)
	{
		m_last_receive = time_now();
		if (m_connect_handler) m_connect_handler(*this);
		asio::async_write(m_sock, asio::buffer(sendbuffer)
			, bind(&http_connection::on_write, shared_from_this(), _1));
	}
/*	else if (i != tcp::resolver::iterator())
	{
		// The connection failed. Try the next endpoint in the list.
		m_sock.close();
		m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
			, bind(&http_connection::on_connect_timeout, shared_from_this())
			, m_timeout);
	}
*/	else
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
	}
}

void http_connection::on_write(asio::error_code const& e)
{
	if (e)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
		return;
	}

	std::string().swap(sendbuffer);
	m_recvbuffer.resize(4096);

	int amount_to_read = m_recvbuffer.size() - m_read_pos;
	if (m_rate_limit > 0 && amount_to_read > m_download_quota)
	{
		amount_to_read = m_download_quota;
		if (m_download_quota == 0)
		{
			if (!m_limiter_timer_active)
				on_assign_bandwidth(asio::error_code());
			return;
		}
	}
	m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos
		, amount_to_read)
		, bind(&http_connection::on_read
		, shared_from_this(), _1, _2));
}

void http_connection::on_read(asio::error_code const& e
	, std::size_t bytes_transferred)
{
	if (m_rate_limit)
	{
		m_download_quota -= bytes_transferred;
		TORRENT_ASSERT(m_download_quota >= 0);
	}

	if (e == asio::error::eof)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		char const* data = 0;
		std::size_t size = 0;
		if (m_bottled && m_parser.header_finished())
		{
			data = m_parser.get_body().begin;
			size = m_parser.get_body().left();
		}
		m_handler(e, m_parser, data, size);
		return;
	}

	if (e)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
		return;
	}

	m_read_pos += bytes_transferred;
	TORRENT_ASSERT(m_read_pos <= int(m_recvbuffer.size()));

	// having a nonempty path means we should handle redirects
	if (m_redirect && m_parser.header_finished())
	{
		int code = m_parser.status_code();
		if (code >= 300 && code < 400)
		{
			// attempt a redirect
			std::string const& url = m_parser.header("location");
			if (url.empty())
			{
				// missing location header
				if (m_bottled && m_called) return;
				m_called = true;
				m_handler(e, m_parser, 0, 0);
				return;
			}

			m_limiter_timer_active = false;
			close();

			get(url, m_timeout);
			return;
		}

		m_redirect = false;
	}

	if (m_bottled || !m_parser.header_finished())
	{
		libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
			, &m_recvbuffer[0] + m_read_pos);
		m_parser.incoming(rcv_buf);
		if (!m_bottled && m_parser.header_finished())
		{
			if (m_read_pos > m_parser.body_start())
				m_handler(e, m_parser, &m_recvbuffer[0] + m_parser.body_start()
					, m_read_pos - m_parser.body_start());
			m_read_pos = 0;
			m_last_receive = time_now();
		}
		else if (m_bottled && m_parser.finished())
		{
			m_timer.cancel();
			if (m_bottled && m_called) return;
			m_called = true;
			m_handler(e, m_parser, m_parser.get_body().begin, m_parser.get_body().left());
		}
	}
	else
	{
		TORRENT_ASSERT(!m_bottled);
		m_handler(e, m_parser, &m_recvbuffer[0], m_read_pos);
		m_read_pos = 0;
		m_last_receive = time_now();
	}

	if (int(m_recvbuffer.size()) == m_read_pos)
		m_recvbuffer.resize((std::min)(m_read_pos + 2048, int(max_bottled_buffer)));
	if (m_read_pos == max_bottled_buffer)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(asio::error::eof, m_parser, 0, 0);
		return;
	}
	int amount_to_read = m_recvbuffer.size() - m_read_pos;
	if (m_rate_limit > 0 && amount_to_read > m_download_quota)
	{
		amount_to_read = m_download_quota;
		if (m_download_quota == 0)
		{
			if (!m_limiter_timer_active)
				on_assign_bandwidth(asio::error_code());
			return;
		}
	}
	m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos
		, amount_to_read)
		, bind(&http_connection::on_read
		, shared_from_this(), _1, _2));
}

void http_connection::on_assign_bandwidth(asio::error_code const& e)
{
	if ((e == asio::error::operation_aborted
		&& m_limiter_timer_active)
		|| !m_sock.is_open())
	{
		if (!m_bottled || !m_called)
			m_handler(e, m_parser, 0, 0);
		return;
	}
	m_limiter_timer_active = false;
	if (e) return;

	if (m_download_quota > 0) return;

	m_download_quota = m_rate_limit / 4;

	int amount_to_read = m_recvbuffer.size() - m_read_pos;
	if (amount_to_read > m_download_quota)
		amount_to_read = m_download_quota;

	m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos
		, amount_to_read)
		, bind(&http_connection::on_read
		, shared_from_this(), _1, _2));

	m_limiter_timer_active = true;
	m_limiter_timer.expires_from_now(milliseconds(250));
	m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
		, shared_from_this(), _1));
}

void http_connection::rate_limit(int limit)
{
	if (!m_limiter_timer_active)
	{
		m_limiter_timer_active = true;
		m_limiter_timer.expires_from_now(milliseconds(250));
		m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
			, shared_from_this(), _1));
	}
	m_rate_limit = limit;
}

}

<commit_msg>http_connection shutdown fixes<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/http_connection.hpp"

#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <asio/ip/tcp.hpp>
#include <string>

using boost::bind;

namespace libtorrent
{

	enum { max_bottled_buffer = 1024 * 1024 };

void http_connection::get(std::string const& url, time_duration timeout
	, bool handle_redirect)
{
	m_redirect = handle_redirect;
	std::string protocol;
	std::string auth;
	std::string hostname;
	std::string path;
	int port;
	boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url);
	std::stringstream headers;
	headers << "GET " << path << " HTTP/1.0\r\n"
		"Host:" << hostname <<
		"\r\nConnection: close\r\n";
	if (!auth.empty())
		headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
	headers << "\r\n";
	sendbuffer = headers.str();
	start(hostname, boost::lexical_cast<std::string>(port), timeout);
}

void http_connection::start(std::string const& hostname, std::string const& port
	, time_duration timeout, bool handle_redirect)
{
	m_redirect = handle_redirect;
	m_timeout = timeout;
	m_timer.expires_from_now(m_timeout);
	m_timer.async_wait(bind(&http_connection::on_timeout
		, boost::weak_ptr<http_connection>(shared_from_this()), _1));
	m_called = false;
	if (m_sock.is_open() && m_hostname == hostname && m_port == port)
	{
		m_parser.reset();
		asio::async_write(m_sock, asio::buffer(sendbuffer)
			, bind(&http_connection::on_write, shared_from_this(), _1));
	}
	else
	{
		m_sock.close();
		tcp::resolver::query query(hostname, port);
		m_resolver.async_resolve(query, bind(&http_connection::on_resolve
			, shared_from_this(), _1, _2));
		m_hostname = hostname;
		m_port = port;
	}
}

void http_connection::on_connect_timeout()
{
	if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
	m_connection_ticket = -1;

	if (m_bottled && m_called) return;
	m_called = true;
	m_handler(asio::error::timed_out, m_parser, 0, 0);
	close();
}

void http_connection::on_timeout(boost::weak_ptr<http_connection> p
	, asio::error_code const& e)
{
	boost::shared_ptr<http_connection> c = p.lock();
	if (!c) return;
	if (c->m_connection_ticket > -1) c->m_cc.done(c->m_connection_ticket);
	c->m_connection_ticket = -1;

	if (e == asio::error::operation_aborted) return;

	if (c->m_bottled && c->m_called) return;

	if (c->m_last_receive + c->m_timeout < time_now())
	{
		c->m_called = true;
		c->m_handler(asio::error::timed_out, c->m_parser, 0, 0);
		return;
	}

	if (!c->m_sock.is_open()) return;

	c->m_timer.expires_at(c->m_last_receive + c->m_timeout);
	c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
}

void http_connection::close()
{
	m_timer.cancel();
	m_limiter_timer.cancel();
	m_sock.close();
	m_hostname.clear();
	m_port.clear();

	if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
	m_connection_ticket = -1;

	if (m_called) return;
	m_called = true;
	m_handler(asio::error::operation_aborted, m_parser, 0, 0);
}

void http_connection::on_resolve(asio::error_code const& e
		, tcp::resolver::iterator i)
{
	if (e)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
		return;
	}
	TORRENT_ASSERT(i != tcp::resolver::iterator());
	m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
		, bind(&http_connection::on_connect_timeout, shared_from_this())
		, m_timeout);
}

void http_connection::connect(int ticket, tcp::endpoint target_address)
{
	m_connection_ticket = ticket;
	m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect
		, shared_from_this(), _1/*, ++i*/));
}

void http_connection::on_connect(asio::error_code const& e
	/*, tcp::resolver::iterator i*/)
{
	if (!e)
	{
		m_last_receive = time_now();
		if (m_connect_handler) m_connect_handler(*this);
		asio::async_write(m_sock, asio::buffer(sendbuffer)
			, bind(&http_connection::on_write, shared_from_this(), _1));
	}
/*	else if (i != tcp::resolver::iterator())
	{
		// The connection failed. Try the next endpoint in the list.
		m_sock.close();
		m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
			, bind(&http_connection::on_connect_timeout, shared_from_this())
			, m_timeout);
	}
*/	else
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
	}
}

void http_connection::on_write(asio::error_code const& e)
{
	if (e)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
		return;
	}

	std::string().swap(sendbuffer);
	m_recvbuffer.resize(4096);

	int amount_to_read = m_recvbuffer.size() - m_read_pos;
	if (m_rate_limit > 0 && amount_to_read > m_download_quota)
	{
		amount_to_read = m_download_quota;
		if (m_download_quota == 0)
		{
			if (!m_limiter_timer_active)
				on_assign_bandwidth(asio::error_code());
			return;
		}
	}
	m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos
		, amount_to_read)
		, bind(&http_connection::on_read
		, shared_from_this(), _1, _2));
}

void http_connection::on_read(asio::error_code const& e
	, std::size_t bytes_transferred)
{
	if (m_rate_limit)
	{
		m_download_quota -= bytes_transferred;
		TORRENT_ASSERT(m_download_quota >= 0);
	}

	if (e == asio::error::eof)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		char const* data = 0;
		std::size_t size = 0;
		if (m_bottled && m_parser.header_finished())
		{
			data = m_parser.get_body().begin;
			size = m_parser.get_body().left();
		}
		m_handler(e, m_parser, data, size);
		return;
	}

	if (e)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(e, m_parser, 0, 0);
		return;
	}

	m_read_pos += bytes_transferred;
	TORRENT_ASSERT(m_read_pos <= int(m_recvbuffer.size()));

	// having a nonempty path means we should handle redirects
	if (m_redirect && m_parser.header_finished())
	{
		int code = m_parser.status_code();
		if (code >= 300 && code < 400)
		{
			// attempt a redirect
			std::string const& url = m_parser.header("location");
			if (url.empty())
			{
				// missing location header
				if (m_bottled && m_called) return;
				m_called = true;
				m_handler(e, m_parser, 0, 0);
				return;
			}

			m_limiter_timer_active = false;
			close();

			get(url, m_timeout);
			return;
		}

		m_redirect = false;
	}

	if (m_bottled || !m_parser.header_finished())
	{
		libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
			, &m_recvbuffer[0] + m_read_pos);
		m_parser.incoming(rcv_buf);
		if (!m_bottled && m_parser.header_finished())
		{
			if (m_read_pos > m_parser.body_start())
				m_handler(e, m_parser, &m_recvbuffer[0] + m_parser.body_start()
					, m_read_pos - m_parser.body_start());
			m_read_pos = 0;
			m_last_receive = time_now();
		}
		else if (m_bottled && m_parser.finished())
		{
			m_timer.cancel();
			if (m_bottled && m_called) return;
			m_called = true;
			m_handler(e, m_parser, m_parser.get_body().begin, m_parser.get_body().left());
		}
	}
	else
	{
		TORRENT_ASSERT(!m_bottled);
		m_handler(e, m_parser, &m_recvbuffer[0], m_read_pos);
		m_read_pos = 0;
		m_last_receive = time_now();
	}

	if (int(m_recvbuffer.size()) == m_read_pos)
		m_recvbuffer.resize((std::min)(m_read_pos + 2048, int(max_bottled_buffer)));
	if (m_read_pos == max_bottled_buffer)
	{
		close();
		if (m_bottled && m_called) return;
		m_called = true;
		m_handler(asio::error::eof, m_parser, 0, 0);
		return;
	}
	int amount_to_read = m_recvbuffer.size() - m_read_pos;
	if (m_rate_limit > 0 && amount_to_read > m_download_quota)
	{
		amount_to_read = m_download_quota;
		if (m_download_quota == 0)
		{
			if (!m_limiter_timer_active)
				on_assign_bandwidth(asio::error_code());
			return;
		}
	}
	m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos
		, amount_to_read)
		, bind(&http_connection::on_read
		, shared_from_this(), _1, _2));
}

void http_connection::on_assign_bandwidth(asio::error_code const& e)
{
	if ((e == asio::error::operation_aborted
		&& m_limiter_timer_active)
		|| !m_sock.is_open())
	{
		if (!m_bottled || !m_called)
			m_handler(e, m_parser, 0, 0);
		return;
	}
	m_limiter_timer_active = false;
	if (e) return;

	if (m_download_quota > 0) return;

	m_download_quota = m_rate_limit / 4;

	int amount_to_read = m_recvbuffer.size() - m_read_pos;
	if (amount_to_read > m_download_quota)
		amount_to_read = m_download_quota;

	if (!m_sock.is_open()) return;

	m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos
		, amount_to_read)
		, bind(&http_connection::on_read
		, shared_from_this(), _1, _2));

	m_limiter_timer_active = true;
	m_limiter_timer.expires_from_now(milliseconds(250));
	m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
		, shared_from_this(), _1));
}

void http_connection::rate_limit(int limit)
{
	if (!m_sock.is_open()) return;

	if (!m_limiter_timer_active)
	{
		m_limiter_timer_active = true;
		m_limiter_timer.expires_from_now(milliseconds(250));
		m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
			, shared_from_this(), _1));
	}
	m_rate_limit = limit;
}

}

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <cctype>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"

#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
{
	using ::isprint;
	using ::isdigit;
}
#endif

namespace
{

	using namespace libtorrent;

	// takes a peer id and returns a valid boost::optional
	// object if the peer id matched the azureus style encoding
	// the returned fingerprint contains information about the
	// client's id
	boost::optional<fingerprint> parse_az_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		for (int j = 0; j < 2; ++j)
		{
			if (!std::isprint(*i)) return boost::optional<fingerprint>();
			ret.id[j] = *i;
			++i;
		}

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.major_version = *i - '0';
		++i;

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.minor_version = *i - '0';
		++i;

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.revision_version = *i - '0';
		++i;

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.tag_version = *i - '0';
		++i;

		if (*i != '-') return boost::optional<fingerprint>();

		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a shadow-style
	// identification
	boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isprint(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (std::equal(id.begin()+4, id.begin()+8, "----"))
		{
			if (!std::isdigit(*i)) return boost::optional<fingerprint>();
			ret.major_version = *i - '0';
			++i;

			if (!std::isdigit(*i)) return boost::optional<fingerprint>();
			ret.minor_version = *i - '0';
			++i;

			if (!std::isdigit(*i)) return boost::optional<fingerprint>();
			ret.revision_version = *i - '0';
		}
		else if (id[8] == 0)
		{
			if (*i > 127) return boost::optional<fingerprint>();
			ret.major_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.minor_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.revision_version = *i;
		}
		else
			return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a mainline-style
	// identification
	boost::optional<fingerprint> parse_mainline_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isprint(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.major_version = *i - '0';
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.minor_version = *i - '0';
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (!std::isdigit(*i)) return boost::optional<fingerprint>();
		ret.revision_version = *i - '0';
		++i;

		if (!std::equal(i, i+1, "--")) return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

} // namespace unnamed

namespace libtorrent
{

	std::string identify_client(const peer_id& p)
	{
		peer_id::const_iterator PID = p.begin();
		boost::optional<fingerprint> f;

		if (p.is_all_zeros()) return "Unkown";

		// look for azureus style id
		f = parse_az_style(p);
		if (f)
		{
			std::stringstream identity;

			// azureus
			if (std::equal(f->id, f->id+2, "AZ"))
				identity << "Azureus ";

			// BittorrentX
			else if (std::equal(f->id, f->id+2, "BX"))
				identity << "BittorrentX ";

			// libtorrent
			else if (std::equal(f->id, f->id+2, "LT"))
				identity << "libtorrent ";

			// Moonlight Torrent
			else if (std::equal(f->id, f->id+2, "MT"))
				identity << "Moonlight Torrent ";

			// Torrent Storm
			else if (std::equal(f->id, f->id+2, "TS"))
				identity << "TorrentStorm ";

			// SwarmScope
			else if (std::equal(f->id, f->id+2, "SS"))
				identity << "SwarmScope ";

			// XanTorrent
			else if (std::equal(f->id, f->id+2, "XT"))
				identity << "XanTorrent ";

			// unknown client
			else
				identity << std::string(f->id, f->id+2) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version
				<< "." << (int)f->tag_version;

			return identity.str();
		}

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f)
		{
			std::stringstream identity;

			// Shadow
			if (std::equal(f->id, f->id+1, "S"))
				identity << "Shadow ";

			// ABC
			else if (std::equal(f->id, f->id+1, "A"))
				identity << "ABC ";

			// UPnP
			else if (std::equal(f->id, f->id+1, "U"))
				identity << "UPnP ";

			// BitTornado
			else if (std::equal(f->id, f->id+1, "T"))
				identity << "BitTornado ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		f = parse_mainline_style(p);
		if (f)
		{
			std::stringstream identity;

			// Mainline
			if (std::equal(f->id, f->id+1, "M"))
				identity << "Mainline ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		// ----------------------
		// non standard encodings
		// ----------------------

		if (std::equal(PID, PID + 12, "-G3g3rmz    "))
		{
			return "G3 Torrent";
		}

		if (std::equal(PID, PID + 4, "exbc"))
		{
			std::stringstream s;
			s << "BitComet " << (int)PID[4] << "." << (int)PID[5]/10 << (int)PID[5]%10;
			return s.str();
		}

		if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
		{
			return "Azureus 2.0.3.2";
		}

		if (std::equal(PID, PID + 11, "DansClient"))
		{
			return "XanTorrent";
		}

		if (std::equal(PID, PID + 7, "Plus---"))
		{
			return "Bittorrent Plus";
		}

		if (std::equal(PID, PID + 16, "Deadman Walking-"))
		{
			return "Deadman";
		}

		if (std::equal(PID, PID + 7, "btuga"))
		{
			return "BTugaXP";
		}

		if (std::equal(PID, PID + 7, "btfans"))
		{
			return "SimpleBT";
		}

		if (std::equal(PID, PID + 7, "turbobt"))
		{
			std::stringstream s;
			s << "TurboBT " << PID[8] << "." << PID[10] << "." << PID[12];
			return s.str();
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
		{
			return "Experimental 3.2.1b2";
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Experimental 3.1";
		}

		if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Generic";
		}

		std::string unknown("Unknown [");
		for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i)
		{
			unknown += std::isprint(*i)?*i:'.';
		}
		unknown += "]";
		return unknown;
	}

}
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <cctype>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"

#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
{
	using ::isprint;
	using ::isdigit;
}
#endif

namespace
{

	using namespace libtorrent;

	// takes a peer id and returns a valid boost::optional
	// object if the peer id matched the azureus style encoding
	// the returned fingerprint contains information about the
	// client's id
	boost::optional<fingerprint> parse_az_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		for (int j = 0; j < 2; ++j)
		{
			if (!std::isprint(*i)) return boost::optional<fingerprint>();
			ret.id[j] = *i;
			++i;
		}

		if (*i < '0') return boost::optional<fingerprint>();
		ret.major_version = *i - '0';
		++i;

		if (*i < '0') return boost::optional<fingerprint>();
		ret.minor_version = *i - '0';
		++i;

		if (*i < '0') return boost::optional<fingerprint>();
		ret.revision_version = *i - '0';
		++i;

		if (*i < '0') return boost::optional<fingerprint>();
		ret.tag_version = *i - '0';
		++i;

		if (*i != '-') return boost::optional<fingerprint>();

		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a shadow-style
	// identification
	boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (*i < '0') return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (std::equal(id.begin()+4, id.begin()+8, "----"))
		{
			if (*i < '0') return boost::optional<fingerprint>();
			ret.major_version = *i - '0';
			++i;

			if (*i < '0') return boost::optional<fingerprint>();
			ret.minor_version = *i - '0';
			++i;

			if (*i < '0') return boost::optional<fingerprint>();
			ret.revision_version = *i - '0';
		}
		else if (id[8] == 0)
		{
			if (*i > 127) return boost::optional<fingerprint>();
			ret.major_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.minor_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.revision_version = *i;
		}
		else
			return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a mainline-style
	// identification
	boost::optional<fingerprint> parse_mainline_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isprint(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (*i < '0') return boost::optional<fingerprint>();
		ret.major_version = *i - '0';
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (*i < '0') return boost::optional<fingerprint>();
		ret.minor_version = *i - '0';
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (*i < '0') return boost::optional<fingerprint>();
		ret.revision_version = *i - '0';
		++i;

		if (!std::equal(i, i+1, "--")) return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

} // namespace unnamed

namespace libtorrent
{

	std::string identify_client(const peer_id& p)
	{
		peer_id::const_iterator PID = p.begin();
		boost::optional<fingerprint> f;

		if (p.is_all_zeros()) return "Unkown";

		// look for azureus style id
		f = parse_az_style(p);
		if (f)
		{
			std::stringstream identity;

			// azureus
			if (std::equal(f->id, f->id+2, "AZ"))
				identity << "Azureus ";

			// BittorrentX
			else if (std::equal(f->id, f->id+2, "BX"))
				identity << "BittorrentX ";

			// libtorrent
			else if (std::equal(f->id, f->id+2, "LT"))
				identity << "libtorrent ";

			// Moonlight Torrent
			else if (std::equal(f->id, f->id+2, "MT"))
				identity << "Moonlight Torrent ";

			// Torrent Storm
			else if (std::equal(f->id, f->id+2, "TS"))
				identity << "TorrentStorm ";

			// SwarmScope
			else if (std::equal(f->id, f->id+2, "SS"))
				identity << "SwarmScope ";

			// XanTorrent
			else if (std::equal(f->id, f->id+2, "XT"))
				identity << "XanTorrent ";

			// unknown client
			else
				identity << std::string(f->id, f->id+2) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version
				<< "." << (int)f->tag_version;

			return identity.str();
		}

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f)
		{
			std::stringstream identity;

			// Shadow
			if (std::equal(f->id, f->id+1, "S"))
				identity << "Shadow ";

			// ABC
			else if (std::equal(f->id, f->id+1, "A"))
				identity << "ABC ";

			// UPnP
			else if (std::equal(f->id, f->id+1, "U"))
				identity << "UPnP ";

			// BitTornado
			else if (std::equal(f->id, f->id+1, "T"))
				identity << "BitTornado ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		f = parse_mainline_style(p);
		if (f)
		{
			std::stringstream identity;

			// Mainline
			if (std::equal(f->id, f->id+1, "M"))
				identity << "Mainline ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		// ----------------------
		// non standard encodings
		// ----------------------

		if (std::equal(PID, PID + 12, "-G3g3rmz    "))
		{
			return "G3 Torrent";
		}

		if (std::equal(PID, PID + 4, "exbc"))
		{
			std::stringstream s;
			s << "BitComet " << (int)PID[4] << "." << (int)PID[5]/10 << (int)PID[5]%10;
			return s.str();
		}

		if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
		{
			return "Azureus 2.0.3.2";
		}

		if (std::equal(PID, PID + 11, "DansClient"))
		{
			return "XanTorrent";
		}

		if (std::equal(PID, PID + 7, "Plus---"))
		{
			return "Bittorrent Plus";
		}

		if (std::equal(PID, PID + 16, "Deadman Walking-"))
		{
			return "Deadman";
		}

		if (std::equal(PID, PID + 7, "btuga"))
		{
			return "BTugaXP";
		}

		if (std::equal(PID, PID + 7, "btfans"))
		{
			return "SimpleBT";
		}

		if (std::equal(PID, PID + 7, "turbobt"))
		{
			std::stringstream s;
			s << "TurboBT " << PID[8] << "." << PID[10] << "." << PID[12];
			return s.str();
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
		{
			return "Experimental 3.2.1b2";
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Experimental 3.1";
		}

		if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Generic";
		}

		std::string unknown("Unknown [");
		for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i)
		{
			unknown += std::isprint(*i)?*i:'.';
		}
		unknown += "]";
		return unknown;
	}

}
<|endoftext|>