1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 6*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube; 7*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType; 8*bb4ee6a4SAndroid Build Coastguard Worker 9*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId; 10*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo; 11*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice; 12*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId; 13*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable; 14*bb4ee6a4SAndroid Build Coastguard Worker 15*bb4ee6a4SAndroid Build Coastguard Worker /// A i8042 PS/2 controller that emulates just enough to shutdown the machine. 16*bb4ee6a4SAndroid Build Coastguard Worker pub struct I8042Device { 17*bb4ee6a4SAndroid Build Coastguard Worker reset_evt_wrtube: SendTube, 18*bb4ee6a4SAndroid Build Coastguard Worker } 19*bb4ee6a4SAndroid Build Coastguard Worker 20*bb4ee6a4SAndroid Build Coastguard Worker impl I8042Device { 21*bb4ee6a4SAndroid Build Coastguard Worker /// Constructs a i8042 device that will signal the given event when the guest requests it. new(reset_evt_wrtube: SendTube) -> I8042Device22*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(reset_evt_wrtube: SendTube) -> I8042Device { 23*bb4ee6a4SAndroid Build Coastguard Worker I8042Device { reset_evt_wrtube } 24*bb4ee6a4SAndroid Build Coastguard Worker } 25*bb4ee6a4SAndroid Build Coastguard Worker } 26*bb4ee6a4SAndroid Build Coastguard Worker 27*bb4ee6a4SAndroid Build Coastguard Worker // i8042 device is mapped I/O address 0x61. We partially implement two 8-bit 28*bb4ee6a4SAndroid Build Coastguard Worker // registers: port 0x61 (I8042_PORT_B_REG), and port 0x64 (I8042_COMMAND_REG). 29*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for I8042Device { device_id(&self) -> DeviceId30*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId { 31*bb4ee6a4SAndroid Build Coastguard Worker CrosvmDeviceId::I8042.into() 32*bb4ee6a4SAndroid Build Coastguard Worker } 33*bb4ee6a4SAndroid Build Coastguard Worker debug_label(&self) -> String34*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String { 35*bb4ee6a4SAndroid Build Coastguard Worker "i8042".to_owned() 36*bb4ee6a4SAndroid Build Coastguard Worker } 37*bb4ee6a4SAndroid Build Coastguard Worker read(&mut self, info: BusAccessInfo, data: &mut [u8])38*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) { 39*bb4ee6a4SAndroid Build Coastguard Worker if data.len() == 1 && info.address == 0x64 { 40*bb4ee6a4SAndroid Build Coastguard Worker data[0] = 0x0; 41*bb4ee6a4SAndroid Build Coastguard Worker } else if data.len() == 1 && info.address == 0x61 { 42*bb4ee6a4SAndroid Build Coastguard Worker // Like kvmtool, we return bit 5 set in I8042_PORT_B_REG to 43*bb4ee6a4SAndroid Build Coastguard Worker // avoid hang in pit_calibrate_tsc() in Linux kernel. 44*bb4ee6a4SAndroid Build Coastguard Worker data[0] = 0x20; 45*bb4ee6a4SAndroid Build Coastguard Worker } 46*bb4ee6a4SAndroid Build Coastguard Worker } 47*bb4ee6a4SAndroid Build Coastguard Worker write(&mut self, info: BusAccessInfo, data: &[u8])48*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, info: BusAccessInfo, data: &[u8]) { 49*bb4ee6a4SAndroid Build Coastguard Worker if data.len() == 1 && data[0] == 0xfe && info.address == 0x64 { 50*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self 51*bb4ee6a4SAndroid Build Coastguard Worker .reset_evt_wrtube 52*bb4ee6a4SAndroid Build Coastguard Worker .send::<VmEventType>(&VmEventType::Reset) 53*bb4ee6a4SAndroid Build Coastguard Worker { 54*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to trigger i8042 reset event: {}", e); 55*bb4ee6a4SAndroid Build Coastguard Worker } 56*bb4ee6a4SAndroid Build Coastguard Worker } 57*bb4ee6a4SAndroid Build Coastguard Worker } 58*bb4ee6a4SAndroid Build Coastguard Worker } 59*bb4ee6a4SAndroid Build Coastguard Worker 60*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for I8042Device { snapshot(&mut self) -> anyhow::Result<serde_json::Value>61*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> { 62*bb4ee6a4SAndroid Build Coastguard Worker Ok(serde_json::Value::Object(serde_json::Map::new())) 63*bb4ee6a4SAndroid Build Coastguard Worker } 64*bb4ee6a4SAndroid Build Coastguard Worker restore(&mut self, _data: serde_json::Value) -> anyhow::Result<()>65*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, _data: serde_json::Value) -> anyhow::Result<()> { 66*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 67*bb4ee6a4SAndroid Build Coastguard Worker } 68*bb4ee6a4SAndroid Build Coastguard Worker sleep(&mut self) -> anyhow::Result<()>69*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> { 70*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 71*bb4ee6a4SAndroid Build Coastguard Worker } 72*bb4ee6a4SAndroid Build Coastguard Worker wake(&mut self) -> anyhow::Result<()>73*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> { 74*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 75*bb4ee6a4SAndroid Build Coastguard Worker } 76*bb4ee6a4SAndroid Build Coastguard Worker } 77