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