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