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