• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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