static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
{
    int result;
    struct {
        u8 version;
        u8 type;
        u8 reserved_1[14];
    } cmd;

    BUILD_BUG_ON(sizeof(cmd) != 16);

    dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);

    result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
    BUG_ON(result && "need to retry here");

    if(result)
        return result;

    if (cmd.version != 1) {
        dev_dbg(&dev->core, "%s:%d: unsupported cmd version (%u)\n",
                __func__, __LINE__, cmd.version);
        return -EIO;
    }

    if (cmd.type != PS3_SM_CMD_SHUTDOWN) {
        dev_dbg(&dev->core, "%s:%d: unknown cmd (%u)\n",
                __func__, __LINE__, cmd.type);
        return -EIO;
    }

    ps3_sys_manager_send_response(dev, 0);
    return 0;
}
static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
{
    int result;
    struct ps3_sys_manager_header header;

    result = ps3_vuart_read(dev, &header,
                            sizeof(struct ps3_sys_manager_header));

    if(result)
        return result;

    if (header.version != 1) {
        dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
                __func__, __LINE__, header.version);
        dump_sm_header(&header);
        goto fail_header;
    }

    BUILD_BUG_ON(sizeof(header) != 16);

    if (header.size != 16 || (header.payload_size != 8
                              && header.payload_size != 16)) {
        dump_sm_header(&header);
        BUG();
    }

    switch (header.service_id) {
    case PS3_SM_SERVICE_ID_EXTERN_EVENT:
        dev_dbg(&dev->core, "%s:%d: EVENT\n", __func__, __LINE__);
        return ps3_sys_manager_handle_event(dev);
    case PS3_SM_SERVICE_ID_COMMAND:
        dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
        return ps3_sys_manager_handle_cmd(dev);
    case PS3_SM_SERVICE_ID_REQUEST_ERROR:
        dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
                __LINE__);
        dump_sm_header(&header);
        break;
    default:
        dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
                __func__, __LINE__, header.service_id);
        break;
    }
    goto fail_id;

fail_header:
    ps3_vuart_clear_rx_bytes(dev, 0);
    return -EIO;
fail_id:
    ps3_vuart_clear_rx_bytes(dev, header.payload_size);
    return -EIO;
}
Example #3
0
static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
                            unsigned long size, int timeout)
{
    int error;
    int loopcnt = 0;

    dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
    timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
    while (loopcnt++ <= timeout) {
        error = ps3_vuart_read(dev, buf, size);
        if (!error)
            return size;
        if (error != -EAGAIN) {
            printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
                   __func__, error);
            return error;
        }
        msleep(POLLING_INTERVAL);
    }
    return -EWOULDBLOCK;
}
static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
{
    int result;
    struct {
        u8 version;
        u8 type;
        u8 reserved_1[2];
        u32 value;
        u8 reserved_2[8];
    } event;

    BUILD_BUG_ON(sizeof(event) != 16);

    result = ps3_vuart_read(dev, &event, sizeof(event));
    BUG_ON(result && "need to retry here");

    if (event.version != 1) {
        dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
                __func__, __LINE__, event.version);
        return -EIO;
    }

    switch (event.type) {
    case PS3_SM_EVENT_POWER_PRESSED:
        dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
                __func__, __LINE__);
        ps3_sm_force_power_off = 1;
        /*
         * A memory barrier is use here to sync memory since
         * ps3_sys_manager_final_restart() could be called on
         * another cpu.
         */
        wmb();
        kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
        break;
    case PS3_SM_EVENT_POWER_RELEASED:
        dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
                __func__, __LINE__, event.value);
        break;
    case PS3_SM_EVENT_RESET_PRESSED:
        dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
                __func__, __LINE__);
        ps3_sm_force_power_off = 0;
        /*
         * A memory barrier is use here to sync memory since
         * ps3_sys_manager_final_restart() could be called on
         * another cpu.
         */
        wmb();
        kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
        break;
    case PS3_SM_EVENT_RESET_RELEASED:
        dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
                __func__, __LINE__, event.value);
        break;
    case PS3_SM_EVENT_THERMAL_ALERT:
        dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
                __func__, __LINE__, event.value);
        printk(KERN_INFO "PS3 Thermal Alert Zone %u\n", event.value);
        break;
    case PS3_SM_EVENT_THERMAL_CLEARED:
        dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
                __func__, __LINE__, event.value);
        break;
    default:
        dev_dbg(&dev->core, "%s:%d: unknown event (%u)\n",
                __func__, __LINE__, event.type);
        return -EIO;
    }

    return 0;
}
Example #5
0
static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
{
    int result;
    struct {
        u8 version;
        u8 type;
        u8 reserved_1[2];
        u32 value;
        u8 reserved_2[8];
    } event;

    BUILD_BUG_ON(sizeof(event) != 16);

    result = ps3_vuart_read(dev, &event, sizeof(event));
    BUG_ON(result && "need to retry here");

    if (event.version != 1) {
        dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
                __func__, __LINE__, event.version);
        return -EIO;
    }

    switch (event.type) {
    case PS3_SM_EVENT_POWER_PRESSED:
        dev_dbg(&dev->core, "%s:%d: POWER_PRESSED (%s)\n",
                __func__, __LINE__,
                (event.value == PS3_SM_BUTTON_EVENT_SOFT ? "soft"
                 : "hard"));
        ps3_sm_force_power_off = 1;

        wmb();
        kill_cad_pid(SIGINT, 1);
        break;
    case PS3_SM_EVENT_POWER_RELEASED:
        dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
                __func__, __LINE__, event.value);
        break;
    case PS3_SM_EVENT_RESET_PRESSED:
        dev_dbg(&dev->core, "%s:%d: RESET_PRESSED (%s)\n",
                __func__, __LINE__,
                (event.value == PS3_SM_BUTTON_EVENT_SOFT ? "soft"
                 : "hard"));
        ps3_sm_force_power_off = 0;

        wmb();
        kill_cad_pid(SIGINT, 1);
        break;
    case PS3_SM_EVENT_RESET_RELEASED:
        dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
                __func__, __LINE__, event.value);
        break;
    case PS3_SM_EVENT_THERMAL_ALERT:
        dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
                __func__, __LINE__, event.value);
        pr_info("PS3 Thermal Alert Zone %u\n", event.value);
        break;
    case PS3_SM_EVENT_THERMAL_CLEARED:
        dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
                __func__, __LINE__, event.value);
        break;
    default:
        dev_dbg(&dev->core, "%s:%d: unknown event (%u)\n",
                __func__, __LINE__, event.type);
        return -EIO;
    }

    return 0;
}