xhci: some quirks for Intel chipsets
This commit is contained in:
parent
3e5f3fc6cd
commit
f1becafaaf
@ -519,6 +519,16 @@ impl MsiXVectorTable<'_> {
|
||||
}
|
||||
|
||||
impl<'s, S: PciConfigurationSpace + ?Sized + 's> MsiData<'s, S> {
|
||||
pub fn set_enabled(&mut self, enabled: bool) {
|
||||
let mut w0 = self.space.read_u16(self.offset + 2);
|
||||
if enabled {
|
||||
w0 |= 1 << 0;
|
||||
} else {
|
||||
w0 &= !(1 << 0);
|
||||
}
|
||||
self.space.write_u16(self.offset + 2, w0);
|
||||
}
|
||||
|
||||
pub fn register(
|
||||
&mut self,
|
||||
ic: &Arc<dyn MessageInterruptController>,
|
||||
|
@ -144,6 +144,10 @@ impl PciDeviceInfo {
|
||||
&& let Some(mut msix) = self.config_space.capability::<MsiXCapability>()
|
||||
{
|
||||
if let Ok(mut vt) = msix.vector_table() {
|
||||
if let Some(mut msi) = self.config_space.capability::<MsiCapability>() {
|
||||
msi.set_enabled(false);
|
||||
}
|
||||
|
||||
vt.mask_all();
|
||||
|
||||
msix.set_function_mask(false);
|
||||
|
@ -23,7 +23,7 @@ use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
LocalRegisterCopy,
|
||||
};
|
||||
use ygg_driver_pci::device::PciDeviceInfo;
|
||||
use ygg_driver_pci::{device::PciDeviceInfo, PciConfigurationSpace};
|
||||
use ygg_driver_usb::{
|
||||
bus::UsbBusManager,
|
||||
device::{UsbBusAddress, UsbDeviceAccess, UsbSpeed},
|
||||
@ -32,6 +32,7 @@ use ygg_driver_usb::{
|
||||
pipe::control::UsbControlPipeAccess,
|
||||
UsbHostController,
|
||||
};
|
||||
use yggdrasil_abi::bitflags;
|
||||
|
||||
use crate::{
|
||||
context::{XhciDeviceContext, XhciInputContext},
|
||||
@ -52,6 +53,13 @@ use crate::{
|
||||
util::EventBitmap,
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
pub struct Quirks: u32 {
|
||||
const INTEL: bit 0;
|
||||
const INTEL_PANTHER_POINT: bit 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
struct ScratchpadArray {
|
||||
buffers: Vec<DmaBuffer<[MaybeUninit<u8>]>>,
|
||||
@ -68,6 +76,7 @@ pub struct Xhci {
|
||||
#[allow(unused)]
|
||||
pci: PciDeviceInfo,
|
||||
pub(crate) dma: Arc<dyn DmaAllocator>,
|
||||
quirks: Quirks,
|
||||
|
||||
dcbaa: IrqSafeRwLock<DmaBuffer<[BusAddress]>>,
|
||||
#[allow(unused)]
|
||||
@ -106,10 +115,19 @@ impl Xhci {
|
||||
pci: PciDeviceInfo,
|
||||
regs: Regs,
|
||||
) -> Result<Self, UsbError> {
|
||||
let mut quirks = Quirks::empty();
|
||||
if pci.vendor_id == 0x8086 {
|
||||
quirks |= Quirks::INTEL;
|
||||
|
||||
if pci.device_id == 0x1E31 {
|
||||
quirks |= Quirks::INTEL_PANTHER_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
let mut dcbaa = DmaBuffer::new_slice(&*dma, BusAddress::ZERO, regs.slot_count + 1)
|
||||
.map_err(UsbError::MemoryError)?;
|
||||
let command_ring = CommandRing::new(&*dma, 128)?;
|
||||
let event_ring = EventRing::new(&*dma, 128)?;
|
||||
let event_ring = EventRing::new(&*dma, 64)?;
|
||||
let erst = EventRingSegmentTable::for_event_rings(&*dma, &[&event_ring])?;
|
||||
|
||||
// Setup scratch buffers
|
||||
@ -146,6 +164,18 @@ impl Xhci {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this is only needed if there's an EHCI controller as well
|
||||
if quirks.contains(Quirks::INTEL_PANTHER_POINT) {
|
||||
log::info!("quirk: intel pantherpoint xhci/ehci port switchover");
|
||||
const INTEL_USB3PSSEN: usize = 0xD8;
|
||||
const INTEL_XUSB2PR: usize = 0xD0;
|
||||
|
||||
let space = &pci.config_space;
|
||||
|
||||
space.write_u32(INTEL_USB3PSSEN, 0xFFFFFFFF);
|
||||
space.write_u32(INTEL_XUSB2PR, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
let port_slot_map = (0..regs.port_count).map(|_| AtomicU8::new(0)).collect();
|
||||
let slots = (0..regs.slot_count)
|
||||
.map(|_| IrqSafeRwLock::new(None))
|
||||
@ -155,6 +185,7 @@ impl Xhci {
|
||||
regs,
|
||||
pci,
|
||||
dma,
|
||||
quirks,
|
||||
|
||||
dcbaa: IrqSafeRwLock::new(dcbaa),
|
||||
scratchpads,
|
||||
@ -483,6 +514,13 @@ impl Device for Xhci {
|
||||
log::info!("xhci: start HC");
|
||||
op.USBCMD.modify(USBCMD::INTE::SET + USBCMD::HSEE::SET);
|
||||
op.USBCMD.modify(USBCMD::RS::SET);
|
||||
|
||||
if self.quirks.contains(Quirks::INTEL) {
|
||||
for _ in 0..100000000 {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
op.wait_usbsts_bit(USBSTS::CNR::CLEAR, 100000000)?;
|
||||
|
||||
let bus = UsbBusManager::register_bus(self.clone());
|
||||
@ -500,6 +538,7 @@ impl Device for Xhci {
|
||||
|
||||
impl InterruptHandler for Xhci {
|
||||
fn handle_irq(self: Arc<Self>, _vector: IrqVector) -> bool {
|
||||
log::info!("xhci irq");
|
||||
let status = self.regs.handle_interrupt(0);
|
||||
|
||||
if status.matches_all(USBSTS::HSE::SET) {
|
||||
|
@ -59,7 +59,7 @@ impl RuntimeRegs {
|
||||
interrupter.ERSTSZ.set(erst.capacity() as u32);
|
||||
interrupter.ERSTBA.set(erstba);
|
||||
interrupter.ERDP.set(erdp);
|
||||
interrupter.IMAN.write(IMAN::IE::SET);
|
||||
interrupter.IMAN.write(IMAN::IE::SET + IMAN::IP::SET);
|
||||
}
|
||||
|
||||
pub fn set_interrupter_dequeue_pointer(&self, index: usize, erdp: BusAddress) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user