1 // Copyright 2019 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 as SysError; 6 use base::Event; 7 use remain::sorted; 8 use thiserror::Error; 9 use vm_memory::GuestAddress; 10 use vm_memory::GuestMemory; 11 12 use super::event_ring::Error as EventRingError; 13 use super::event_ring::EventRing; 14 use super::xhci_abi::CommandCompletionEventTrb; 15 use super::xhci_abi::Error as TrbError; 16 use super::xhci_abi::PortStatusChangeEventTrb; 17 use super::xhci_abi::TransferEventTrb; 18 use super::xhci_abi::Trb; 19 use super::xhci_abi::TrbCast; 20 use super::xhci_abi::TrbCompletionCode; 21 use super::xhci_abi::TrbType; 22 use super::xhci_regs::*; 23 use crate::register_space::Register; 24 25 #[sorted] 26 #[derive(Error, Debug)] 27 pub enum Error { 28 #[error("cannot add event: {0}")] 29 AddEvent(EventRingError), 30 #[error("cannot cast trb: {0}")] 31 CastTrb(TrbError), 32 #[error("cannot send interrupt: {0}")] 33 SendInterrupt(SysError), 34 #[error("cannot set seg table base addr: {0}")] 35 SetSegTableBaseAddr(EventRingError), 36 #[error("cannot set seg table size: {0}")] 37 SetSegTableSize(EventRingError), 38 } 39 40 type Result<T> = std::result::Result<T, Error>; 41 42 /// See spec 4.17 for interrupters. Controller can send an event back to guest kernel driver 43 /// through interrupter. 44 pub struct Interrupter { 45 interrupt_evt: Event, 46 usbsts: Register<u32>, 47 iman: Register<u32>, 48 erdp: Register<u64>, 49 event_handler_busy: bool, 50 enabled: bool, 51 moderation_interval: u16, 52 moderation_counter: u16, 53 event_ring: EventRing, 54 } 55 56 impl Interrupter { 57 /// Create a new interrupter. new(mem: GuestMemory, irq_evt: Event, regs: &XhciRegs) -> Self58 pub fn new(mem: GuestMemory, irq_evt: Event, regs: &XhciRegs) -> Self { 59 Interrupter { 60 interrupt_evt: irq_evt, 61 usbsts: regs.usbsts.clone(), 62 iman: regs.iman.clone(), 63 erdp: regs.erdp.clone(), 64 event_handler_busy: false, 65 enabled: false, 66 moderation_interval: 0, 67 moderation_counter: 0, 68 event_ring: EventRing::new(mem), 69 } 70 } 71 72 /// Returns true if event ring is empty. event_ring_is_empty(&self) -> bool73 pub fn event_ring_is_empty(&self) -> bool { 74 self.event_ring.is_empty() 75 } 76 77 /// Add event to event ring. add_event(&mut self, trb: Trb) -> Result<()>78 fn add_event(&mut self, trb: Trb) -> Result<()> { 79 self.event_ring.add_event(trb).map_err(Error::AddEvent)?; 80 self.interrupt_if_needed() 81 } 82 83 /// Send port status change trb for port. send_port_status_change_trb(&mut self, port_id: u8) -> Result<()>84 pub fn send_port_status_change_trb(&mut self, port_id: u8) -> Result<()> { 85 let mut trb = Trb::new(); 86 let psctrb = trb 87 .cast_mut::<PortStatusChangeEventTrb>() 88 .map_err(Error::CastTrb)?; 89 psctrb.set_port_id(port_id); 90 psctrb.set_completion_code(TrbCompletionCode::Success); 91 psctrb.set_trb_type(TrbType::PortStatusChangeEvent); 92 self.add_event(trb) 93 } 94 95 /// Send command completion trb. send_command_completion_trb( &mut self, completion_code: TrbCompletionCode, slot_id: u8, trb_addr: GuestAddress, ) -> Result<()>96 pub fn send_command_completion_trb( 97 &mut self, 98 completion_code: TrbCompletionCode, 99 slot_id: u8, 100 trb_addr: GuestAddress, 101 ) -> Result<()> { 102 let mut trb = Trb::new(); 103 let ctrb = trb 104 .cast_mut::<CommandCompletionEventTrb>() 105 .map_err(Error::CastTrb)?; 106 ctrb.set_trb_pointer(trb_addr.0); 107 ctrb.set_command_completion_parameter(0); 108 ctrb.set_completion_code(completion_code); 109 ctrb.set_trb_type(TrbType::CommandCompletionEvent); 110 ctrb.set_vf_id(0); 111 ctrb.set_slot_id(slot_id); 112 self.add_event(trb) 113 } 114 115 /// Send transfer event trb. send_transfer_event_trb( &mut self, completion_code: TrbCompletionCode, trb_pointer: u64, transfer_length: u32, event_data: bool, slot_id: u8, endpoint_id: u8, ) -> Result<()>116 pub fn send_transfer_event_trb( 117 &mut self, 118 completion_code: TrbCompletionCode, 119 trb_pointer: u64, 120 transfer_length: u32, 121 event_data: bool, 122 slot_id: u8, 123 endpoint_id: u8, 124 ) -> Result<()> { 125 let mut trb = Trb::new(); 126 let event_trb = trb.cast_mut::<TransferEventTrb>().map_err(Error::CastTrb)?; 127 event_trb.set_trb_pointer(trb_pointer); 128 event_trb.set_trb_transfer_length(transfer_length); 129 event_trb.set_completion_code(completion_code); 130 event_trb.set_event_data(event_data.into()); 131 event_trb.set_trb_type(TrbType::TransferEvent); 132 event_trb.set_endpoint_id(endpoint_id); 133 event_trb.set_slot_id(slot_id); 134 self.add_event(trb) 135 } 136 137 /// Enable/Disable this interrupter. set_enabled(&mut self, enabled: bool) -> Result<()>138 pub fn set_enabled(&mut self, enabled: bool) -> Result<()> { 139 usb_debug!("interrupter set enabled {}", enabled); 140 self.enabled = enabled; 141 self.interrupt_if_needed() 142 } 143 144 /// Set interrupt moderation. set_moderation(&mut self, interval: u16, counter: u16) -> Result<()>145 pub fn set_moderation(&mut self, interval: u16, counter: u16) -> Result<()> { 146 // TODO(jkwang) Moderation is not implemented yet. 147 self.moderation_interval = interval; 148 self.moderation_counter = counter; 149 self.interrupt_if_needed() 150 } 151 152 /// Set event ring seg table size. set_event_ring_seg_table_size(&mut self, size: u16) -> Result<()>153 pub fn set_event_ring_seg_table_size(&mut self, size: u16) -> Result<()> { 154 usb_debug!("interrupter set seg table size {}", size); 155 self.event_ring 156 .set_seg_table_size(size) 157 .map_err(Error::SetSegTableSize) 158 } 159 160 /// Set event ring segment table base address. set_event_ring_seg_table_base_addr(&mut self, addr: GuestAddress) -> Result<()>161 pub fn set_event_ring_seg_table_base_addr(&mut self, addr: GuestAddress) -> Result<()> { 162 usb_debug!("interrupter set table base addr {:#x}", addr.0); 163 self.event_ring 164 .set_seg_table_base_addr(addr) 165 .map_err(Error::SetSegTableBaseAddr) 166 } 167 168 /// Set event ring dequeue pointer. set_event_ring_dequeue_pointer(&mut self, addr: GuestAddress) -> Result<()>169 pub fn set_event_ring_dequeue_pointer(&mut self, addr: GuestAddress) -> Result<()> { 170 usb_debug!("interrupter set dequeue ptr addr {:#x}", addr.0); 171 self.event_ring.set_dequeue_pointer(addr); 172 self.interrupt_if_needed() 173 } 174 175 /// Set event hander busy. set_event_handler_busy(&mut self, busy: bool) -> Result<()>176 pub fn set_event_handler_busy(&mut self, busy: bool) -> Result<()> { 177 usb_debug!("set event handler busy {}", busy); 178 self.event_handler_busy = busy; 179 self.interrupt_if_needed() 180 } 181 182 /// Send and interrupt. interrupt(&mut self) -> Result<()>183 pub fn interrupt(&mut self) -> Result<()> { 184 usb_debug!("sending interrupt"); 185 self.event_handler_busy = true; 186 self.usbsts.set_bits(USB_STS_EVENT_INTERRUPT); 187 self.iman.set_bits(IMAN_INTERRUPT_PENDING); 188 self.erdp.set_bits(ERDP_EVENT_HANDLER_BUSY); 189 self.interrupt_evt.signal().map_err(Error::SendInterrupt) 190 } 191 interrupt_if_needed(&mut self) -> Result<()>192 fn interrupt_if_needed(&mut self) -> Result<()> { 193 // TODO(dverkamp): re-add !self.event_handler_busy after solving https://crbug.com/1082930 194 if self.enabled && !self.event_ring.is_empty() { 195 self.interrupt()?; 196 } 197 Ok(()) 198 } 199 } 200