• 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 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