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; }
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; }
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; }